Conversation
…e bundle support - Add EnableLocalBotAPI, TelegramBotApiId, TelegramBotApiHash, LocalBotApiPort to Config/Env - Auto-set BaseUrl and IsLocalAPI when EnableLocalBotAPI is true - Launch telegram-bot-api.exe as a ChildProcessManager-managed process in GeneralBootstrap - Add conditional Content entry for telegram-bot-api.exe in .csproj - Build telegram-bot-api from source via cmake+vcpkg in GitHub Actions push workflow Co-authored-by: ModerRAS <28183976+ModerRAS@users.noreply.github.com>
- 新增UrlDisplayService处理长URL显示 - 支持URL截断(默认80字符) - 自动提取域名和路径进行显示优化 - 支持纯URL消息检测 - 支持消息预览截断 用于解决长URL(如二维码链接)在搜索结果和消息中造成的刷屏问题 Fixes #24
📝 WalkthroughWalkthroughThis change adds a new Changes
Sequence DiagramsequenceDiagram
participant Controller as AutoQRController
participant Service as UrlDisplayService
participant SendMsg as SendMessageService
participant Bot as Telegram Bot API
Controller->>Service: IsUrlOnlyMessage(qrStr)
activate Service
Service-->>Controller: true/false
deactivate Service
alt URL Only Message
Controller->>Service: TryFormatUrlOnlyMessage(qrStr)
activate Service
Service-->>Controller: markdownLink
deactivate Service
Controller->>SendMsg: TrySendMessageWithFallback(..., disableLinkPreview=true)
activate SendMsg
SendMsg->>Bot: SendMessage with LinkPreviewOptions.Disabled
Bot-->>SendMsg: success
SendMsg-->>Controller: success
deactivate SendMsg
else Not URL Only
Controller->>SendMsg: SendMessage(qrStr)
activate SendMsg
SendMsg->>Bot: SendMessage(raw)
Bot-->>SendMsg: success
SendMsg-->>Controller: success
deactivate SendMsg
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
🔍 PR检查报告📋 检查概览
🧪 测试结果
📊 代码质量
📁 测试产物
🔗 相关链接此报告由GitHub Actions自动生成 |
Fix whitespace formatting issues detected by CI on Windows
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
TelegramSearchBot.Test/Service/Common/UrlDisplayServiceTests.cs (1)
5-36: LGTM — consider adding negative-scheme coverage.If you adopt the http(s) allowlist suggested in
UrlDisplayService, add a[Theory]coveringjavascript:alert(1),file:///etc/passwd, anddata:text/html,...returningfalsefromIsUrlOnlyMessageto lock the behavior in.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TelegramSearchBot.Test/Service/Common/UrlDisplayServiceTests.cs` around lines 5 - 36, Add a parameterized test for UrlDisplayService.IsUrlOnlyMessage that asserts it returns false for disallowed schemes; specifically add a [Theory] (with InlineData for "javascript:alert(1)", "file:///etc/passwd", "data:text/html,<svg/onload=alert(1)>") that calls _service.IsUrlOnlyMessage on each input and asserts False, so the http(s) allowlist behavior in UrlDisplayService.IsUrlOnlyMessage is locked in by test.TelegramSearchBot/Controller/AI/QR/AutoQRController.cs (1)
78-95: LGTM on the integration, one small note.The conditional formatting +
plainTextFallbackOverride: qrStr+disableLinkPreview: trueis a nice way to keep the raw URL recoverable if Markdown/HTML parsing fails. Two minor remarks:
initialContentForNewMessage: qrStr(positional arg 7) is ignored by the currentTrySendMessageWithFallbackimplementation for the non-edit path; passingqrStrhere is harmless but can be misleading to future readers.- Consider unit-testing this controller path with a mocked
ISendMessageServiceto assert both branches (URL-only vs. non-URL) produce the intended calls, since this is the user-visible behavior fixing#24.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TelegramSearchBot/Controller/AI/QR/AutoQRController.cs` around lines 78 - 95, The call to _sendMessageService.TrySendMessageWithFallback passes qrStr as the positional initialContentForNewMessage (arg 7) even though TrySendMessageWithFallback currently ignores that parameter on the non-edit path; remove the misleading positional arg (pass only named parameters or update TrySendMessageWithFallback to accept and use an initialContentForNewMessage for new messages) and add unit tests mocking ISendMessageService to assert both branches of _urlDisplayService.TryFormatUrlOnlyMessage produce the expected calls to TrySendMessageWithFallback (with plainTextFallbackOverride and disableLinkPreview) and to SendMessage respectively.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@TelegramSearchBot/Service/Common/UrlDisplayService.cs`:
- Line 9: The DefaultMaxDisplayLength constant in UrlDisplayService
(DefaultMaxDisplayLength = 60) conflicts with the PR description that specifies
an 80-character default; update the constant to 80 to match the PR/issue or, if
the intended default is 60, update the PR description/docs to state 60 —
typically change the value of DefaultMaxDisplayLength in UrlDisplayService to 80
and run related tests/usage checks to ensure consistent behavior across methods
that reference DefaultMaxDisplayLength.
- Around line 17-26: TryFormatUrlOnlyMessage currently emits the angle-bracket
link form which breaks if the URL contains '>' or whitespace; update
TryFormatUrlOnlyMessage to use the non-bracketed markdown form instead
(markdownText = $"[打开链接:{label}]({url})") after verifying the url returned by
TryGetStandaloneUrl contains no unencoded ')' (or other raw whitespace/'>') — if
such characters are present, either reject the URL (return false) or
re-encode/escape them before emitting. Keep label generation via
BuildDisplayLabel and EscapeMarkdownLinkText unchanged but add the
validation/guard against raw '>'/whitespace in the url inside
TryFormatUrlOnlyMessage.
- Around line 60-73: The TryGetStandaloneUrl method currently accepts any
absolute URI; restrict it to only allow http and https schemes by changing the
Uri.TryCreate call to capture the resulting Uri (e.g., Uri.TryCreate(trimmed,
UriKind.Absolute, out var uri)) and then verify uri.Scheme equals
Uri.UriSchemeHttp or Uri.UriSchemeHttps (case-insensitive) before returning
true; leave url = trimmed only when the scheme check passes and return false
otherwise so unsafe schemes like javascript:, file:, data:, mailto:, ftp:, etc.
are rejected.
---
Nitpick comments:
In `@TelegramSearchBot.Test/Service/Common/UrlDisplayServiceTests.cs`:
- Around line 5-36: Add a parameterized test for
UrlDisplayService.IsUrlOnlyMessage that asserts it returns false for disallowed
schemes; specifically add a [Theory] (with InlineData for "javascript:alert(1)",
"file:///etc/passwd", "data:text/html,<svg/onload=alert(1)>") that calls
_service.IsUrlOnlyMessage on each input and asserts False, so the http(s)
allowlist behavior in UrlDisplayService.IsUrlOnlyMessage is locked in by test.
In `@TelegramSearchBot/Controller/AI/QR/AutoQRController.cs`:
- Around line 78-95: The call to _sendMessageService.TrySendMessageWithFallback
passes qrStr as the positional initialContentForNewMessage (arg 7) even though
TrySendMessageWithFallback currently ignores that parameter on the non-edit
path; remove the misleading positional arg (pass only named parameters or update
TrySendMessageWithFallback to accept and use an initialContentForNewMessage for
new messages) and add unit tests mocking ISendMessageService to assert both
branches of _urlDisplayService.TryFormatUrlOnlyMessage produce the expected
calls to TrySendMessageWithFallback (with plainTextFallbackOverride and
disableLinkPreview) and to SendMessage 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 56767db2-dfdc-4221-8176-753bc2b3314b
📒 Files selected for processing (5)
TelegramSearchBot.Test/Service/Common/UrlDisplayServiceTests.csTelegramSearchBot/Controller/AI/QR/AutoQRController.csTelegramSearchBot/Interface/ISendMessageService.csTelegramSearchBot/Service/BotAPI/SendMessageService.csTelegramSearchBot/Service/Common/UrlDisplayService.cs
| namespace TelegramSearchBot.Service.Common { | ||
| [Injectable(Microsoft.Extensions.DependencyInjection.ServiceLifetime.Transient)] | ||
| public class UrlDisplayService : IService { | ||
| private const int DefaultMaxDisplayLength = 60; |
There was a problem hiding this comment.
Default truncation length disagrees with PR description.
The PR description (and linked issue context) states the default truncation is 80 characters, but DefaultMaxDisplayLength = 60. Please reconcile — either update the constant to 80 or adjust the PR description / docs to reflect 60.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@TelegramSearchBot/Service/Common/UrlDisplayService.cs` at line 9, The
DefaultMaxDisplayLength constant in UrlDisplayService (DefaultMaxDisplayLength =
60) conflicts with the PR description that specifies an 80-character default;
update the constant to 80 to match the PR/issue or, if the intended default is
60, update the PR description/docs to state 60 — typically change the value of
DefaultMaxDisplayLength in UrlDisplayService to 80 and run related tests/usage
checks to ensure consistent behavior across methods that reference
DefaultMaxDisplayLength.
| public bool TryFormatUrlOnlyMessage(string text, out string markdownText) { | ||
| markdownText = string.Empty; | ||
| if (!TryGetStandaloneUrl(text, out var url)) { | ||
| return false; | ||
| } | ||
|
|
||
| var label = EscapeMarkdownLinkText(BuildDisplayLabel(url)); | ||
| markdownText = $"[打开链接:{label}](<{url}>)"; | ||
| return true; | ||
| } |
There was a problem hiding this comment.
URL containing > or whitespace would break the [label](<url>) output.
The angle-bracket link form terminates at the first >. If the QR payload is a URI that contains %3E decoded somewhere upstream, or any character that closes the bracketed form (>, newline), the resulting Markdown is malformed. Since TryGetStandaloneUrl returns the raw trimmed text without re-encoding, consider either using the non-bracketed form [label](url) (URLs don’t contain ) unencoded) or escaping/rejecting URLs that contain >/whitespace. Minor because real http(s) URLs rarely contain raw >, but worth a defensive check.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@TelegramSearchBot/Service/Common/UrlDisplayService.cs` around lines 17 - 26,
TryFormatUrlOnlyMessage currently emits the angle-bracket link form which breaks
if the URL contains '>' or whitespace; update TryFormatUrlOnlyMessage to use the
non-bracketed markdown form instead (markdownText = $"[打开链接:{label}]({url})")
after verifying the url returned by TryGetStandaloneUrl contains no unencoded
')' (or other raw whitespace/'>') — if such characters are present, either
reject the URL (return false) or re-encode/escape them before emitting. Keep
label generation via BuildDisplayLabel and EscapeMarkdownLinkText unchanged but
add the validation/guard against raw '>'/whitespace in the url inside
TryFormatUrlOnlyMessage.
| private static bool TryGetStandaloneUrl(string text, out string url) { | ||
| url = string.Empty; | ||
| if (string.IsNullOrWhiteSpace(text)) { | ||
| return false; | ||
| } | ||
|
|
||
| var trimmed = text.Trim(); | ||
| if (!Uri.TryCreate(trimmed, UriKind.Absolute, out _)) { | ||
| return false; | ||
| } | ||
|
|
||
| url = trimmed; | ||
| return true; | ||
| } |
There was a problem hiding this comment.
Restrict TryGetStandaloneUrl to safe URL schemes.
Uri.TryCreate(..., UriKind.Absolute, ...) accepts any absolute URI, including javascript:, data:, file:, ftp:, mailto:, etc. Since a QR code payload is untrusted input and the output of this method is rendered as a clickable Markdown link sent to the chat, any non-http(s) scheme (e.g., file:///etc/passwd, javascript:...) will become a one-tap link for every chat member. Consider whitelisting http/https only.
🛡️ Proposed fix
- var trimmed = text.Trim();
- if (!Uri.TryCreate(trimmed, UriKind.Absolute, out _)) {
- return false;
- }
-
- url = trimmed;
- return true;
+ var trimmed = text.Trim();
+ if (!Uri.TryCreate(trimmed, UriKind.Absolute, out var parsed)) {
+ return false;
+ }
+ if (parsed.Scheme != Uri.UriSchemeHttp && parsed.Scheme != Uri.UriSchemeHttps) {
+ return false;
+ }
+
+ url = trimmed;
+ return true;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| private static bool TryGetStandaloneUrl(string text, out string url) { | |
| url = string.Empty; | |
| if (string.IsNullOrWhiteSpace(text)) { | |
| return false; | |
| } | |
| var trimmed = text.Trim(); | |
| if (!Uri.TryCreate(trimmed, UriKind.Absolute, out _)) { | |
| return false; | |
| } | |
| url = trimmed; | |
| return true; | |
| } | |
| private static bool TryGetStandaloneUrl(string text, out string url) { | |
| url = string.Empty; | |
| if (string.IsNullOrWhiteSpace(text)) { | |
| return false; | |
| } | |
| var trimmed = text.Trim(); | |
| if (!Uri.TryCreate(trimmed, UriKind.Absolute, out var parsed)) { | |
| return false; | |
| } | |
| if (parsed.Scheme != Uri.UriSchemeHttp && parsed.Scheme != Uri.UriSchemeHttps) { | |
| return false; | |
| } | |
| url = trimmed; | |
| return true; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@TelegramSearchBot/Service/Common/UrlDisplayService.cs` around lines 60 - 73,
The TryGetStandaloneUrl method currently accepts any absolute URI; restrict it
to only allow http and https schemes by changing the Uri.TryCreate call to
capture the resulting Uri (e.g., Uri.TryCreate(trimmed, UriKind.Absolute, out
var uri)) and then verify uri.Scheme equals Uri.UriSchemeHttp or
Uri.UriSchemeHttps (case-insensitive) before returning true; leave url = trimmed
only when the scheme check passes and return false otherwise so unsafe schemes
like javascript:, file:, data:, mailto:, ftp:, etc. are rejected.
实现Issue #24 - 二维码链接过长造成的刷屏问题
新增功能
UrlDisplayService
显示规则
URL长度阈值
截断格式
文件变更
使用场景
Fixes #24
Summary by CodeRabbit
New Features
Tests