From cf5d093f0b9d626ffe718b106152b72ff594b6ee Mon Sep 17 00:00:00 2001 From: miao-moe Date: Sat, 20 Jun 2026 12:44:21 +0800 Subject: [PATCH] fix(kw): robust cover field handling + official anti-server getUrl fallback --- Koneko_酷我音乐_v0.0.4.js | 93 +++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 18 deletions(-) diff --git a/Koneko_酷我音乐_v0.0.4.js b/Koneko_酷我音乐_v0.0.4.js index 34e4d6a..44648a4 100644 --- a/Koneko_酷我音乐_v0.0.4.js +++ b/Koneko_酷我音乐_v0.0.4.js @@ -47,6 +47,14 @@ function formatPlayTime(seconds) { return m + ':' + (s < 10 ? '0' : '') + s } +function safeGet(obj, keys) { + if (!obj) return '' + for (var i = 0; i < keys.length; i++) { + if (obj[keys[i]] != null) return obj[keys[i]] + } + return '' +} + var musicSearch = { limit: 30, total: 0, @@ -62,16 +70,26 @@ var musicSearch = { 'http://search.kuwo.cn/r.s?client=kt&all=' + encodeURIComponent(str) + '&pn=' + (page - 1) + '&rn=' + limit + '&uid=794762570&ver=kwplayer_ar_9.2.2.1&vipver=1&show_copyright_off=1&newver=1&ft=music&cluster=0&strategy=2012&encoding=utf8&rformat=json&vermerge=1&mobi=1&issubtitle=1', HEADERS_COMMON ).then(function(result) { - if (!result || !result.abslist || result.abslist.length === 0) { + var listData = result && result.abslist + if (!listData || listData.length === 0) { + listData = result && result.data && result.data.list + } + if (!listData || listData.length === 0) { + listData = result && result.songs + } + if (!listData || listData.length === 0) { return self.search(str, page, limit, retryNum) } var list = [] - for (var i = 0; i < result.abslist.length; i++) { - var info = result.abslist[i] - var songId = (info.MUSICRID || '').replace('MUSIC_', '') + for (var i = 0; i < listData.length; i++) { + var info = listData[i] + var musicRid = safeGet(info, ['MUSICRID', 'musicrid', 'rid', 'id', 'songid']) + var songId = musicRid ? String(musicRid).replace('MUSIC_', '') : '' + if (!songId) continue var qualities = {} - if (info.N_MINFO) { - var parts = info.N_MINFO.split(';') + var nmInfo = safeGet(info, ['N_MINFO', 'n_minfo', 'minfo']) + if (nmInfo) { + var parts = String(nmInfo).split(';') for (var j = 0; j < parts.length; j++) { var m = parts[j].match(/level:(\w+),bitrate:(\d+),format:(\w+),size:([\w.]+)/) if (m) { @@ -84,29 +102,36 @@ var musicSearch = { } } var picUrl = '' - if (info.ALBUMID) { - picUrl = 'https://img2.kuwo.cn/star/albumcover/300/' + info.ALBUMID + '.jpg' - } else { - picUrl = 'http://artistpicserver.kuwo.cn/pic.web?corp=kuwo&type=rid_pic&pictype=500&size=500&rid=' + songId + var albumId = safeGet(info, ['ALBUMID', 'albumid', 'album_id', 'AlbumID']) + if (albumId) { + picUrl = 'https://img2.kuwo.cn/star/albumcover/300/' + albumId + '.jpg' } - var artistStr = '' - if (info.ARTIST) artistStr = info.ARTIST.replace(/&/g, '、') - var duration = parseInt(info.DURATION) + if (!picUrl || picUrl === '') { + picUrl = 'http://artistpicserver.kuwo.cn/pic.web?corp=kuwo&type=rid_pic&pictype=500&size=500&rid=MUSIC_' + songId + } + var artistStr = safeGet(info, ['ARTIST', 'artist', 'singer', 'author']) + if (artistStr) artistStr = String(artistStr).replace(/&/g, '、') + var duration = parseInt(safeGet(info, ['DURATION', 'duration', 'Duration', 'time'])) || 0 + var songName = safeGet(info, ['SONGNAME', 'songname', 'name', 'Name', 'title']) + var albumName = safeGet(info, ['ALBUM', 'album', 'Album', 'album_name']) list.push({ id: String(songId), - name: String(info.SONGNAME || ''), + name: String(songName || ''), artists: artistStr, source: 'kw', pic: picUrl, mPic: picUrl, sPic: picUrl, - albumName: String(info.ALBUM || ''), - albumId: String(info.ALBUMID || ''), + albumName: String(albumName || ''), + albumId: String(albumId || ''), interval: isNaN(duration) ? '--/--' : formatPlayTime(duration), qualities: qualities }) } - self.total = parseInt(result.TOTAL) || 0 + if (list.length === 0) { + return self.search(str, page, limit, retryNum) + } + self.total = parseInt(safeGet(result, ['TOTAL', 'total', 'Total'])) || list.length self.page = page self.allPage = Math.ceil(self.total / limit) return { list: list, allPage: self.allPage, limit: limit, total: self.total, source: 'kw' } @@ -152,6 +177,7 @@ var hotSearch = { function buildApis(songId, q) { var br = mapBr(q) + var fullRid = 'MUSIC_' + songId var apis = [] if (CERU_KEY) { apis.push({ @@ -168,6 +194,24 @@ function buildApis(songId, q) { headers: { 'User-Agent': HEADERS_COMMON['User-Agent'], 'X-Request-Key': 'share-v3' }, extract: function(res) { return res && res.code === 0 && res.url ? res.url : null } }, + { + name: '官方反代', + url: 'http://antiserver.kuwo.cn/anti.s?rid=' + fullRid + '&format=mp3&type=convert_url', + headers: HEADERS_COMMON, + extract: function(res) { + if (typeof res === 'string' && res.indexOf('http') === 0) return res + return null + } + }, + { + name: '官方反代2', + url: 'http://antiserver.kuwo.cn/anti.s?type=convert_url&rid=' + fullRid + '&format=aac|mp3', + headers: HEADERS_COMMON, + extract: function(res) { + if (typeof res === 'string' && res.indexOf('http') === 0) return res + return null + } + }, { name: '星海', url: 'https://music-api.gdstudio.xyz/api.php?types=url&source=kuwo&id=' + songId + '&br=' + br, @@ -288,7 +332,20 @@ var album = { search: function(str, page, limit) { return Promise.resolve([]) } } -function getLyric(id) { return Promise.resolve('') } +function getLyric(id) { + return httpGet('http://m.kuwo.cn/newh5app/api/music/musicLyric?musicId=' + id, HEADERS_COMMON, 8000).then(function(res) { + if (res && res.data && res.data.lrc) return { lrc: res.data.lrc } + if (res && res.lrclist) { + var lrc = '' + for (var i = 0; i < res.lrclist.length; i++) { + var t = res.lrclist[i] + lrc += '[' + t.time + ']' + (t.lineLyric || t.content || '') + '\n' + } + return { lrc: lrc } + } + return '' + }).catch(function(e) { return '' }) +} function getPic(songId) { return Promise.resolve('') } function musicDetail(id) { return Promise.resolve(null) } function musicInfo(id) { return Promise.resolve(null) }