feat(download): 搜索框支持识别资源链接#2989
Conversation
审阅者指南将 CurseForge/Modrinth 链接解析重构为可复用的辅助方法,并将“单链接识别”整合进下载搜索流程,使在搜索框中输入恰好一个资源 URL 时,能够将其解析为一个单独的搜索结果并返回对应项目,同时具备完善的错误提示与类型校验。 下载搜索中单个资源链接处理的序列图sequenceDiagram
actor User
participant DownloadSearchBox as DownloadSearch
participant ModComp
participant CompProjectStorage
participant CompRequest
participant ModDownload
participant Lang
User->>DownloadSearch: enter searchText (single CF/Modrinth link)
DownloadSearch->>ModComp: CompProjectsGet(request, task)
ModComp->>CompProjectStorage: TryExtractSingleResourceLink(request.searchText)
CompProjectStorage-->>ModComp: singleLink
ModComp->>CompProjectStorage: ResolveLinkToProjectId(singleLink)
alt CurseForge link
CompProjectStorage->>ModDownload: DlModRequest(url with slug)
ModDownload-->>CompProjectStorage: JsonObject (CF search result)
else Modrinth link
CompProjectStorage->>ModDownload: DlModRequest(url with slug)
ModDownload-->>CompProjectStorage: JsonObject (Modrinth project)
end
CompProjectStorage-->>ModComp: projectId or null
alt projectId resolved
ModComp->>CompRequest: GetCompProjectsByIds([projectId])
CompRequest-->>ModComp: CompProject or null
alt CompProject is null
ModComp->>Lang: Text(Download.Comp.Link.ResolveFailed)
Lang-->>ModComp: message
ModComp-->>DownloadSearch: throw Exception(message)
else type mismatch with request.type
ModComp->>Lang: Text(Download.Comp.List.NoMatchingResults)
Lang-->>ModComp: message
ModComp-->>DownloadSearch: throw Exception(message)
else valid single result
ModComp->>DownloadSearch: storage.results.Add(project)
ModComp->>DownloadSearch: curseForgeTotal = 0, modrinthTotal = 0
end
else projectId null or resolve error
ModComp->>Lang: Text(Download.Comp.Link.ResolveFailed)
Lang-->>ModComp: message
ModComp-->>DownloadSearch: throw Exception(message)
end
文件级变更
与关联 Issue 的符合度评估
可能相关的 Issue
提示与命令与 Sourcery 交互
自定义你的体验访问你的 dashboard 以:
获取帮助Original review guide in EnglishReviewer's GuideRefactors CurseForge/Modrinth link parsing into reusable helpers and integrates single-link detection into the download search flow so entering exactly one resource URL returns that specific project as a single search result, with proper error messaging and type validation. Sequence diagram for single resource link handling in download searchsequenceDiagram
actor User
participant DownloadSearchBox as DownloadSearch
participant ModComp
participant CompProjectStorage
participant CompRequest
participant ModDownload
participant Lang
User->>DownloadSearch: enter searchText (single CF/Modrinth link)
DownloadSearch->>ModComp: CompProjectsGet(request, task)
ModComp->>CompProjectStorage: TryExtractSingleResourceLink(request.searchText)
CompProjectStorage-->>ModComp: singleLink
ModComp->>CompProjectStorage: ResolveLinkToProjectId(singleLink)
alt CurseForge link
CompProjectStorage->>ModDownload: DlModRequest(url with slug)
ModDownload-->>CompProjectStorage: JsonObject (CF search result)
else Modrinth link
CompProjectStorage->>ModDownload: DlModRequest(url with slug)
ModDownload-->>CompProjectStorage: JsonObject (Modrinth project)
end
CompProjectStorage-->>ModComp: projectId or null
alt projectId resolved
ModComp->>CompRequest: GetCompProjectsByIds([projectId])
CompRequest-->>ModComp: CompProject or null
alt CompProject is null
ModComp->>Lang: Text(Download.Comp.Link.ResolveFailed)
Lang-->>ModComp: message
ModComp-->>DownloadSearch: throw Exception(message)
else type mismatch with request.type
ModComp->>Lang: Text(Download.Comp.List.NoMatchingResults)
Lang-->>ModComp: message
ModComp-->>DownloadSearch: throw Exception(message)
else valid single result
ModComp->>DownloadSearch: storage.results.Add(project)
ModComp->>DownloadSearch: curseForgeTotal = 0, modrinthTotal = 0
end
else projectId null or resolve error
ModComp->>Lang: Text(Download.Comp.Link.ResolveFailed)
Lang-->>ModComp: message
ModComp-->>DownloadSearch: throw Exception(message)
end
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我在这里给出了一些整体性的反馈:
- 在
TryExtractSingleResourceLink中,仅按空白字符分割可能会遗漏一些常见情况,比如链接后紧跟标点符号(,,,,), 等);建议在提取前去掉常见的结尾标点,或者使用对 URL 更友好的抽取方式,以便在自然文本中也能可靠地工作。 - 在
TryExtractSingleResourceLink和ResolveLinkToProjectId中,URL 预处理(Replace("https://", "").Replace("http://", ""))以及主机名检查是重复的;可以考虑抽取到一个共享的 helper 中(或使用Uri解析),这样能够降低未来出现不一致的风险。 ResolveLinkToProjectId中的categoryMapping字典在每次调用时都会重新分配;将其改为 static readonly 字段可以避免在频繁查询时产生不必要的分配。
供 AI Agent 使用的提示词
Please address the comments from this code review:
## Overall Comments
- 在 `TryExtractSingleResourceLink` 中,仅按空白字符分割可能会遗漏一些常见情况,比如链接后紧跟标点符号(`,`, `,`, `)`, 等);建议在提取前去掉常见的结尾标点,或者使用对 URL 更友好的抽取方式,以便在自然文本中也能可靠地工作。
- 在 `TryExtractSingleResourceLink` 和 `ResolveLinkToProjectId` 中,URL 预处理(`Replace("https://", "").Replace("http://", "")`)以及主机名检查是重复的;可以考虑抽取到一个共享的 helper 中(或使用 `Uri` 解析),这样能够降低未来出现不一致的风险。
- `ResolveLinkToProjectId` 中的 `categoryMapping` 字典在每次调用时都会重新分配;将其改为 static readonly 字段可以避免在频繁查询时产生不必要的分配。帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈来改进后续的评审。
Original comment in English
Hey - I've left some high level feedback:
- In
TryExtractSingleResourceLink, splitting only on whitespace may miss common cases like links followed by punctuation (,,,,), etc.); consider trimming common trailing punctuation or using a more URL-aware extraction so the feature works reliably in natural text. - The URL preprocessing (
Replace("https://", "").Replace("http://", "")) and host checks are duplicated betweenTryExtractSingleResourceLinkandResolveLinkToProjectId; factoring this into a shared helper (or usingUriparsing) would reduce the risk of future inconsistencies. - The
categoryMappingdictionary inResolveLinkToProjectIdis allocated on every call; making it a static readonly field would avoid unnecessary allocations on frequent searches.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `TryExtractSingleResourceLink`, splitting only on whitespace may miss common cases like links followed by punctuation (`,`, `,`, `)`, etc.); consider trimming common trailing punctuation or using a more URL-aware extraction so the feature works reliably in natural text.
- The URL preprocessing (`Replace("https://", "").Replace("http://", "")`) and host checks are duplicated between `TryExtractSingleResourceLink` and `ResolveLinkToProjectId`; factoring this into a shared helper (or using `Uri` parsing) would reduce the risk of future inconsistencies.
- The `categoryMapping` dictionary in `ResolveLinkToProjectId` is allocated on every call; making it a static readonly field would avoid unnecessary allocations on frequent searches.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
在下载页搜索框输入恰好 1 条 CurseForge/Modrinth 资源链接时,识别并将该资源作为单条结果显示;0 或多条链接照常文本搜索,解析失败或类型不符则无结果。
5d7515c to
574e437
Compare
| { | ||
| json = ModDownload.DlModRequest<JsonObject>( | ||
| $"https://api.curseforge.com/v1/mods/search?gameId=432&slug={encodedSlug}&classId={targetClassId}"); | ||
| dataArray = (JsonArray)json["data"]; |
There was a problem hiding this comment.
不建议将一个语义不同的值赋值给存在的变量,最佳实践为单开一个新的变量(如innerDatas),否则会导致阅读时的理解错误
| dataArray = (JsonArray)json["data"]; | ||
| } | ||
|
|
||
| return dataArray.Any() ? dataArray[0]["id"]?.ToString() : null; |
There was a problem hiding this comment.
按照R2239的comment修改后这里应当做出改变,包括前面if分支的逻辑
| public static string? TryExtractSingleResourceLink(string? text) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(text)) return null; | ||
| var tokens = text.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); |
| private static string? FindFirstResourceLinkToken(string? text) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(text)) return null; | ||
| foreach (var token in text.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) |
| if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps) return false; | ||
|
|
||
| // 仅取 path 段,天然忽略 ?query 与 #fragment | ||
| var segments = uri.AbsolutePath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); |
|
请尽快处理,否则按照超时关闭 |
Co-authored-by: WhiteCAT <64885812+whitecat346@users.noreply.github.com>
Co-authored-by: WhiteCAT <64885812+whitecat346@users.noreply.github.com>
集合表达式替代 new[] 写法,classId 重搜结果改用独立变量以区分语义, 并删除新增方法 XMLDoc 的额外缩进以统一注释风格。
|
改好了 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a74b8de1bf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b31c44193f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Close #2942
在下载页搜索框输入恰好 1 条 CurseForge/Modrinth 资源链接并搜索时,识别该链接并将对应资源作为单条结果显示,便于定位用关键词搜不到的资源。
Summary by Sourcery
在下载搜索框中支持识别单个 CurseForge/Modrinth 资源链接,并重构链接到项目的解析逻辑以便复用。
新功能:
增强:
Original summary in English
Summary by Sourcery
Support recognizing single CurseForge/Modrinth resource links in the download search box and refactor link-to-project resolution for reuse.
New Features:
Enhancements: