fix: v0.1.5 修复网易云/酷狗/咪咕搜索API稳定性

- 网易云: 回退到 api/search/get/web 稳定接口
- 酷狗: 回退到 format=json 不带 showtype=14 的接口
- 咪咕: 使用 searchAll 接口,兼容多种数据结构
- 统一版本号 v0.1.5,更新 README
This commit is contained in:
Koneko
2026-07-12 18:06:12 +08:00
parent abc700ecc4
commit e58beff507
4 changed files with 715 additions and 7 deletions

View File

@@ -0,0 +1,233 @@
var env = global.env || {};
var https = require('https');
var http = require('http');
var crypto = require('crypto');
var querystring = require('querystring');
// ===== 通用HTTP请求 =====
function doRequest(protocol, options, postData) {
return new Promise(function(resolve, reject) {
var client = protocol === 'https' ? https : http;
var req = client.request(options, function(res) {
var chunks = [];
res.on('data', function(chunk) { chunks.push(chunk); });
res.on('end', function() {
var buf = Buffer.concat(chunks);
var body;
try {
body = JSON.parse(buf.toString('utf8'));
} catch (e) {
body = buf.toString('utf8');
}
resolve({ body: body, statusCode: res.statusCode, headers: res.headers });
});
});
req.on('error', function(err) { reject(err); });
req.setTimeout(15000, function() { req.destroy(); reject(new Error('timeout')); });
if (postData) req.write(postData);
req.end();
});
}
function requestUrl(urlStr, method, headers, body) {
var parsed = new URL(urlStr);
var protocol = parsed.protocol.replace(':', '');
var options = {
hostname: parsed.hostname,
port: parsed.port || (protocol === 'https' ? 443 : 80),
path: parsed.pathname + parsed.search,
method: method || 'GET',
headers: headers || {}
};
var postData = null;
if (body) {
if (typeof body === 'string') {
postData = Buffer.from(body, 'utf8');
} else if (Buffer.isBuffer(body)) {
postData = body;
} else {
postData = Buffer.from(JSON.stringify(body), 'utf8');
if (!options.headers['Content-Type']) options.headers['Content-Type'] = 'application/json';
}
if (postData) options.headers['Content-Length'] = postData.length;
}
return doRequest(protocol, options, postData);
}
// ===== 格式化辅助 =====
function formatPlayTime(time) {
if (!time) return '--/--';
var m = Math.floor(time / 60);
var s = Math.floor(time % 60);
if (m === 0 && s === 0) return '--/--';
return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
}
function sizeFormate(bytes) {
if (typeof bytes === 'string') bytes = parseFloat(bytes.replace(/[^0-9.]/g, ''));
var n = parseFloat(bytes);
if (isNaN(n) || n < 0) return '0.00MB';
var mb = n / (1024 * 1024);
return mb.toFixed(2) + 'MB';
}
// ===== 搜索实现使用稳定版searchAll API =====
function musicSearch(str, page, limit) {
var searchSwitch = encodeURIComponent('{"song":1,"album":0,"singer":0,"tagSong":0,"mvSong":0,"songlist":0,"bestShow":1}');
var url = 'https://jadeite.migu.cn/music_search/v3/search/searchAll?isCorrect=0&isCopyright=1&searchSwitch=' + searchSwitch + '&pageSize=' + limit + '&text=' + encodeURIComponent(str) + '&pageNo=' + page + '&sort=0&sid=USS';
return requestUrl(url, 'GET', {
'User-Agent': 'Mozilla/5.0 (Linux; Android 10)',
'Referer': 'https://jadeite.migu.cn/music_search.html?keyword=' + encodeURIComponent(str),
'By': '7242a87651f953c07d759b1d08c62b74'
}).then(function(res) {
if (res.body && res.body.songResultData && res.body.songResultData.result) {
return res.body.songResultData.result;
}
if (res.body && res.body.musics) return res.body.musics;
throw new Error('mg search failed: ' + JSON.stringify(res.body).slice(0, 200));
});
}
function handleSearchResult(rawList) {
var list = [];
if (!rawList) return list;
for (var i = 0; i < rawList.length; i++) {
var item = rawList[i];
var qualities = {};
if (item.newRateFormats) {
for (var j = 0; j < item.newRateFormats.length; j++) {
var fmt = item.newRateFormats[j];
if (fmt.formatType === 'LQ' && fmt.size) qualities['128k'] = sizeFormate(fmt.size);
if (fmt.formatType === 'HQ' && fmt.size) qualities['320k'] = sizeFormate(fmt.size);
if (fmt.formatType === 'SQ' && fmt.size) qualities['flac'] = sizeFormate(fmt.size);
}
} else if (item.rateFormats) {
for (var j = 0; j < item.rateFormats.length; j++) {
var fmt = item.rateFormats[j];
if (fmt.formatType === 'LQ' && fmt.size) qualities['128k'] = sizeFormate(fmt.size);
if (fmt.formatType === 'HQ' && fmt.size) qualities['320k'] = sizeFormate(fmt.size);
if (fmt.formatType === 'SQ' && fmt.size) qualities['flac'] = sizeFormate(fmt.size);
}
}
var picUrl = item.img || (item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : '');
if (picUrl && picUrl.indexOf('/') === 0) picUrl = 'https://d.musicapp.migu.cn' + picUrl;
var intervalStr = item.length ? String(item.length).replace(/.*(\d\d:\d\d)$/, '$1') : '--/--';
if (!intervalStr) intervalStr = '--/--';
list.push({
id: String(item.copyrightId || item.id || ''),
name: item.title || item.songName || '',
artists: item.artist || item.singerName || '',
source: 'mg',
pic: picUrl, mPic: picUrl, sPic: picUrl,
albumName: item.album || item.albumName || '',
albumId: String(item.albumId || ''),
interval: intervalStr,
qualities: qualities
});
}
return list;
}
function search(str, page, limit, retryNum) {
if (retryNum === undefined) retryNum = 0;
if (++retryNum > 3) return Promise.reject(new Error('try max num'));
if (!limit) limit = 30;
return musicSearch(str, page, limit).then(function(rawList) {
var list = handleSearchResult(rawList);
return { list: list, allPage: page + 1, limit: limit, total: list.length * 10, source: 'mg' };
}).catch(function(err) {
if (retryNum < 3) return search(str, page, limit, retryNum);
return Promise.reject(err);
});
}
// ===== 热歌/提示搜索 =====
function hotSearch() {
return Promise.resolve({ source: 'mg', list: [] });
}
function tipSearch(str) {
return Promise.resolve({ order: [], songs: [], artists: [], albums: [], playlists: [] });
}
// ===== getUrl仅保留聆澜API =====
function getUrl(songId, quality) {
if (quality === 'standard') quality = '128k';
else if (quality === 'exhigh') quality = '320k';
else if (quality === 'lossless' || quality === 'hires' || quality === 'jymaster') quality = 'flac';
songId = String(songId || '');
quality = String(quality || '128k');
var envNow = global.env || {};
var ceruKey = envNow.ceru_key || '';
var headers = { 'User-Agent': 'QZMusic/2.0' };
if (ceruKey) headers['X-API-Key'] = ceruKey;
return requestUrl('https://source.shiqianjiang.cn/api/music/url?source=mg&songId=' + encodeURIComponent(songId) + '&quality=' + encodeURIComponent(quality), 'GET', headers)
.then(function(res) {
if (res.body && typeof res.body === 'object' && res.body.url) return res.body.url;
if (res.body && typeof res.body === 'object' && res.body.data && res.body.data.url) return res.body.data.url;
if (typeof res.body === 'string' && res.body.indexOf('http') === 0) return res.body;
return '';
}).catch(function() { return ''; });
}
// ===== 其他功能占位 =====
function getLrc(songId) { return Promise.resolve(''); }
function getPic(songId) { return Promise.resolve(''); }
// ===== 插件信息 =====
var pluginInfo = {
info: {
name: '咪咕音乐',
author: 'Koneko',
version: '0.1.5',
description: '咪咕音乐搜索 + 聆澜音源',
source: 'mg',
icon: 'https://m.music.migu.cn/favicon.ico'
},
ext: {
name: '咪咕音乐',
type: 'music',
action: 'mg',
id: 'mg',
ext: 'mg',
active: true,
useMessage: {
success: '咪咕音乐已激活',
fail: '咪咕音乐激活失败',
loading: '咪咕音乐加载中...'
},
description: {
basic: '咪咕音乐官方搜索 + 聆澜音源',
update: '修复搜索API稳定性',
author: 'Koneko'
},
entry: {
js: 'Koneko_聆澜_咪咕音乐_v0.1.5_QZv2.js'
}
},
env: [
{ name: 'ceru_key', description: '聆澜音源API密钥可选' }
],
quality: {
'128k': { name: '标准音质', size: '' },
'320k': { name: '高品音质', size: '' },
'flac': { name: '无损音质', size: '' }
},
supportFunc: ['search_song', 'search_playlist', 'playlist', 'album', 'lyric']
};
module.exports = {
musicSearch: { search: search },
tipSearch: { search: tipSearch },
hotSearch: { getList: hotSearch },
songList: { getList: function() { return Promise.resolve([]); } },
album: { getList: function() { return Promise.resolve([]); } },
leaderboard: { getList: function() { return Promise.resolve([]); } },
getUrl: getUrl,
getLrc: getLrc,
getPic: getPic,
pluginInfo: pluginInfo
};

