feat: align with upstream 1.5.9.9

This commit is contained in:
2026-09-12 18:21:11 +08:00
commit 34f0679117
805 changed files with 376275 additions and 0 deletions
+171
View File
@@ -0,0 +1,171 @@
import {
getTxSongPlayableInfo,
TX_MUSICU_URL,
txRequest,
txSignedRequest
} from '~~/server/utils/native_tx'
import { SERVER_ERROR_CODES } from '~~/server/config/constants'
import { createApiError } from '~~/server/utils/apiError'
import {
buildQqCommentRequestParam,
normalizeQqCommentPage
} from '~~/server/utils/qqComment'
interface QqCommentListData {
Comments?: unknown
comments?: unknown
commentlist?: unknown
list?: unknown
Total?: unknown
total?: unknown
HasMore?: unknown
hasMore?: unknown
hasmore?: unknown
}
interface QqCommentModuleData extends QqCommentListData {
CommentList?: QqCommentListData
comment?: QqCommentListData
}
interface QqCommentResponse {
code?: unknown
request?: {
code?: unknown
data?: QqCommentModuleData
}
comment?: {
code?: unknown
data?: QqCommentModuleData
}
}
const getCommentListData = (response: QqCommentResponse) => {
const data = response.request?.data || response.comment?.data || {}
const list = data.CommentList || data.comment || data
return {
list,
comments: list.Comments || list.comments || list.commentlist || list.list || []
}
}
const isSuccessfulResponse = (response: QqCommentResponse | undefined) => {
if (!response || Number(response.code) !== 0) return false
const moduleCode = response.request?.code ?? response.comment?.code
return Number(moduleCode) === 0
}
export default defineEventHandler(async (event) => {
const query = getQuery(event)
const musicId = String(query.musicId || '').trim()
const originalSongId = String(query.songId || '').trim()
const cursor = String(query.cursor || '').trim()
const rawPage = Number(query.page)
const rawPageSize = Number(query.pageSize)
const page = Number.isFinite(rawPage) ? Math.max(0, Math.floor(rawPage)) : 0
const pageSize = Number.isFinite(rawPageSize)
? Math.min(50, Math.max(1, Math.floor(rawPageSize)))
: 20
const type = query.type === 'latest' ? 'latest' : 'hot'
if (!musicId) {
throw createApiError(
400,
SERVER_ERROR_CODES.COMMON_INVALID_PARAMS,
'缺少 musicId 参数'
)
}
let topid = /^\d+$/.test(originalSongId) ? originalSongId : ''
if (!topid && /^\d+$/.test(musicId)) topid = musicId
if (!topid) {
try {
const info = await getTxSongPlayableInfo(musicId)
topid = String(info.songId || '').trim()
} catch (error) {
console.error('[QQ评论] 解析歌曲 ID 失败:', error instanceof Error ? error.message : error)
throw createApiError(
502,
SERVER_ERROR_CODES.QQ_COMMENT_FETCH_FAILED,
'QQ 音乐评论获取失败'
)
}
}
if (!topid) {
throw createApiError(
400,
SERVER_ERROR_CODES.COMMON_INVALID_PARAMS,
'QQ 音乐歌曲 ID 无效'
)
}
const requestBody = {
comm: {
ct: 11,
cv: '1003006',
v: '1003006',
os_ver: '15',
phonetype: '24122RKC7C',
tmeAppID: 'qqmusiclight',
nettype: 'NETWORK_WIFI',
udid: '0',
OpenUDID: '0',
QIMEI36: '0',
uin: '0'
},
request: {
module: 'music.globalComment.CommentRead',
method: type === 'hot' ? 'GetHotCommentList' : 'GetNewCommentList',
param: buildQqCommentRequestParam({ topid, cursor, page, pageSize, type })
}
}
let response: QqCommentResponse | undefined
try {
response = (await txRequest(TX_MUSICU_URL, requestBody, {
signal: AbortSignal.timeout(8000)
})) as QqCommentResponse
} catch (error) {
console.warn('[QQ评论] 直连接口请求失败,尝试签名接口:', error)
}
if (!isSuccessfulResponse(response)) {
try {
response = (await txSignedRequest(requestBody, {
signal: AbortSignal.timeout(8000)
})) as QqCommentResponse
} catch (error) {
console.error('[QQ评论] 签名接口请求失败:', error instanceof Error ? error.message : error)
throw createApiError(
502,
SERVER_ERROR_CODES.QQ_COMMENT_FETCH_FAILED,
'QQ 音乐评论获取失败'
)
}
}
if (!isSuccessfulResponse(response)) {
throw createApiError(
502,
SERVER_ERROR_CODES.QQ_COMMENT_FETCH_FAILED,
'QQ 音乐评论获取失败'
)
}
const { list, comments: responseComments } = getCommentListData(response)
const rawComments = Array.isArray(responseComments) ? responseComments : []
const normalizedPage = normalizeQqCommentPage(rawComments)
const commentItems = normalizedPage.comments
return {
code: 200,
data: {
comments: commentItems,
orphanReplies: normalizedPage.orphanReplies,
total: Number(list.Total ?? list.total) || commentItems.length,
more: Number(list.HasMore ?? list.hasMore ?? list.hasmore) === 1,
nextCursor:
Number(list.HasMore ?? list.hasMore ?? list.hasmore) === 1
? String(rawComments.at(-1)?.SeqNo || rawComments.at(-1)?.seqNo || '')
: ''
}
}
})