feat: Add QQ Music as a lyric source#140
Conversation
…ual lyric search.
SafeDep Report SummaryNo dependency changes detected. Nothing to scan. This report is generated by SafeDep Github App |
Walkthrough该变更为应用添加了 QQ 音乐作为歌词源支持。包括新增 QQ 音乐 API 集成、重构歌词搜索钩子、添加歌词源选择设置界面、更新歌词服务层以支持多源搜索,并扩展了类型定义。 Changes
Sequence Diagram(s)sequenceDiagram
participant User as 用户
participant Settings as 设置界面
participant AppStore as 应用状态存储
participant LyricService as 歌词服务
participant NeteaseAPI as 网易云API
participant QQMusicAPI as QQ音乐API
User->>Settings: 选择歌词源(QQ音乐/网易云/自动)
Settings->>AppStore: 更新 lyricSource 设置
AppStore->>AppStore: 保存用户选择
User->>LyricService: 触发歌词搜索
LyricService->>LyricService: 读取 lyricSource 设置
alt source = 'auto'
LyricService->>NeteaseAPI: 并行搜索歌词
LyricService->>QQMusicAPI: 并行搜索歌词
NeteaseAPI-->>LyricService: 返回结果
QQMusicAPI-->>LyricService: 返回结果
LyricService->>LyricService: 合并结果,返回首个成功响应
else source = 'netease'
LyricService->>NeteaseAPI: 搜索歌词
NeteaseAPI-->>LyricService: 返回结果
else source = 'qqmusic'
LyricService->>QQMusicAPI: 搜索歌词
QQMusicAPI-->>LyricService: 返回结果
end
LyricService-->>User: 显示歌词搜索结果
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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 |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/hooks/stores/useAppStore.ts (1)
63-71: 旧持久化 settings 会覆盖新字段,可能导致 lyricSource 为 undefined。
当前merge是浅合并,老用户升级时settings会整体覆盖默认值,lyricSource可能丢失并影响后续逻辑。建议在 merge 时对settings进行深合并并补默认值。🛠️ 建议修复(示例)
- merge: (persistedState, currentState) => { - if (persistedState) { - return { ...currentState, ...(persistedState as Partial<AppState>) } - } + merge: (persistedState, currentState) => { + if (persistedState) { + const merged = { + ...currentState, + ...(persistedState as Partial<AppState>), + } + merged.settings = { + ...currentState.settings, + ...(persistedState as Partial<AppState>).settings, + } + if (!merged.settings.lyricSource) { + merged.settings.lyricSource = 'netease' + } + return merged + }
🤖 Fix all issues with AI agents
In `@src/lib/api/qqmusic/api.ts`:
- Around line 113-116: The conditional currently checks the return value of
parseLrc which never is falsy; update the check to verify the presence of
parsedTrans.lyrics instead: after calling const parsedTrans =
parseLrc(transLyrics), test if parsedTrans.lyrics exists/has length, and if not
return parsedRaw; ensure you reference parsedTrans and parsedRaw and leave
parseLrc usage unchanged.
🧹 Nitpick comments (5)
src/hooks/queries/lyrics/index.ts (1)
43-71: 建议移除调试日志语句。第 47 行和第 62 行的
console.log语句应该移除或转换为项目使用的 logger 工具,以保持代码库的一致性。♻️ 建议的修改
const neteaseQuery = useQuery({ queryKey: lyricsQueryKeys.manualSearch(uniqueKey, `netease-${searchQuery}`), queryFn: async () => { if (!searchQuery) return [] - console.log('Searching Netease:', searchQuery) const res = await neteaseApi.search({ keywords: searchQuery, limit: 20 })const qqMusicQuery = useQuery({ queryKey: lyricsQueryKeys.manualSearch(uniqueKey, `qq-${searchQuery}`), queryFn: async () => { if (!searchQuery) return [] - console.log('Searching QQ:', searchQuery) const res = await qqMusicApi.search(searchQuery, 20)src/lib/api/qqmusic/api.ts (3)
66-72: 可能丢失多艺术家信息。当前实现只取第一个歌手名称。对于多艺术家的歌曲,可以考虑合并所有歌手名称以提供更完整的信息。
♻️ 建议的修改
return list.map((song) => ({ source: 'qqmusic' as const, duration: song.interval, title: song.name, - artist: song.singer[0]?.name ?? 'Unknown', + artist: song.singer.map((s) => s.name).join(' / ') || 'Unknown', remoteId: song.mid, }))
158-160: 不必要的类型断言。
bestMatch来自songs数组,其remoteId已经是string类型,无需类型断言。♻️ 建议的修改
- return this.getLyrics(bestMatch.remoteId as string).map((response) => + return this.getLyrics(bestMatch.remoteId).map((response) => this.parseLyrics(response), )
46-63: 为 fetch 请求添加超时配置以防止请求长时间挂起。当前的
fetch调用在search()和getLyrics()方法中缺少超时限制。如果 QQ Music API 响应缓慢或无响应,请求会无限期地挂起。建议使用AbortSignal.timeout()为每个请求设置合理的超时时间:fetch(url, { signal: AbortSignal.timeout(5000), // 5 秒超时 // ...其他选项 })src/lib/services/lyricService.ts (1)
96-101: 错误类型语义不准确。当所有歌词提供者都失败时,使用
FileSystemError在语义上不太准确。建议使用更具描述性的错误类型(如DataParsingError或创建新的错误类型如LyricFetchError)来更清晰地表达错误的性质。♻️ 建议的修改
(e) => { // All failed // e will be an AggregateError if using Promise.any - return new FileSystemError('All lyric providers failed', { cause: e }) + return new DataParsingError('All lyric providers failed', { cause: e }) },或者考虑在
@/lib/errors中创建一个专门的LyricFetchError类型。
Summary by CodeRabbit
发行说明
新功能
优化
✏️ Tip: You can customize this high-level summary in your review settings.