View File

@@ -0,0 +1,253 @@
var env = global.env || {};
var WY_COOKIE = env.cookie || '';
var https = require('https');
var http = require('http');
var crypto = require('crypto');
var querystring = require('querystring');
// ===== 通用HTTP请求 =====
function doRequest(protocol, options, postData) {
return new Promise(function(resolve, reject) {
var client = protocol === 'https' ? https : http;
var req = client.request(options, function(res) {
var chunks = [];
res.on('data', function(chunk) { chunks.push(chunk); });
res.on('end', function() {
var buf = Buffer.concat(chunks);
var body;
try {
body = JSON.parse(buf.toString('utf8'));
} catch (e) {
body = buf.toString('utf8');
}
resolve({ body: body, statusCode: res.statusCode, headers: res.headers });
});
});
req.on('error', function(err) { reject(err); });
req.setTimeout(15000, function() { req.destroy(); reject(new Error('timeout')); });
if (postData) req.write(postData);
req.end();
});
}
function requestUrl(urlStr, method, headers, body) {
var parsed = new URL(urlStr);
var protocol = parsed.protocol.replace(':', '');
var options = {
hostname: parsed.hostname,
port: parsed.port || (protocol === 'https' ? 443 : 80),
path: parsed.pathname + parsed.search,
method: method || 'GET',
headers: headers || {}
};
var postData = null;
if (body) {
if (typeof body === 'string') {
postData = Buffer.from(body, 'utf8');
} else if (Buffer.isBuffer(body)) {
postData = body;
} else {
postData = Buffer.from(JSON.stringify(body), 'utf8');
if (!options.headers['Content-Type']) options.headers['Content-Type'] = 'application/json';
}
if (postData) options.headers['Content-Length'] = postData.length;
}
return doRequest(protocol, options, postData);
}
// ===== 格式化辅助 =====
function formatPlayTime(time) {
if (!time) return '--/--';
var m = Math.floor(time / 60);
var s = Math.floor(time % 60);
if (m === 0 && s === 0) return '--/--';
return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
}
function sizeFormate(bytes) {
if (typeof bytes === 'string') bytes = parseFloat(bytes.replace(/[^0-9.]/g, ''));
var n = parseFloat(bytes);
if (isNaN(n) || n < 0) return '0.00MB';
var mb = n / (1024 * 1024);
return mb.toFixed(2) + 'MB';
}
// ===== 搜索实现使用稳定版web API =====
function musicSearch(str, page, limit) {
var offset = limit * (page - 1);
var url = 'https://music.163.com/api/search/get/web?csrf_token=&hlposttag=&s=' + encodeURIComponent(str) + '&type=1&offset=' + offset + '&total=true&limit=' + limit;
return requestUrl(url, 'GET', {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Referer': 'https://music.163.com/',
'Cookie': WY_COOKIE
}).then(function(res) {
if (res.body && res.body.code === 200 && res.body.result) return res.body.result;
if (res.body && res.body.result && res.body.result.songs) return res.body.result;
throw new Error('wy search failed: ' + JSON.stringify(res.body).slice(0, 200));
});
}
function handleSearchResult(result) {
if (!result || !result.songs) return [];
var rawList = result.songs;
var list = [];
for (var i = 0; i < rawList.length; i++) {
var item = rawList[i];
var qualities = {};
if (item.l && item.l.size) qualities['128k'] = sizeFormate(item.l.size);
if (item.m && item.m.size) qualities['128k'] = sizeFormate(item.m.size);
if (item.h && item.h.size) qualities['320k'] = sizeFormate(item.h.size);
if (item.sq && item.sq.size) qualities['flac'] = sizeFormate(item.sq.size);
if (item.hr && item.hr.size) qualities['hires'] = sizeFormate(item.hr.size);
var picUrl = '';
if (item.album && item.album.picUrl) picUrl = item.album.picUrl;
else if (item.al && item.al.picUrl) picUrl = item.al.picUrl;
var artists = [];
if (item.artists) {
for (var j = 0; j < item.artists.length; j++) {
if (item.artists[j].name) artists.push(item.artists[j].name);
}
} else if (item.ar) {
for (var j = 0; j < item.ar.length; j++) {
if (item.ar[j].name) artists.push(item.ar[j].name);
}
}
list.push({
id: String(item.id),
name: item.name || '',
artists: artists.join('、'),
source: 'wy',
pic: picUrl, mPic: picUrl, sPic: picUrl,
albumName: (item.album && item.album.name) || (item.al && item.al.name) || '',
albumId: String((item.album && item.album.id) || (item.al && item.al.id) || ''),
interval: String(formatPlayTime((item.duration || item.dt || 0) / 1000) || '--/--'),
qualities: qualities
});
}
return list;
}
function search(str, page, limit, retryNum) {
if (retryNum === undefined) retryNum = 0;
if (++retryNum > 3) return Promise.reject(new Error('try max num'));
if (!limit) limit = 30;
return musicSearch(str, page, limit).then(function(result) {
var list = handleSearchResult(result);
var total = result.songCount || list.length * 10;
return { list: list, allPage: Math.ceil(total / limit), limit: limit, total: total, source: 'wy' };
}).catch(function(err) {
if (retryNum < 3) return search(str, page, limit, retryNum);
return Promise.reject(err);
});
}
// ===== 热歌/提示搜索 =====
function hotSearch() {
return requestUrl('https://music.163.com/weapi/search/hot', 'POST', {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': WY_COOKIE
}, querystring.stringify({ type: 1111 })).then(function(res) {
if (res.body && res.body.data) return { source: 'wy', list: res.body.data };
return { source: 'wy', list: [] };
}).catch(function() { return { source: 'wy', list: [] }; });
}
function tipSearch(str) {
return requestUrl('https://music.163.com/weapi/search/suggest/web', 'POST', {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': WY_COOKIE
}, querystring.stringify({ s: str })).then(function(res) {
if (res.body && res.body.result) return res.body.result;
return { order: [], songs: [], artists: [], albums: [], playlists: [] };
}).catch(function() { return { order: [], songs: [], artists: [], albums: [], playlists: [] }; });
}
// ===== getUrl仅保留聆澜API =====
function getUrl(songId, quality) {
if (quality === 'standard') quality = '128k';
else if (quality === 'exhigh') quality = '320k';
else if (quality === 'lossless' || quality === 'hires' || quality === 'jymaster') quality = 'flac';
songId = String(songId || '');
quality = String(quality || '128k');
var envNow = global.env || {};
var ceruKey = envNow.ceru_key || '';
var wyCookie = envNow.cookie || '';
var headers = { 'User-Agent': 'QZMusic/2.0' };
if (ceruKey) headers['X-API-Key'] = ceruKey;
if (wyCookie) headers['Cookie'] = wyCookie;
return requestUrl('https://source.shiqianjiang.cn/api/music/url?source=wy&songId=' + encodeURIComponent(songId) + '&quality=' + encodeURIComponent(quality), 'GET', headers)
.then(function(res) {
if (res.body && typeof res.body === 'object' && res.body.url) return res.body.url;
if (res.body && typeof res.body === 'object' && res.body.data && res.body.data.url) return res.body.data.url;
if (typeof res.body === 'string' && res.body.indexOf('http') === 0) return res.body;
return '';
})
.catch(function() { return ''; });
}
// ===== 其他功能占位 =====
function getLrc(songId) { return Promise.resolve(''); }
function getPic(songId) { return Promise.resolve(''); }
// ===== 插件信息 =====
var pluginInfo = {
info: {
name: '网易云音乐',
author: 'Koneko',
version: '0.1.5',
description: '网易云音乐搜索 + 聆澜音源',
source: 'wy',
icon: 'https://s1.music.126.net/style/favicon.ico'
},
ext: {
name: '网易云音乐',
type: 'music',
action: 'wy',
id: 'wy',
ext: 'wy',
active: true,
useMessage: {
success: '网易云音乐已激活',
fail: '网易云音乐激活失败',
loading: '网易云音乐加载中...'
},
description: {
basic: '网易云音乐官方搜索 + 聆澜音源',
update: '修复搜索API稳定性',
author: 'Koneko'
},
entry: {
js: 'Koneko_聆澜_网易云音乐_v0.1.5_QZv2.js'
}
},
env: [
{ name: 'ceru_key', description: '聆澜音源API密钥可选' },
{ name: 'cookie', description: '网易云Cookie用于搜索/每日推荐/私人FM/我喜欢的音乐等' },
{ name: 'playlist_url', description: '网易云个人主页链接,用于获取个人歌单' }
],
quality: {
'128k': { name: '标准音质', size: '' },
'320k': { name: '高品音质', size: '' },
'flac': { name: '无损音质', size: '' },
'hires': { name: 'Hi-Res', size: '' }
},
supportFunc: ['search_song', 'search_playlist', 'playlist', 'album', 'lyric']
};
module.exports = {
musicSearch: { search: search },
tipSearch: { search: tipSearch },
hotSearch: { getList: hotSearch },
songList: { getList: function() { return Promise.resolve([]); } },
album: { getList: function() { return Promise.resolve([]); } },
leaderboard: { getList: function() { return Promise.resolve([]); } },
getUrl: getUrl,
getLrc: getLrc,
getPic: getPic,
pluginInfo: pluginInfo
};

