From 9ae7e0a540f586414d5752c393de7482e0188336 Mon Sep 17 00:00:00 2001 From: TRAE Bot Date: Sun, 5 Jul 2026 12:03:44 +0000 Subject: [PATCH] =?UTF-8?q?chore:=20reorganize=20repo=20-=20/=E8=81=86?= =?UTF-8?q?=E6=BE=9C=20for=20v0.1.0=20plugins,=20/=E6=97=A7=E7=89=88?= =?UTF-8?q?=E5=AD=98=E6=A1=A3=20for=20legacy=20v0.0.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Koneko_聆澜_GIT音源_v0.0.3_QZv2.js | 223 ----------- Koneko_聆澜_QQ音乐_v0.0.3_QZv2.js | 324 ---------------- Koneko_聆澜_咪咕音乐_v0.0.3_QZv2.js | 210 ---------- Koneko_聆澜_网易云音乐_v0.0.3_QZv2.js | 362 ------------------ Koneko_聆澜_酷我音乐_v0.0.3_QZv2.js | 199 ---------- Koneko_聆澜_酷狗音乐_v0.0.3_QZv2.js | 210 ---------- .../Koneko_GIT音源_v0.0.2.js | 0 .../Koneko_QQ音乐_v0.0.2.js | 0 .../Koneko_咪咕音乐_v0.0.2.js | 0 .../Koneko_网易云音乐_v0.0.2.js | 0 .../Koneko_酷我音乐_v0.0.2.js | 0 .../Koneko_酷狗音乐_v0.0.2.js | 0 .../Koneko_聆澜_GIT音源_v0.1.0_QZv2.js | 0 .../Koneko_聆澜_QQ音乐_v0.1.0_QZv2.js | 0 .../Koneko_聆澜_咪咕音乐_v0.1.0_QZv2.js | 0 .../Koneko_聆澜_网易云音乐_v0.1.0_QZv2.js | 0 .../Koneko_聆澜_酷我音乐_v0.1.0_QZv2.js | 0 .../Koneko_聆澜_酷狗音乐_v0.1.0_QZv2.js | 0 18 files changed, 1528 deletions(-) delete mode 100644 Koneko_聆澜_GIT音源_v0.0.3_QZv2.js delete mode 100644 Koneko_聆澜_QQ音乐_v0.0.3_QZv2.js delete mode 100644 Koneko_聆澜_咪咕音乐_v0.0.3_QZv2.js delete mode 100644 Koneko_聆澜_网易云音乐_v0.0.3_QZv2.js delete mode 100644 Koneko_聆澜_酷我音乐_v0.0.3_QZv2.js delete mode 100644 Koneko_聆澜_酷狗音乐_v0.0.3_QZv2.js rename Koneko_GIT音源_v0.0.2.js => 旧版存档/Koneko_GIT音源_v0.0.2.js (100%) rename Koneko_QQ音乐_v0.0.2.js => 旧版存档/Koneko_QQ音乐_v0.0.2.js (100%) rename Koneko_咪咕音乐_v0.0.2.js => 旧版存档/Koneko_咪咕音乐_v0.0.2.js (100%) rename Koneko_网易云音乐_v0.0.2.js => 旧版存档/Koneko_网易云音乐_v0.0.2.js (100%) rename Koneko_酷我音乐_v0.0.2.js => 旧版存档/Koneko_酷我音乐_v0.0.2.js (100%) rename Koneko_酷狗音乐_v0.0.2.js => 旧版存档/Koneko_酷狗音乐_v0.0.2.js (100%) rename Koneko_聆澜_GIT音源_v0.1.0_QZv2.js => 聆澜/Koneko_聆澜_GIT音源_v0.1.0_QZv2.js (100%) rename Koneko_聆澜_QQ音乐_v0.1.0_QZv2.js => 聆澜/Koneko_聆澜_QQ音乐_v0.1.0_QZv2.js (100%) rename Koneko_聆澜_咪咕音乐_v0.1.0_QZv2.js => 聆澜/Koneko_聆澜_咪咕音乐_v0.1.0_QZv2.js (100%) rename Koneko_聆澜_网易云音乐_v0.1.0_QZv2.js => 聆澜/Koneko_聆澜_网易云音乐_v0.1.0_QZv2.js (100%) rename Koneko_聆澜_酷我音乐_v0.1.0_QZv2.js => 聆澜/Koneko_聆澜_酷我音乐_v0.1.0_QZv2.js (100%) rename Koneko_聆澜_酷狗音乐_v0.1.0_QZv2.js => 聆澜/Koneko_聆澜_酷狗音乐_v0.1.0_QZv2.js (100%) diff --git a/Koneko_聆澜_GIT音源_v0.0.3_QZv2.js b/Koneko_聆澜_GIT音源_v0.0.3_QZv2.js deleted file mode 100644 index 2cfa116..0000000 --- a/Koneko_聆澜_GIT音源_v0.0.3_QZv2.js +++ /dev/null @@ -1,223 +0,0 @@ -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(seconds) { - if (!seconds) return '00:00'; - var m = Math.floor(seconds / 60); - var s = Math.floor(seconds % 60); - return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s); -} - -// ===== Git音源配置 ===== -var GITCODE_CONFIG = { owner: 'ikun_0014', repo: 'music', token: 'WzsER9knWNgC_4tjeJCtHKcN' }; -function getGitcodeUrl() { - return 'https://api.gitcode.com/api/v5/repos/' + GITCODE_CONFIG.owner + '/' + GITCODE_CONFIG.repo + '/raw/audio_database.json?access_token=' + GITCODE_CONFIG.token; -} -var cachedList = null; -var cacheTime = 0; -var CACHE_TTL = 5 * 60 * 1000; - -function fetchAllGitMusic() { - var now = Date.now(); - if (cachedList && now - cacheTime < CACHE_TTL) return Promise.resolve(cachedList); - return requestUrl(getGitcodeUrl(), 'GET', { 'User-Agent': 'Mozilla/5.0' }).then(function(res) { - var body = Array.isArray(res.body) ? res.body : []; - var list = []; - for (var i = 0; i < body.length; i++) list.push(formatGitItem(body[i])); - cachedList = list; - cacheTime = now; - return list; - }); -} - -function formatGitItem(item) { - var qualities = {}; - var fmt = (item.format || '').toLowerCase(); - if (fmt === 'flac' && item.filesize) qualities.lossless = String(item.filesize); - else if (fmt === 'mp3' && item.filesize) qualities.exhigh = String(item.filesize); - else if (item.filesize) qualities.standard = String(item.filesize); - var picUrl = item.img || ''; - return { - id: item.relative_path || '', - name: item.title || item.filename || '', - artists: item.artist || '未知歌手', - source: 'git', - pic: picUrl, - mPic: picUrl, - sPic: picUrl, - albumName: item.album || '未知专辑', - albumId: '', - interval: '', - qualities: qualities, - _gitcodeData: item - }; -} - -// ===== 搜索实现 ===== -function musicSearch(str, page, limit) { - return fetchAllGitMusic().then(function(list) { - var regexStr = str.split('').map(function(c) { return c.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }).join('.*'); - var regex = new RegExp(regexStr, 'i'); - var filtered = []; - for (var i = 0; i < list.length; i++) { - var item = list[i]; - if (regex.test(item.artists) || regex.test(item.name) || regex.test(item.albumName)) filtered.push(item); - } - var start = (page - 1) * limit; - return { data: filtered.slice(start, start + limit), total: filtered.length }; - }); -} - -function handleSearchResult(result) { - return result.data || []; -} - -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); - return { list: list, allPage: Math.ceil(result.total / limit), limit: limit, total: result.total, source: 'git' }; - }); -} - -// ===== 播放链接 ===== -function getUrl(songInfo, type) { - var q = type || '128k'; - var songId = songInfo.id || ''; - if (!songId) return Promise.resolve(''); - var ceruKey = process.env.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=git&songId=' + encodeURIComponent(songId) + '&quality=' + encodeURIComponent(q), '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 getPic(songInfo) { - if (songInfo.pic) return Promise.resolve(songInfo.pic); - return Promise.resolve(''); -} - -// ===== 歌词 ===== -function getLyric(songInfo) { - if (songInfo._gitcodeData && songInfo._gitcodeData.lyrics) return Promise.resolve(songInfo._gitcodeData.lyrics); - return Promise.resolve(''); -} - -// ===== 音乐详情 ===== -function musicDetail(songmid) { - return Promise.resolve(null); -} -function musicInfo(songmid) { return musicDetail(songmid); } - -// ===== 热搜 ===== -function hotSearch() { return Promise.resolve({ source: 'git', list: [] }); } - -// ===== 搜索建议 ===== -function tipSearch(str) { return Promise.resolve({ order: [], songs: [], artists: [], albums: [], playlists: [] }); } - -// ===== 榜单 ===== -function leaderboard() { return Promise.resolve([]); } - -// ===== 歌单 ===== -function songList() { return Promise.resolve({ list: [], total: 0, page: 1, source: 'git' }); } - -// ===== 歌手 ===== -function singer() { return Promise.resolve({ source: 'git', list: [], total: 0 }); } - -// ===== 专辑 ===== -function album() { return Promise.resolve({ source: 'git', list: [], total: 0 }); } - -// ===== 插件信息 ===== -var pluginInfo = { - info: { - id: 'koneko_ceru_git', - name: 'GIT音源 - Koneko 聆澜', - version: '0.0.3', - source: 'git', - description: 'GIT音源,基于 CeruMusic musicSdk 搜索 + Ceru 播放接口' - }, - ext: [], - env: [{ key: 'ceru_key', name: 'Ceru API Key', description: '聆澜播放接口密钥' }], - quality: [ - { name: '标准', ui: '标', id: '128k' }, - { name: '高品', ui: 'HQ', id: '320k' }, - { name: '无损', ui: 'SQ', id: 'flac' } - ], - supportFunc: [] -} - -module.exports = { - musicSearch: { search: search }, - tipSearch: { search: tipSearch }, - hotSearch: { getList: hotSearch }, - leaderboard: { getBoards: leaderboard }, - songList: songList, - artists: singer, - album: album, - getLyric: getLyric, - getPic: getPic, - getUrl: getUrl, - musicDetail: musicDetail, - musicInfo: musicInfo, - pluginInfo: pluginInfo -}; diff --git a/Koneko_聆澜_QQ音乐_v0.0.3_QZv2.js b/Koneko_聆澜_QQ音乐_v0.0.3_QZv2.js deleted file mode 100644 index 3d36797..0000000 --- a/Koneko_聆澜_QQ音乐_v0.0.3_QZv2.js +++ /dev/null @@ -1,324 +0,0 @@ -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); -} - -// ===== QQ音乐zzcSign ===== -var PART_1_INDEXES = [23, 14, 6, 36, 16, 40, 7, 19]; -var PART_2_INDEXES = [16, 1, 32, 12, 19, 27, 8, 5]; -var SCRAMBLE_VALUES = [89, 39, 179, 150, 218, 82, 58, 252, 177, 52, 186, 123, 120, 64, 242, 133, 143, 161, 121, 179]; -function hashSHA1(text) { - return crypto.createHash('sha1').update(Buffer.from(text, 'utf-8')).digest().toString('hex').toUpperCase(); -} -function pickHashByIdx(hash, indexes) { - var out = ''; - for (var i = 0; i < indexes.length; i++) out += hash[indexes[i]]; - return out; -} -function base64Encode(data) { - var buf; - if (typeof data === 'string') buf = Buffer.from(data); - else if (Array.isArray(data)) buf = Buffer.from(data); - else buf = data; - return buf.toString('base64').replace(/[\\/+=]/g, ''); -} -function zzcSign(text) { - var hash = hashSHA1(text); - var part1 = pickHashByIdx(hash, PART_1_INDEXES); - var part2 = pickHashByIdx(hash, PART_2_INDEXES); - var part3 = []; - for (var i = 0; i < SCRAMBLE_VALUES.length; i++) { - part3.push(SCRAMBLE_VALUES[i] ^ parseInt(hash.slice(i * 2, i * 2 + 2), 16)); - } - var b64Part = base64Encode(part3).replace(/[\\/+=]/g, ''); - return ('zzc' + part1 + b64Part + part2).toLowerCase(); -} -function randomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; -} -function getSearchId() { - var e = randomInt(1, 20); - var t = Number(e * Number('18014398509481984').toFixed()); - var n = randomInt(0, 4194304) * 4294967296; - var a = Date.now(); - var r = Math.round(a * 1000) % (24 * 60 * 60 * 1000); - return String(t + n + r); -} -function signRequest(data) { - var sign = zzcSign(JSON.stringify(data)); - return requestUrl('https://u.y.qq.com/cgi-bin/musics.fcg?sign=' + encodeURIComponent(sign), 'POST', { - 'User-Agent': 'QQMusic 14090508(android 12)', - 'Content-Type': 'application/json' - }, JSON.stringify(data)); -} - -function formatPlayTime(seconds) { - if (!seconds) return '00:00'; - var m = Math.floor(seconds / 60); - var s = Math.floor(seconds % 60); - return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s); -} - -// ===== 搜索实现 ===== -function musicSearch(str, page, limit) { - var body = { - comm: { ct: '11', cv: '14090508', v: '14090508', tmeAppID: 'qqmusic', phonetype: 'EBG-AN10', deviceScore: '553.47', devicelevel: '50', newdevicelevel: '20', rom: 'HuaWei/EMOTION/EmotionUI_14.2.0', os_ver: '12', OpenUDID: '0', OpenUDID2: '0', QIMEI36: '0', udid: '0', chid: '0', aid: '0', oaid: '0', taid: '0', tid: '0', wid: '0', uid: '0', sid: '0', modeSwitch: '6', teenMode: '0', ui_mode: '2', nettype: '1020', v4ip: '' }, - req: { module: 'music.search.SearchCgiService', method: 'DoSearchForQQMusicMobile', param: { search_type: 0, searchid: getSearchId(), query: str, page_num: page, num_per_page: limit, highlight: 0, nqc_flag: 0, multi_zhida: 0, cat: 2, grp: 1, sin: 0, sem: 0 } } - }; - return signRequest(body).then(function(res) { - if (res.body && res.body.code === 0 && res.body.req && res.body.req.code === 0) return res.body.req.data; - throw new Error('tx search failed'); - }); -} - -function handleSearchResult(rawList) { - var list = []; - for (var i = 0; i < rawList.length; i++) { - var item = rawList[i]; - if (!item.file || !item.file.media_mid) continue; - var qualities = {}; - if (item.file.size_128mp3) qualities.standard = String(item.file.size_128mp3); - if (item.file.size_320mp3) qualities.exhigh = String(item.file.size_320mp3); - if (item.file.size_flac) qualities.lossless = String(item.file.size_flac); - if (item.file.size_hires) qualities.hires = String(item.file.size_hires); - var albumId = ''; - var albumName = ''; - if (item.album) { albumName = item.album.name; albumId = item.album.mid; } - var singerName = ''; - if (item.singer && item.singer.length) { - var ns = []; - for (var j = 0; j < item.singer.length; j++) ns.push(item.singer[j].name); - singerName = ns.join('、'); - } - var picUrl = albumId ? 'https://y.gtimg.cn/music/photo_new/T002R500x500M000' + albumId + '.jpg' : (item.singer && item.singer.length ? 'https://y.gtimg.cn/music/photo_new/T001R500x500M000' + item.singer[0].mid + '.jpg' : ''); - list.push({ - id: item.mid, - name: item.name + (item.title_extra || ''), - artists: singerName, - source: 'tx', - pic: picUrl, - mPic: picUrl, - sPic: picUrl, - albumName: albumName, - albumId: albumId, - interval: formatPlayTime(item.interval), - 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(data) { - if (!data || !data.body || !data.body.item_song) return search(str, page, limit, retryNum); - var list = handleSearchResult(data.body.item_song); - var meta = data.meta || {}; - var total = meta.estimate_sum || 0; - return { list: list, allPage: Math.ceil(total / limit), limit: limit, total: total, source: 'tx' }; - }); -} - -// ===== 播放链接 ===== -function getUrl(songInfo, type) { - var q = type || '128k'; - var songId = songInfo.id || ''; - var ceruKey = process.env.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=tx&songId=' + encodeURIComponent(songId) + '&quality=' + encodeURIComponent(q), '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 getPic(songInfo) { - if (songInfo.pic) return Promise.resolve(songInfo.pic); - var albumId = songInfo.albumId || ''; - if (albumId) return Promise.resolve('https://y.gtimg.cn/music/photo_new/T002R500x500M000' + albumId + '.jpg'); - return Promise.resolve(''); -} - -// ===== 歌词 ===== -function getLyric(songInfo) { - var songmid = songInfo.id || ''; - return requestUrl('https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?format=json&nobase64=1&songmid=' + encodeURIComponent(songmid), 'GET', { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 10)', - 'Referer': 'https://y.qq.com/portal/player.html' - }).then(function(res) { - if (typeof res.body === 'string') { - try { var obj = JSON.parse(res.body.replace(/^MusicJsonCallback\(/, '').replace(/\)$/, '')); return obj.lyric || ''; } catch(e) {} - } - if (res.body && res.body.lyric) return res.body.lyric; - return ''; - }).catch(function() { return ''; }); -} - -// ===== 音乐详情 ===== -function musicDetail(songmid) { - var data = { - comm: { ct: '11', cv: '14090508', v: '14090508', tmeAppID: 'qqmusic' }, - req: { module: 'music.pf_song_detail_svr', method: 'get_song_detail_yqq', param: { song_mid: songmid } } - }; - return signRequest(data).then(function(res) { - if (res.body && res.body.req && res.body.req.data && res.body.req.data.info && res.body.req.data.info.track_info) { - var t = res.body.req.data.info.track_info; - var albumId = t.album ? t.album.mid : ''; - var singerName = ''; - if (t.singer && t.singer.length) { var ns = []; for (var j = 0; j < t.singer.length; j++) ns.push(t.singer[j].name); singerName = ns.join('、'); } - var picUrl = albumId ? 'https://y.gtimg.cn/music/photo_new/T002R500x500M000' + albumId + '.jpg' : ''; - return { - id: t.mid, - name: t.name, - artists: singerName, - source: 'tx', - pic: picUrl, - mPic: picUrl, - sPic: picUrl, - albumName: t.album ? t.album.name : '', - albumId: albumId, - interval: formatPlayTime(t.interval), - qualities: {} - }; - } - return null; - }).catch(function() { return null; }); -} - -function musicInfo(songmid) { return musicDetail(songmid); } - -// ===== 热搜 ===== -function hotSearch() { - var data = { - comm: { ct: '19', cv: '1803', guid: '0', patch: '118', psrf_access_token_expiresAt: 0, psrf_qqaccess_token: '', psrf_qqopenid: '', psrf_qqunionid: '', tmeAppID: 'qqmusic', tmeLoginType: 0, uin: '0', wid: '0' }, - hotkey: { method: 'GetHotkeyForQQMusicPC', module: 'tencent_musicsoso_hotkey.HotkeyService', param: { search_id: '', uin: 0 } } - }; - return requestUrl('https://u.y.qq.com/cgi-bin/musicu.fcg', 'POST', { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 10)', - 'Referer': 'https://y.qq.com/portal/player.html', - 'Content-Type': 'application/json' - }, JSON.stringify(data)).then(function(res) { - var list = []; - if (res.body && res.body.hotkey && res.body.hotkey.data && res.body.hotkey.data.vec_hotkey) { - var arr = res.body.hotkey.data.vec_hotkey; - for (var i = 0; i < arr.length; i++) list.push(arr[i].query); - } - return { source: 'tx', list: list }; - }).catch(function() { return { source: 'tx', list: [] }; }); -} - -// ===== 搜索建议 ===== -function tipSearch(str) { - return Promise.resolve({ order: [], songs: [], artists: [], albums: [], playlists: [] }); -} - -// ===== 榜单 ===== -function leaderboard() { - return Promise.resolve([]); -} - -// ===== 歌单 ===== -function songList() { - return Promise.resolve({ list: [], total: 0, page: 1, source: 'tx' }); -} - -// ===== 歌手 ===== -function singer() { - return Promise.resolve({ source: 'tx', list: [], total: 0 }); -} - -// ===== 专辑 ===== -function album() { - return Promise.resolve({ source: 'tx', list: [], total: 0 }); -} - -// ===== 插件信息 ===== -var pluginInfo = { - info: { - id: 'koneko_ceru_tx', - name: 'QQ音乐 - Koneko 聆澜', - version: '0.0.3', - source: 'tx', - description: 'QQ音乐音源,基于 CeruMusic musicSdk 搜索 + Ceru 播放接口' - }, - ext: [], - env: [{ key: 'ceru_key', name: 'Ceru API Key', description: '聆澜播放接口密钥' }], - quality: [ - { name: '标准', ui: '标', id: '128k' }, - { name: '高品', ui: 'HQ', id: '320k' }, - { name: '无损', ui: 'SQ', id: 'flac' } - ], - supportFunc: [] -} - -module.exports = { - musicSearch: { search: search }, - tipSearch: { search: tipSearch }, - hotSearch: { getList: hotSearch }, - leaderboard: { getBoards: leaderboard }, - songList: songList, - artists: singer, - album: album, - getLyric: getLyric, - getPic: getPic, - getUrl: getUrl, - musicDetail: musicDetail, - musicInfo: musicInfo, - pluginInfo: pluginInfo -}; diff --git a/Koneko_聆澜_咪咕音乐_v0.0.3_QZv2.js b/Koneko_聆澜_咪咕音乐_v0.0.3_QZv2.js deleted file mode 100644 index 833f640..0000000 --- a/Koneko_聆澜_咪咕音乐_v0.0.3_QZv2.js +++ /dev/null @@ -1,210 +0,0 @@ -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(seconds) { - if (!seconds) return '00:00'; - var m = Math.floor(seconds / 60); - var s = Math.floor(seconds % 60); - return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s); -} - -// ===== 搜索实现 ===== -function musicSearch(str, page, limit) { - var url = 'https://jadeite.migu.cn/music_search/v3/search?text=' + encodeURIComponent(str) + '&pageNo=' + page + '&pageSize=' + limit + '&searchSwitch={"song":1}'; - 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.musics) return res.body.musics; - throw new Error('mg search failed'); - }); -} - -function handleSearchResult(rawList) { - var 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 === 'SQ' && fmt.size) qualities.lossless = String(fmt.size); - if (fmt.formatType === 'HQ' && fmt.size) qualities.exhigh = String(fmt.size); - if (fmt.formatType === 'LQ' && fmt.size) qualities.standard = String(fmt.size); - } - } - var picUrl = item.img || (item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : ''); - if (picUrl && picUrl.startsWith('/')) picUrl = 'https://d.musicapp.migu.cn' + picUrl; - list.push({ - id: 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: item.albumId || '', - interval: item.length ? item.length.replace(/.*(\d\d:\d\d)$/, '$1') : '', - 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' }; - }); -} - -// ===== 播放链接 ===== -function getUrl(songInfo, type) { - var q = type || '128k'; - var songId = songInfo.id || ''; - var ceruKey = process.env.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(q), '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 getPic(songInfo) { - if (songInfo.pic) return Promise.resolve(songInfo.pic); - return Promise.resolve(''); -} - -// ===== 歌词 ===== -function getLyric(songInfo) { - var copyrightId = songInfo.id || ''; - if (!copyrightId) return Promise.resolve(''); - return requestUrl('http://music.migu.cn/v3/api/music/audioPlayer/getLyric?copyrightId=' + encodeURIComponent(copyrightId), 'GET', { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 10)', - 'Referer': 'http://music.migu.cn/v3/music/player/audio?from=migu' - }).then(function(res) { - if (res.body && res.body.lyric) return res.body.lyric; - return ''; - }).catch(function() { return ''; }); -} - -// ===== 音乐详情 ===== -function musicDetail(songmid) { - return Promise.resolve(null); -} -function musicInfo(songmid) { return musicDetail(songmid); } - -// ===== 热搜 ===== -function hotSearch() { return Promise.resolve({ source: 'mg', list: [] }); } - -// ===== 搜索建议 ===== -function tipSearch(str) { return Promise.resolve({ order: [], songs: [], artists: [], albums: [], playlists: [] }); } - -// ===== 榜单 ===== -function leaderboard() { return Promise.resolve([]); } - -// ===== 歌单 ===== -function songList() { return Promise.resolve({ list: [], total: 0, page: 1, source: 'mg' }); } - -// ===== 歌手 ===== -function singer() { return Promise.resolve({ source: 'mg', list: [], total: 0 }); } - -// ===== 专辑 ===== -function album() { return Promise.resolve({ source: 'mg', list: [], total: 0 }); } - -// ===== 插件信息 ===== -var pluginInfo = { - info: { - id: 'koneko_ceru_mg', - name: '咪咕音乐 - Koneko 聆澜', - version: '0.0.3', - source: 'mg', - description: '咪咕音乐音源,基于 CeruMusic musicSdk 搜索 + Ceru 播放接口' - }, - ext: [], - env: [{ key: 'ceru_key', name: 'Ceru API Key', description: '聆澜播放接口密钥' }], - quality: [ - { name: '标准', ui: '标', id: '128k' }, - { name: '高品', ui: 'HQ', id: '320k' }, - { name: '无损', ui: 'SQ', id: 'flac' } - ], - supportFunc: [] -} - -module.exports = { - musicSearch: { search: search }, - tipSearch: { search: tipSearch }, - hotSearch: { getList: hotSearch }, - leaderboard: { getBoards: leaderboard }, - songList: songList, - artists: singer, - album: album, - getLyric: getLyric, - getPic: getPic, - getUrl: getUrl, - musicDetail: musicDetail, - musicInfo: musicInfo, - pluginInfo: pluginInfo -}; diff --git a/Koneko_聆澜_网易云音乐_v0.0.3_QZv2.js b/Koneko_聆澜_网易云音乐_v0.0.3_QZv2.js deleted file mode 100644 index fe7d93c..0000000 --- a/Koneko_聆澜_网易云音乐_v0.0.3_QZv2.js +++ /dev/null @@ -1,362 +0,0 @@ -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); -} - -// ===== 网易云eapi加密 ===== -var EAPI_KEY = 'e82ckenh8dichen8'; -function aesEncryptEapi(text) { - var cipher = crypto.createCipheriv('aes-128-ecb', EAPI_KEY, ''); - var encrypted = cipher.update(text, 'utf8', 'base64'); - encrypted += cipher.final('base64'); - return encrypted; -} -function eapi(url, params) { - var payload = JSON.stringify({ - method: 'POST', - url: url, - params: params - }); - return { params: aesEncryptEapi(payload) }; -} - -// ===== weapi加密(简化版,用于歌词等) ===== -var WEAPI_IV = '0102030405060708'; -var WEAPI_PRESET_KEY = '0CoJUm6Qyw8W8jud'; -var WEAPI_RSA_PUBKEY = '010001'; -var WEAPI_RSA_MODULUS = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'; -function aesEncryptWeapi(text, key) { - var cipher = crypto.createCipheriv('aes-128-cbc', key, WEAPI_IV); - var encrypted = cipher.update(text, 'utf8', 'base64'); - encrypted += cipher.final('base64'); - return encrypted; -} -function rsaEncryptWeapi(text) { - var reversed = text.split('').reverse().join(''); - var input = Buffer.from(reversed, 'utf8').toString('hex'); - var bigInput = BigInt('0x' + input); - var bigExp = BigInt('0x' + WEAPI_RSA_PUBKEY); - var bigMod = BigInt('0x' + WEAPI_RSA_MODULUS); - var bigResult = 1n; - var e = bigExp; - var b = bigInput; - while (e > 0n) { - if (e % 2n === 1n) bigResult = (bigResult * b) % bigMod; - b = (b * b) % bigMod; - e = e / 2n; - } - var result = bigResult.toString(16).padStart(256, '0'); - return result; -} -function weapi(params) { - var text = JSON.stringify(params); - var secretKey = ''; - for (var i = 0; i < 16; i++) secretKey += String.fromCharCode(97 + Math.floor(Math.random() * 25)); - var encrypted = aesEncryptWeapi(aesEncryptWeapi(text, WEAPI_PRESET_KEY), secretKey); - var encSecKey = rsaEncryptWeapi(secretKey); - return { params: encrypted, encSecKey: encSecKey }; -} - -// ===== 格式化辅助 ===== -function formatPlayTime(seconds) { - var m = Math.floor(seconds / 60); - var s = Math.floor(seconds % 60); - return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s); -} - -function formatSingerName(arr, key) { - if (!arr || !arr.length) return ''; - var names = []; - for (var i = 0; i < arr.length; i++) names.push(arr[i][key] || arr[i]); - return names.join('、'); -} - -// ===== 搜索实现 ===== -function musicSearch(str, page, limit) { - var form = eapi('/api/search/song/list/page', { - keyword: str, - needCorrect: '1', - channel: 'typing', - offset: limit * (page - 1), - scene: 'normal', - total: page == 1, - limit: limit - }); - return requestUrl('http://interface3.music.163.com/eapi/search/song/list/page', 'POST', { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', - 'Origin': 'https://music.163.com', - 'Content-Type': 'application/x-www-form-urlencoded' - }, querystring.stringify(form)).then(function(res) { - return res.body; - }); -} - -function handleSearchResult(rawList) { - if (!rawList) return []; - var list = []; - for (var i = 0; i < rawList.length; i++) { - var item = rawList[i]; - if (!item.baseInfo || !item.baseInfo.simpleSongData) continue; - var s = item.baseInfo.simpleSongData; - var qualities = {}; - if (s.l && s.l.size) qualities.standard = String(s.l.size); - if (s.m && s.m.size) qualities.standard = String(s.m.size); - if (s.h && s.h.size) qualities.exhigh = String(s.h.size); - if (s.sq && s.sq.size) qualities.lossless = String(s.sq.size); - if (s.hr && s.hr.size) qualities.hires = String(s.hr.size); - var picUrl = s.al && s.al.picUrl ? s.al.picUrl : ''; - list.push({ - id: s.id, - name: s.name, - artists: formatSingerName(s.ar, 'name'), - source: 'wy', - pic: picUrl, - mPic: picUrl, - sPic: picUrl, - albumName: s.al && s.al.name ? s.al.name : '', - albumId: s.al && s.al.id ? s.al.id : '', - interval: formatPlayTime((s.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) { - if (!result || result.code !== 200) return search(str, page, limit, retryNum); - var list = handleSearchResult(result.data && result.data.resources ? result.data.resources : []); - if (!list || list.length === 0) return search(str, page, limit, retryNum); - var total = result.data && result.data.totalCount ? result.data.totalCount : 0; - return { - list: list, - allPage: Math.ceil(total / limit), - limit: limit, - total: total, - source: 'wy' - }; - }); -} - -// ===== 播放链接 ===== -function getUrl(songInfo, type) { - var q = type || '128k'; - var songId = songInfo.id || ''; - var ceruKey = process.env.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=wy&songId=' + encodeURIComponent(songId) + '&quality=' + encodeURIComponent(q), '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 getPic(songInfo) { - if (songInfo.pic) return Promise.resolve(songInfo.pic); - return requestUrl('https://music.163.com/weapi/v3/song/detail', 'POST', { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36', - 'Referer': 'https://music.163.com/song?id=' + songInfo.id, - 'Origin': 'https://music.163.com', - 'Content-Type': 'application/x-www-form-urlencoded' - }, querystring.stringify(weapi({ c: '[{"id":' + songInfo.id + '}]', ids: '[' + songInfo.id + ']' }))) - .then(function(res) { - if (res.body && res.body.songs && res.body.songs.length) return res.body.songs[0].al.picUrl; - return ''; - }) - .catch(function() { return ''; }); -} - -// ===== 歌词 ===== -function getLyric(songInfo) { - var songmid = songInfo.id || ''; - return requestUrl('https://music.163.com/api/song/lyric?id=' + songmid + '&lv=1&kv=1&tv=-1', 'GET', { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36', - 'Referer': 'https://music.163.com/song?id=' + songmid - }).then(function(res) { - if (res.body && res.body.lrc && res.body.lrc.lyric) return res.body.lrc.lyric; - return ''; - }).catch(function() { return ''; }); -} - -// ===== 音乐详情 ===== -function musicDetail(songmid) { - return requestUrl('https://music.163.com/weapi/v3/song/detail', 'POST', { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36', - 'Origin': 'https://music.163.com', - 'Content-Type': 'application/x-www-form-urlencoded' - }, querystring.stringify(weapi({ c: '[{"id":' + songmid + '}]', ids: '[' + songmid + ']' }))) - .then(function(res) { - if (res.body && res.body.songs && res.body.songs.length) { - var s = res.body.songs[0]; - var picUrl = s.al && s.al.picUrl ? s.al.picUrl : ''; - return { - id: s.id, - name: s.name, - artists: formatSingerName(s.ar, 'name'), - source: 'wy', - pic: picUrl, - mPic: picUrl, - sPic: picUrl, - albumName: s.al && s.al.name ? s.al.name : '', - albumId: s.al && s.al.id ? s.al.id : '', - interval: formatPlayTime((s.dt || 0) / 1000), - qualities: {} - }; - } - return null; - }) - .catch(function() { return null; }); -} - -function musicInfo(songmid) { - return musicDetail(songmid); -} - -// ===== 热搜 ===== -function hotSearch() { - return requestUrl('https://music.163.com/weapi/search/hot', 'POST', { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36', - 'Origin': 'https://music.163.com', - 'Content-Type': 'application/x-www-form-urlencoded' - }, querystring.stringify(weapi({ type: 1111 }))) - .then(function(res) { - var list = []; - if (res.body && res.body.result && res.body.result.hots) { - for (var i = 0; i < res.body.result.hots.length; i++) list.push(res.body.result.hots[i].first); - } - return { source: 'wy', list: 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 (X11; Linux x86_64) AppleWebKit/537.36', - 'Origin': 'https://music.163.com', - 'Content-Type': 'application/x-www-form-urlencoded' - }, querystring.stringify(weapi({ s: str, limit: 10 }))) - .then(function(res) { - var result = { order: [], songs: [], artists: [], albums: [], playlists: [] }; - if (res.body && res.body.result) { - var r = res.body.result; - if (r.songs) { result.order.push('songs'); result.songs = r.songs.map(function(s) { return { name: s.name, id: s.id, source: 'wy' }; }); } - if (r.artists) { result.order.push('artists'); result.artists = r.artists.map(function(a) { return { name: a.name, id: a.id, source: 'wy' }; }); } - } - return result; - }) - .catch(function() { return { order: [], songs: [], artists: [], albums: [], playlists: [] }; }); -} - -// ===== 榜单 ===== -function leaderboard() { - return Promise.resolve([]); -} - -// ===== 歌单 ===== -function songList() { - return Promise.resolve({ list: [], total: 0, page: 1, source: 'wy' }); -} - -// ===== 歌手 ===== -function singer() { - return Promise.resolve({ source: 'wy', list: [], total: 0 }); -} - -// ===== 专辑 ===== -function album() { - return Promise.resolve({ source: 'wy', list: [], total: 0 }); -} - -// ===== 插件信息 ===== -var pluginInfo = { - info: { - id: 'koneko_ceru_wy', - name: '网易云音乐 - Koneko 聆澜', - version: '0.0.3', - source: 'wy', - description: '网易云音乐音源,基于 CeruMusic musicSdk 搜索 + Ceru 播放接口' - }, - ext: [], - env: [{ key: 'ceru_key', name: 'Ceru API Key', description: '聆澜播放接口密钥' }], - quality: [ - { name: '标准', ui: '标', id: '128k' }, - { name: '高品', ui: 'HQ', id: '320k' }, - { name: '无损', ui: 'SQ', id: 'flac' } - ], - supportFunc: [] -} - -module.exports = { - musicSearch: { search: search }, - tipSearch: { search: tipSearch }, - hotSearch: { getList: hotSearch }, - leaderboard: { getBoards: leaderboard }, - songList: songList, - artists: singer, - album: album, - getLyric: getLyric, - getPic: getPic, - getUrl: getUrl, - musicDetail: musicDetail, - musicInfo: musicInfo, - pluginInfo: pluginInfo -}; diff --git a/Koneko_聆澜_酷我音乐_v0.0.3_QZv2.js b/Koneko_聆澜_酷我音乐_v0.0.3_QZv2.js deleted file mode 100644 index 47401f3..0000000 --- a/Koneko_聆澜_酷我音乐_v0.0.3_QZv2.js +++ /dev/null @@ -1,199 +0,0 @@ -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(seconds) { - if (!seconds) return '00:00'; - var m = Math.floor(seconds / 60); - var s = Math.floor(seconds % 60); - return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s); -} - -// ===== 搜索实现 ===== -function musicSearch(str, page, limit) { - var url = 'https://kuwo-api.vercel.app/api/search?key=' + encodeURIComponent(str) + '&page=' + page + '&limit=' + limit; - return requestUrl(url, 'GET', { 'User-Agent': 'Mozilla/5.0 (Linux; Android 10)' }).then(function(res) { - if (res.body && res.body.data && res.body.data.list) return res.body.data.list; - throw new Error('kw search failed'); - }); -} - -function handleSearchResult(rawList) { - var list = []; - for (var i = 0; i < rawList.length; i++) { - var item = rawList[i]; - var qualities = {}; - if (item.filesize) qualities.standard = String(item.filesize); - if (item.sqfilesize) qualities.exhigh = String(item.sqfilesize); - if (item.flacfilesize) qualities.lossless = String(item.flacfilesize); - var picUrl = item.pic || ''; - list.push({ - id: item.id || item.rid || '', - name: item.name || '', - artists: item.artist || '', - source: 'kw', - pic: picUrl, - mPic: picUrl, - sPic: picUrl, - albumName: item.album || '', - albumId: item.albumid || '', - interval: item.duration ? 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: 'kw' }; - }); -} - -// ===== 播放链接 ===== -function getUrl(songInfo, type) { - var q = type || '128k'; - var songId = songInfo.id || ''; - var ceruKey = process.env.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=kw&songId=' + encodeURIComponent(songId) + '&quality=' + encodeURIComponent(q), '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 getPic(songInfo) { - if (songInfo.pic) return Promise.resolve(songInfo.pic); - return Promise.resolve(''); -} - -// ===== 歌词 ===== -function getLyric(songInfo) { - var rid = songInfo.id || ''; - if (!rid) return Promise.resolve(''); - return requestUrl('https://kuwo-api.vercel.app/api/lyric?id=' + encodeURIComponent(rid), 'GET', { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 10)' - }).then(function(res) { - if (res.body && res.body.data && res.body.data.lrc) return res.body.data.lrc; - return ''; - }).catch(function() { return ''; }); -} - -// ===== 音乐详情 ===== -function musicDetail(songmid) { - return Promise.resolve(null); -} -function musicInfo(songmid) { return musicDetail(songmid); } - -// ===== 热搜 ===== -function hotSearch() { return Promise.resolve({ source: 'kw', list: [] }); } - -// ===== 搜索建议 ===== -function tipSearch(str) { return Promise.resolve({ order: [], songs: [], artists: [], albums: [], playlists: [] }); } - -// ===== 榜单 ===== -function leaderboard() { return Promise.resolve([]); } - -// ===== 歌单 ===== -function songList() { return Promise.resolve({ list: [], total: 0, page: 1, source: 'kw' }); } - -// ===== 歌手 ===== -function singer() { return Promise.resolve({ source: 'kw', list: [], total: 0 }); } - -// ===== 专辑 ===== -function album() { return Promise.resolve({ source: 'kw', list: [], total: 0 }); } - -// ===== 插件信息 ===== -var pluginInfo = { - info: { - id: 'koneko_ceru_kw', - name: '酷我音乐 - Koneko 聆澜', - version: '0.0.3', - source: 'kw', - description: '酷我音乐音源,基于 CeruMusic musicSdk 搜索 + Ceru 播放接口' - }, - ext: [], - env: [{ key: 'ceru_key', name: 'Ceru API Key', description: '聆澜播放接口密钥' }], - quality: [ - { name: '标准', ui: '标', id: '128k' }, - { name: '高品', ui: 'HQ', id: '320k' }, - { name: '无损', ui: 'SQ', id: 'flac' } - ], - supportFunc: [] -} - -module.exports = { - musicSearch: { search: search }, - tipSearch: { search: tipSearch }, - hotSearch: { getList: hotSearch }, - leaderboard: { getBoards: leaderboard }, - songList: songList, - artists: singer, - album: album, - getLyric: getLyric, - getPic: getPic, - getUrl: getUrl, - musicDetail: musicDetail, - musicInfo: musicInfo, - pluginInfo: pluginInfo -}; diff --git a/Koneko_聆澜_酷狗音乐_v0.0.3_QZv2.js b/Koneko_聆澜_酷狗音乐_v0.0.3_QZv2.js deleted file mode 100644 index 9d130ba..0000000 --- a/Koneko_聆澜_酷狗音乐_v0.0.3_QZv2.js +++ /dev/null @@ -1,210 +0,0 @@ -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(seconds) { - if (!seconds) return '00:00'; - var m = Math.floor(seconds / 60); - var s = Math.floor(seconds % 60); - return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s); -} - -// ===== 搜索实现 ===== -function musicSearch(str, page, limit) { - var url = 'http://mobilecdn.kugou.com/api/v3/search/song?showtype=14&highlight=em&pagesize=' + limit + '&page=' + page + '&keyword=' + encodeURIComponent(str); - return requestUrl(url, 'GET', { 'User-Agent': 'Mozilla/5.0 (Linux; Android 10)' }).then(function(res) { - if (res.body && res.body.data && res.body.data.info) return res.body.data.info; - throw new Error('kg search failed'); - }); -} - -function handleSearchResult(rawList) { - var list = []; - for (var i = 0; i < rawList.length; i++) { - var item = rawList[i]; - var qualities = {}; - if (item.filesize) qualities.standard = String(item.filesize); - if (item.sqfilesize) qualities.exhigh = String(item.sqfilesize); - if (item.flacfilesize) qualities.lossless = String(item.flacfilesize); - var picUrl = item.img || ''; - list.push({ - id: item.hash || item.audio_id || '', - name: item.songname || '', - artists: item.singername || '', - source: 'kg', - pic: picUrl, - mPic: picUrl, - sPic: picUrl, - albumName: item.album_name || '', - albumId: item.album_id || '', - interval: item.duration ? 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' }; - }); -} - -// ===== 播放链接 ===== -function getUrl(songInfo, type) { - var q = type || '128k'; - var songId = songInfo.id || ''; - var ceruKey = process.env.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(q), '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 getPic(songInfo) { - if (songInfo.pic) return Promise.resolve(songInfo.pic); - return Promise.resolve(''); -} - -// ===== 歌词 ===== -function getLyric(songInfo) { - var hash = songInfo.id || ''; - if (!hash) return Promise.resolve(''); - return requestUrl('https://krcs.kugou.com/search?ver=1&man=yes&client=mobi&keyword=&duration=&hash=' + encodeURIComponent(hash) + '&album_audio_id=', 'GET', { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 10)' - }).then(function(res) { - if (res.body && res.body.candidates && res.body.candidates.length) { - var id = res.body.candidates[0].id; - var accesskey = res.body.candidates[0].accesskey; - return requestUrl('https://krcs.kugou.com/download?ver=1&client=pc&id=' + encodeURIComponent(id) + '&accesskey=' + encodeURIComponent(accesskey) + '&fmt=lrc&charset=utf8', 'GET', { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 10)' - }).then(function(res2) { - if (res2.body && res2.body.content) { - try { return Buffer.from(res2.body.content, 'base64').toString('utf8'); } catch(e) { return ''; } - } - return ''; - }); - } - return ''; - }).catch(function() { return ''; }); -} - -// ===== 音乐详情 ===== -function musicDetail(songmid) { - return Promise.resolve(null); -} -function musicInfo(songmid) { return musicDetail(songmid); } - -// ===== 热搜 ===== -function hotSearch() { return Promise.resolve({ source: 'kg', list: [] }); } - -// ===== 搜索建议 ===== -function tipSearch(str) { return Promise.resolve({ order: [], songs: [], artists: [], albums: [], playlists: [] }); } - -// ===== 榜单 ===== -function leaderboard() { return Promise.resolve([]); } - -// ===== 歌单 ===== -function songList() { return Promise.resolve({ list: [], total: 0, page: 1, source: 'kg' }); } - -// ===== 歌手 ===== -function singer() { return Promise.resolve({ source: 'kg', list: [], total: 0 }); } - -// ===== 专辑 ===== -function album() { return Promise.resolve({ source: 'kg', list: [], total: 0 }); } - -// ===== 插件信息 ===== -var pluginInfo = { - info: { - id: 'koneko_ceru_kg', - name: '酷狗音乐 - Koneko 聆澜', - version: '0.0.3', - source: 'kg', - description: '酷狗音乐音源,基于 CeruMusic musicSdk 搜索 + Ceru 播放接口' - }, - ext: [], - env: [{ key: 'ceru_key', name: 'Ceru API Key', description: '聆澜播放接口密钥' }], - quality: [ - { name: '标准', ui: '标', id: '128k' }, - { name: '高品', ui: 'HQ', id: '320k' }, - { name: '无损', ui: 'SQ', id: 'flac' } - ], - supportFunc: [] -} - -module.exports = { - musicSearch: { search: search }, - tipSearch: { search: tipSearch }, - hotSearch: { getList: hotSearch }, - leaderboard: { getBoards: leaderboard }, - songList: songList, - artists: singer, - album: album, - getLyric: getLyric, - getPic: getPic, - getUrl: getUrl, - musicDetail: musicDetail, - musicInfo: musicInfo, - pluginInfo: pluginInfo -}; diff --git a/Koneko_GIT音源_v0.0.2.js b/旧版存档/Koneko_GIT音源_v0.0.2.js similarity index 100% rename from Koneko_GIT音源_v0.0.2.js rename to 旧版存档/Koneko_GIT音源_v0.0.2.js diff --git a/Koneko_QQ音乐_v0.0.2.js b/旧版存档/Koneko_QQ音乐_v0.0.2.js similarity index 100% rename from Koneko_QQ音乐_v0.0.2.js rename to 旧版存档/Koneko_QQ音乐_v0.0.2.js diff --git a/Koneko_咪咕音乐_v0.0.2.js b/旧版存档/Koneko_咪咕音乐_v0.0.2.js similarity index 100% rename from Koneko_咪咕音乐_v0.0.2.js rename to 旧版存档/Koneko_咪咕音乐_v0.0.2.js diff --git a/Koneko_网易云音乐_v0.0.2.js b/旧版存档/Koneko_网易云音乐_v0.0.2.js similarity index 100% rename from Koneko_网易云音乐_v0.0.2.js rename to 旧版存档/Koneko_网易云音乐_v0.0.2.js diff --git a/Koneko_酷我音乐_v0.0.2.js b/旧版存档/Koneko_酷我音乐_v0.0.2.js similarity index 100% rename from Koneko_酷我音乐_v0.0.2.js rename to 旧版存档/Koneko_酷我音乐_v0.0.2.js diff --git a/Koneko_酷狗音乐_v0.0.2.js b/旧版存档/Koneko_酷狗音乐_v0.0.2.js similarity index 100% rename from Koneko_酷狗音乐_v0.0.2.js rename to 旧版存档/Koneko_酷狗音乐_v0.0.2.js diff --git a/Koneko_聆澜_GIT音源_v0.1.0_QZv2.js b/聆澜/Koneko_聆澜_GIT音源_v0.1.0_QZv2.js similarity index 100% rename from Koneko_聆澜_GIT音源_v0.1.0_QZv2.js rename to 聆澜/Koneko_聆澜_GIT音源_v0.1.0_QZv2.js diff --git a/Koneko_聆澜_QQ音乐_v0.1.0_QZv2.js b/聆澜/Koneko_聆澜_QQ音乐_v0.1.0_QZv2.js similarity index 100% rename from Koneko_聆澜_QQ音乐_v0.1.0_QZv2.js rename to 聆澜/Koneko_聆澜_QQ音乐_v0.1.0_QZv2.js diff --git a/Koneko_聆澜_咪咕音乐_v0.1.0_QZv2.js b/聆澜/Koneko_聆澜_咪咕音乐_v0.1.0_QZv2.js similarity index 100% rename from Koneko_聆澜_咪咕音乐_v0.1.0_QZv2.js rename to 聆澜/Koneko_聆澜_咪咕音乐_v0.1.0_QZv2.js diff --git a/Koneko_聆澜_网易云音乐_v0.1.0_QZv2.js b/聆澜/Koneko_聆澜_网易云音乐_v0.1.0_QZv2.js similarity index 100% rename from Koneko_聆澜_网易云音乐_v0.1.0_QZv2.js rename to 聆澜/Koneko_聆澜_网易云音乐_v0.1.0_QZv2.js diff --git a/Koneko_聆澜_酷我音乐_v0.1.0_QZv2.js b/聆澜/Koneko_聆澜_酷我音乐_v0.1.0_QZv2.js similarity index 100% rename from Koneko_聆澜_酷我音乐_v0.1.0_QZv2.js rename to 聆澜/Koneko_聆澜_酷我音乐_v0.1.0_QZv2.js diff --git a/Koneko_聆澜_酷狗音乐_v0.1.0_QZv2.js b/聆澜/Koneko_聆澜_酷狗音乐_v0.1.0_QZv2.js similarity index 100% rename from Koneko_聆澜_酷狗音乐_v0.1.0_QZv2.js rename to 聆澜/Koneko_聆澜_酷狗音乐_v0.1.0_QZv2.js