View File

@@ -0,0 +1,222 @@
var env = global.env || {};
var https = require('https');
var http = require('http');
var crypto = require('crypto');
var querystring = require('querystring');
// ===== 通用HTTP请求 =====
function doRequest(protocol, options, postData) {
return new Promise(function(resolve, reject) {
var client = protocol === 'https' ? https : http;
var req = client.request(options, function(res) {
var chunks = [];
res.on('data', function(chunk) { chunks.push(chunk); });
res.on('end', function() {
var buf = Buffer.concat(chunks);
var body;
try {
body = JSON.parse(buf.toString('utf8'));
} catch (e) {
body = buf.toString('utf8');
}
resolve({ body: body, statusCode: res.statusCode, headers: res.headers });
});
});
req.on('error', function(err) { reject(err); });
req.setTimeout(15000, function() { req.destroy(); reject(new Error('timeout')); });
if (postData) req.write(postData);
req.end();
});
}
function requestUrl(urlStr, method, headers, body) {
var parsed = new URL(urlStr);
var protocol = parsed.protocol.replace(':', '');
var options = {
hostname: parsed.hostname,
port: parsed.port || (protocol === 'https' ? 443 : 80),
path: parsed.pathname + parsed.search,
method: method || 'GET',
headers: headers || {}
};
var postData = null;
if (body) {
if (typeof body === 'string') {
postData = Buffer.from(body, 'utf8');
} else if (Buffer.isBuffer(body)) {
postData = body;
} else {
postData = Buffer.from(JSON.stringify(body), 'utf8');
if (!options.headers['Content-Type']) options.headers['Content-Type'] = 'application/json';
}
if (postData) options.headers['Content-Length'] = postData.length;
}
return doRequest(protocol, options, postData);
}
// ===== 格式化辅助 =====
function formatPlayTime(time) {
if (!time) return '--/--';
var m = Math.floor(time / 60);
var s = Math.floor(time % 60);
if (m === 0 && s === 0) return '--/--';
return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
}
function sizeFormate(bytes) {
if (typeof bytes === 'string') bytes = parseFloat(bytes.replace(/[^0-9.]/g, ''));
var n = parseFloat(bytes);
if (isNaN(n) || n < 0) return '0.00MB';
var mb = n / (1024 * 1024);
return mb.toFixed(2) + 'MB';
}
function stripEm(s) {
if (!s) return '';
return String(s).replace(/<\/?em>/g, '').replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&').trim();
}
// ===== 搜索实现使用稳定版API =====
function musicSearch(str, page, limit) {
var url = 'http://mobilecdn.kugou.com/api/v3/search/song?format=json&keyword=' + encodeURIComponent(str) + '&page=' + page + '&pagesize=' + limit;
return requestUrl(url, 'GET', {
'User-Agent': 'Mozilla/5.0 (Linux; Android 10)',
'Referer': 'http://m.kugou.com/'
}).then(function(res) {
if (res.body && res.body.data && res.body.data.info) return res.body.data.info;
throw new Error('kg search failed: ' + JSON.stringify(res.body).slice(0, 200));
});
}
function handleSearchResult(rawList) {
var list = [];
if (!rawList) return list;
for (var i = 0; i < rawList.length; i++) {
var item = rawList[i];
var qualities = {};
if (item.filesize) qualities['128k'] = sizeFormate(item.filesize);
if (item['320filesize']) qualities['320k'] = sizeFormate(item['320filesize']);
if (item.sqfilesize) qualities['flac'] = sizeFormate(item.sqfilesize);
var picUrl = '';
if (item.imgurl && typeof item.imgurl === 'string' && item.imgurl.indexOf('http') === 0) {
picUrl = item.imgurl.replace('{size}', '400');
}
if (!picUrl && item.album_img) picUrl = item.album_img;
if (!picUrl && item.img) picUrl = item.img;
list.push({
id: String(item.hash || item.audio_id || ''),
name: stripEm(item.songname || item.song_name || ''),
artists: stripEm(item.singername || item.singer_name || ''),
source: 'kg',
pic: picUrl, mPic: picUrl, sPic: picUrl,
albumName: stripEm(item.album_name || ''),
albumId: String(item.album_id || ''),
interval: String(formatPlayTime(item.duration) || '--/--'),
qualities: qualities
});
}
return list;
}
function search(str, page, limit, retryNum) {
if (retryNum === undefined) retryNum = 0;
if (++retryNum > 3) return Promise.reject(new Error('try max num'));
if (!limit) limit = 30;
return musicSearch(str, page, limit).then(function(rawList) {
var list = handleSearchResult(rawList);
return { list: list, allPage: page + 1, limit: limit, total: list.length * 10, source: 'kg' };
}).catch(function(err) {
if (retryNum < 3) return search(str, page, limit, retryNum);
return Promise.reject(err);
});
}
// ===== 热歌/提示搜索 =====
function hotSearch() {
return Promise.resolve({ source: 'kg', list: [] });
}
function tipSearch(str) {
return Promise.resolve({ order: [], songs: [], artists: [], albums: [], playlists: [] });
}
// ===== getUrl仅保留聆澜API =====
function getUrl(songId, quality) {
if (quality === 'standard') quality = '128k';
else if (quality === 'exhigh') quality = '320k';
else if (quality === 'lossless' || quality === 'hires' || quality === 'jymaster') quality = 'flac';
songId = String(songId || '');
quality = String(quality || '128k');
var envNow = global.env || {};
var ceruKey = envNow.ceru_key || '';
var headers = { 'User-Agent': 'QZMusic/2.0' };
if (ceruKey) headers['X-API-Key'] = ceruKey;
return requestUrl('https://source.shiqianjiang.cn/api/music/url?source=kg&songId=' + encodeURIComponent(songId) + '&quality=' + encodeURIComponent(quality), 'GET', headers)
.then(function(res) {
if (res.body && typeof res.body === 'object' && res.body.url) return res.body.url;
if (res.body && typeof res.body === 'object' && res.body.data && res.body.data.url) return res.body.data.url;
if (typeof res.body === 'string' && res.body.indexOf('http') === 0) return res.body;
return '';
}).catch(function() { return ''; });
}
// ===== 其他功能占位 =====
function getLrc(songId) { return Promise.resolve(''); }
function getPic(songId) { return Promise.resolve(''); }
// ===== 插件信息 =====
var pluginInfo = {
info: {
name: '酷狗音乐',
author: 'Koneko',
version: '0.1.5',
description: '酷狗音乐搜索 + 聆澜音源',
source: 'kg',
icon: 'https://www.kugou.com/favicon.ico'
},
ext: {
name: '酷狗音乐',
type: 'music',
action: 'kg',
id: 'kg',
ext: 'kg',
active: true,
useMessage: {
success: '酷狗音乐已激活',
fail: '酷狗音乐激活失败',
loading: '酷狗音乐加载中...'
},
description: {
basic: '酷狗音乐官方搜索 + 聆澜音源',
update: '修复搜索API稳定性',
author: 'Koneko'
},
entry: {
js: 'Koneko_聆澜_酷狗音乐_v0.1.5_QZv2.js'
}
},
env: [
{ name: 'ceru_key', description: '聆澜音源API密钥可选' }
],
quality: {
'128k': { name: '标准音质', size: '' },
'320k': { name: '高品音质', size: '' },
'flac': { name: '无损音质', size: '' }
},
supportFunc: ['search_song', 'search_playlist', 'playlist', 'album', 'lyric']
};
module.exports = {
musicSearch: { search: search },
tipSearch: { search: tipSearch },
hotSearch: { getList: hotSearch },
songList: { getList: function() { return Promise.resolve([]); } },
album: { getList: function() { return Promise.resolve([]); } },
leaderboard: { getList: function() { return Promise.resolve([]); } },
getUrl: getUrl,
getLrc: getLrc,
getPic: getPic,
pluginInfo: pluginInfo
};