@eldment/meting-mcp 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/package.json +64 -0
- package/src/index.js +53 -0
- package/src/mcp-server.js +242 -0
- package/src/meting.js +192 -0
- package/src/providers/baidu.js +280 -0
- package/src/providers/base.js +247 -0
- package/src/providers/index.js +49 -0
- package/src/providers/kugou.js +417 -0
- package/src/providers/kuwo.js +226 -0
- package/src/providers/netease.js +363 -0
- package/src/providers/tencent.js +328 -0
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import BaseProvider from './base.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 酷狗音乐平台提供者
|
|
6
|
+
*/
|
|
7
|
+
export default class KugouProvider extends BaseProvider {
|
|
8
|
+
constructor(meting) {
|
|
9
|
+
super(meting);
|
|
10
|
+
this.name = 'kugou';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 获取酷狗音乐的请求头配置
|
|
15
|
+
*/
|
|
16
|
+
getHeaders() {
|
|
17
|
+
return {
|
|
18
|
+
'User-Agent': 'IPhone-8990-searchSong',
|
|
19
|
+
'UNI-UserAgent': 'iOS11.4-Phone8990-1009-0-WiFi'
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 搜索歌曲
|
|
25
|
+
*/
|
|
26
|
+
search(keyword, option = {}) {
|
|
27
|
+
return {
|
|
28
|
+
method: 'GET',
|
|
29
|
+
url: 'http://mobilecdn.kugou.com/api/v3/search/song',
|
|
30
|
+
body: {
|
|
31
|
+
api_ver: 1,
|
|
32
|
+
area_code: 1,
|
|
33
|
+
correct: 1,
|
|
34
|
+
pagesize: option.limit || 30,
|
|
35
|
+
plat: 2,
|
|
36
|
+
tag: 1,
|
|
37
|
+
sver: 5,
|
|
38
|
+
showtype: 10,
|
|
39
|
+
page: option.page || 1,
|
|
40
|
+
keyword: keyword,
|
|
41
|
+
version: 8990
|
|
42
|
+
},
|
|
43
|
+
format: 'data.info'
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 获取歌曲详情
|
|
49
|
+
*/
|
|
50
|
+
song(id) {
|
|
51
|
+
return {
|
|
52
|
+
method: 'POST',
|
|
53
|
+
url: 'http://m.kugou.com/app/i/getSongInfo.php',
|
|
54
|
+
body: {
|
|
55
|
+
cmd: 'playInfo',
|
|
56
|
+
hash: id,
|
|
57
|
+
from: 'mkugou'
|
|
58
|
+
},
|
|
59
|
+
format: ''
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 获取专辑信息
|
|
65
|
+
*/
|
|
66
|
+
album(id) {
|
|
67
|
+
return {
|
|
68
|
+
method: 'GET',
|
|
69
|
+
url: 'http://mobilecdn.kugou.com/api/v3/album/song',
|
|
70
|
+
body: {
|
|
71
|
+
albumid: id,
|
|
72
|
+
area_code: 1,
|
|
73
|
+
plat: 2,
|
|
74
|
+
page: 1,
|
|
75
|
+
pagesize: -1,
|
|
76
|
+
version: 8990
|
|
77
|
+
},
|
|
78
|
+
format: 'data.info'
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 获取艺术家作品
|
|
84
|
+
*/
|
|
85
|
+
artist(id, limit = 50) {
|
|
86
|
+
return {
|
|
87
|
+
method: 'GET',
|
|
88
|
+
url: 'http://mobilecdn.kugou.com/api/v3/singer/song',
|
|
89
|
+
body: {
|
|
90
|
+
singerid: id,
|
|
91
|
+
area_code: 1,
|
|
92
|
+
page: 1,
|
|
93
|
+
plat: 0,
|
|
94
|
+
pagesize: limit,
|
|
95
|
+
version: 8990
|
|
96
|
+
},
|
|
97
|
+
format: 'data.info'
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 获取播放列表
|
|
103
|
+
*/
|
|
104
|
+
playlist(id) {
|
|
105
|
+
return {
|
|
106
|
+
method: 'GET',
|
|
107
|
+
url: 'http://mobilecdn.kugou.com/api/v3/special/song',
|
|
108
|
+
body: {
|
|
109
|
+
specialid: id,
|
|
110
|
+
area_code: 1,
|
|
111
|
+
page: 1,
|
|
112
|
+
plat: 2,
|
|
113
|
+
pagesize: -1,
|
|
114
|
+
version: 8990
|
|
115
|
+
},
|
|
116
|
+
format: 'data.info'
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 获取音频播放链接
|
|
122
|
+
* 有 cookie 时走新接口(songinfo + 签名),无 cookie 走老接口
|
|
123
|
+
*/
|
|
124
|
+
url(id, br = 320) {
|
|
125
|
+
const cookie = this.parseCookie(this.meting.header['Cookie'] || '');
|
|
126
|
+
const hasToken = !!(cookie.t && cookie.KugooID);
|
|
127
|
+
|
|
128
|
+
if (hasToken) {
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
const params = {
|
|
131
|
+
srcappid: '2919',
|
|
132
|
+
clientver: '20000',
|
|
133
|
+
clienttime: String(now),
|
|
134
|
+
mid: cookie.mid || cookie.kg_mid || '',
|
|
135
|
+
uuid: cookie.uuid || cookie.mid || cookie.kg_mid || '',
|
|
136
|
+
dfid: cookie.dfid || cookie.kg_dfid || '',
|
|
137
|
+
appid: '1014',
|
|
138
|
+
platid: '4',
|
|
139
|
+
hash: id,
|
|
140
|
+
token: cookie.t || '',
|
|
141
|
+
userid: cookie.KugooID || ''
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
method: 'GET',
|
|
146
|
+
url: this.buildSonginfoUrl(params),
|
|
147
|
+
body: null,
|
|
148
|
+
decode: 'kugou_url_new'
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// 老接口,无需 cookie
|
|
153
|
+
return {
|
|
154
|
+
method: 'POST',
|
|
155
|
+
url: 'http://media.store.kugou.com/v1/get_res_privilege',
|
|
156
|
+
body: JSON.stringify({
|
|
157
|
+
relate: 1,
|
|
158
|
+
userid: '0',
|
|
159
|
+
vip: 0,
|
|
160
|
+
appid: 1000,
|
|
161
|
+
token: '',
|
|
162
|
+
behavior: 'download',
|
|
163
|
+
area_code: '1',
|
|
164
|
+
clientver: '8990',
|
|
165
|
+
resource: [{
|
|
166
|
+
id: 0,
|
|
167
|
+
type: 'audio',
|
|
168
|
+
hash: id
|
|
169
|
+
}]
|
|
170
|
+
}),
|
|
171
|
+
decode: 'kugou_url_legacy'
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* 获取歌词
|
|
177
|
+
*/
|
|
178
|
+
lyric(id) {
|
|
179
|
+
return {
|
|
180
|
+
method: 'GET',
|
|
181
|
+
url: 'http://krcs.kugou.com/search',
|
|
182
|
+
body: {
|
|
183
|
+
keyword: '%20-%20',
|
|
184
|
+
ver: 1,
|
|
185
|
+
hash: id,
|
|
186
|
+
client: 'mobi',
|
|
187
|
+
man: 'yes'
|
|
188
|
+
},
|
|
189
|
+
decode: 'kugou_lyric'
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 获取封面图片
|
|
195
|
+
*/
|
|
196
|
+
async pic(id, size = 300) {
|
|
197
|
+
const format = this.meting.isFormat;
|
|
198
|
+
const data = await this.meting.format(false).song(id);
|
|
199
|
+
this.meting.isFormat = format;
|
|
200
|
+
const songData = JSON.parse(data);
|
|
201
|
+
let url = songData.imgUrl;
|
|
202
|
+
url = url.replace('{size}', '400');
|
|
203
|
+
return JSON.stringify({ url: url });
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 格式化酷狗音乐数据
|
|
208
|
+
*/
|
|
209
|
+
format(data) {
|
|
210
|
+
const filename = data.filename || data.fileName;
|
|
211
|
+
const result = {
|
|
212
|
+
id: data.hash,
|
|
213
|
+
name: data.songName || filename,
|
|
214
|
+
artist: [],
|
|
215
|
+
album: data.album_name || '',
|
|
216
|
+
url_id: data.encode_album_audio_id || data.hash,
|
|
217
|
+
pic_id: data.hash,
|
|
218
|
+
lyric_id: data.hash,
|
|
219
|
+
source: 'kugou'
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
if (data.authors && Array.isArray(data.authors)) {
|
|
223
|
+
result.artist = data.authors.map(a => a.author_name);
|
|
224
|
+
} else if (filename) {
|
|
225
|
+
const parts = filename.split(' - ');
|
|
226
|
+
if (parts.length >= 2) {
|
|
227
|
+
result.artist = parts[0].split('、');
|
|
228
|
+
result.name = parts[1];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* 解析 Cookie 字符串为对象
|
|
237
|
+
*/
|
|
238
|
+
parseCookie(cookieStr) {
|
|
239
|
+
const cookies = {};
|
|
240
|
+
if (!cookieStr) return cookies;
|
|
241
|
+
cookieStr.split(';').forEach(pair => {
|
|
242
|
+
const idx = pair.indexOf('=');
|
|
243
|
+
if (idx > 0) {
|
|
244
|
+
const key = pair.substring(0, idx).trim();
|
|
245
|
+
const val = pair.substring(idx + 1).trim();
|
|
246
|
+
cookies[key] = val;
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
return cookies;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* 生成酷狗 API 签名
|
|
254
|
+
*/
|
|
255
|
+
getSignature(params) {
|
|
256
|
+
const MD5_KEY = 'NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt';
|
|
257
|
+
const paramStr = Object.entries(params)
|
|
258
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
259
|
+
.join('&');
|
|
260
|
+
const sorted = paramStr.split('&').sort().join('');
|
|
261
|
+
return crypto.createHash('md5').update(`${MD5_KEY}${sorted}${MD5_KEY}`).digest('hex');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* 处理酷狗音乐的解码逻辑
|
|
266
|
+
*/
|
|
267
|
+
async handleDecode(decodeType, data) {
|
|
268
|
+
if (decodeType === 'kugou_url_new') {
|
|
269
|
+
return this.urlDecodeNew(data);
|
|
270
|
+
} else if (decodeType === 'kugou_url_legacy') {
|
|
271
|
+
return this.urlDecodeLegacy(data);
|
|
272
|
+
} else if (decodeType === 'kugou_lyric') {
|
|
273
|
+
return this.lyricDecode(data);
|
|
274
|
+
}
|
|
275
|
+
return data;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* 构建带签名的 songinfo 请求 URL
|
|
280
|
+
*/
|
|
281
|
+
buildSonginfoUrl(params) {
|
|
282
|
+
const signature = this.getSignature(params);
|
|
283
|
+
const queryString = Object.entries(params)
|
|
284
|
+
.map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
|
|
285
|
+
.join('&');
|
|
286
|
+
return `https://wwwapi.kugou.com/play/songinfo?${queryString}&signature=${signature}`;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* 酷狗音乐 URL 解码(新接口,需要 cookie)
|
|
291
|
+
* 第一步用 hash 查询获取 encode_album_audio_id,
|
|
292
|
+
* 第二步用 encode_album_audio_id 查询获取播放链接
|
|
293
|
+
*/
|
|
294
|
+
async urlDecodeNew(result) {
|
|
295
|
+
try {
|
|
296
|
+
const json = JSON.parse(result);
|
|
297
|
+
const data = json.data;
|
|
298
|
+
if (!data || !data.encode_album_audio_id) {
|
|
299
|
+
return JSON.stringify({ url: '', size: 0, br: -1 });
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// 第二步:用 encode_album_audio_id 重新查询
|
|
303
|
+
const cookie = this.parseCookie(this.meting.header['Cookie'] || '');
|
|
304
|
+
const now = Date.now();
|
|
305
|
+
const params = {
|
|
306
|
+
srcappid: '2919',
|
|
307
|
+
clientver: '20000',
|
|
308
|
+
clienttime: String(now),
|
|
309
|
+
mid: cookie.mid || cookie.kg_mid || '',
|
|
310
|
+
uuid: cookie.uuid || cookie.mid || cookie.kg_mid || '',
|
|
311
|
+
dfid: cookie.dfid || cookie.kg_dfid || '',
|
|
312
|
+
appid: '1014',
|
|
313
|
+
platid: '4',
|
|
314
|
+
encode_album_audio_id: data.encode_album_audio_id,
|
|
315
|
+
token: cookie.t || '',
|
|
316
|
+
userid: cookie.KugooID || ''
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const api = {
|
|
320
|
+
method: 'GET',
|
|
321
|
+
url: this.buildSonginfoUrl(params),
|
|
322
|
+
body: null
|
|
323
|
+
};
|
|
324
|
+
const response = JSON.parse(await this.meting._exec(api));
|
|
325
|
+
const detail = response.data;
|
|
326
|
+
if (detail) {
|
|
327
|
+
const url = detail.play_url || detail.play_backup_url || '';
|
|
328
|
+
return JSON.stringify({
|
|
329
|
+
url: url,
|
|
330
|
+
size: detail.filesize || 0,
|
|
331
|
+
br: detail.bitrate || -1
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
} catch (e) {
|
|
335
|
+
// parse error
|
|
336
|
+
}
|
|
337
|
+
return JSON.stringify({ url: '', size: 0, br: -1 });
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* 酷狗音乐 URL 解码(老接口,无需 cookie)
|
|
342
|
+
*/
|
|
343
|
+
async urlDecodeLegacy(result) {
|
|
344
|
+
try {
|
|
345
|
+
const data = JSON.parse(result);
|
|
346
|
+
|
|
347
|
+
let maxBr = 0;
|
|
348
|
+
let url;
|
|
349
|
+
|
|
350
|
+
for (const item of data.data[0].relate_goods) {
|
|
351
|
+
if (item.info.bitrate <= this.meting.temp.br && item.info.bitrate > maxBr) {
|
|
352
|
+
const api = {
|
|
353
|
+
method: 'GET',
|
|
354
|
+
url: 'http://trackercdn.kugou.com/i/v2/',
|
|
355
|
+
body: {
|
|
356
|
+
hash: item.hash,
|
|
357
|
+
key: crypto.createHash('md5').update(item.hash + 'kgcloudv2').digest('hex'),
|
|
358
|
+
pid: 3,
|
|
359
|
+
behavior: 'play',
|
|
360
|
+
cmd: '25',
|
|
361
|
+
version: 8990
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const response = JSON.parse(await this.meting._exec(api));
|
|
366
|
+
if (response.url) {
|
|
367
|
+
maxBr = response.bitRate / 1000;
|
|
368
|
+
url = {
|
|
369
|
+
url: Array.isArray(response.url) ? response.url[0] : response.url,
|
|
370
|
+
size: response.fileSize,
|
|
371
|
+
br: response.bitRate / 1000
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (url) {
|
|
378
|
+
return JSON.stringify(url);
|
|
379
|
+
}
|
|
380
|
+
} catch (e) {
|
|
381
|
+
// parse error
|
|
382
|
+
}
|
|
383
|
+
return JSON.stringify({ url: '', size: 0, br: -1 });
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* 酷狗音乐歌词解码
|
|
388
|
+
*/
|
|
389
|
+
async lyricDecode(result) {
|
|
390
|
+
const data = JSON.parse(result);
|
|
391
|
+
|
|
392
|
+
if (!data.candidates || data.candidates.length === 0) {
|
|
393
|
+
return JSON.stringify({ lyric: '', tlyric: '' });
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const api = {
|
|
397
|
+
method: 'GET',
|
|
398
|
+
url: 'http://lyrics.kugou.com/download',
|
|
399
|
+
body: {
|
|
400
|
+
charset: 'utf8',
|
|
401
|
+
accesskey: data.candidates[0].accesskey,
|
|
402
|
+
id: data.candidates[0].id,
|
|
403
|
+
client: 'mobi',
|
|
404
|
+
fmt: 'lrc',
|
|
405
|
+
ver: 1
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
const response = JSON.parse(await this.meting._exec(api));
|
|
410
|
+
const lyricData = {
|
|
411
|
+
lyric: Buffer.from(response.content, 'base64').toString(),
|
|
412
|
+
tlyric: ''
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
return JSON.stringify(lyricData);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import BaseProvider from './base.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 酷我音乐平台提供者
|
|
5
|
+
*/
|
|
6
|
+
export default class KuwoProvider extends BaseProvider {
|
|
7
|
+
constructor(meting) {
|
|
8
|
+
super(meting);
|
|
9
|
+
this.name = 'kuwo';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 获取酷我音乐的请求头配置
|
|
14
|
+
*/
|
|
15
|
+
getHeaders() {
|
|
16
|
+
return {
|
|
17
|
+
'Cookie': 'Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1623339177,1623339183; _ga=GA1.2.1195980605.1579367081; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1623339982; kw_token=3E7JFQ7MRPL; _gid=GA1.2.747985028.1623339179; _gat=1',
|
|
18
|
+
'csrf': '3E7JFQ7MRPL',
|
|
19
|
+
'Host': 'www.kuwo.cn',
|
|
20
|
+
'Referer': 'http://www.kuwo.cn/',
|
|
21
|
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36'
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 搜索歌曲
|
|
27
|
+
*/
|
|
28
|
+
search(keyword, option = {}) {
|
|
29
|
+
return {
|
|
30
|
+
method: 'GET',
|
|
31
|
+
url: 'http://www.kuwo.cn/api/www/search/searchMusicBykeyWord',
|
|
32
|
+
body: {
|
|
33
|
+
key: keyword,
|
|
34
|
+
pn: option.page || 1,
|
|
35
|
+
rn: option.limit || 30,
|
|
36
|
+
httpsStatus: 1
|
|
37
|
+
},
|
|
38
|
+
format: 'data.list'
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 获取歌曲详情
|
|
44
|
+
*/
|
|
45
|
+
song(id) {
|
|
46
|
+
return {
|
|
47
|
+
method: 'GET',
|
|
48
|
+
url: 'http://www.kuwo.cn/api/www/music/musicInfo',
|
|
49
|
+
body: {
|
|
50
|
+
mid: id,
|
|
51
|
+
httpsStatus: 1
|
|
52
|
+
},
|
|
53
|
+
format: 'data'
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 获取专辑信息
|
|
59
|
+
*/
|
|
60
|
+
album(id) {
|
|
61
|
+
return {
|
|
62
|
+
method: 'GET',
|
|
63
|
+
url: 'http://www.kuwo.cn/api/www/album/albumInfo',
|
|
64
|
+
body: {
|
|
65
|
+
albumId: id,
|
|
66
|
+
pn: 1,
|
|
67
|
+
rn: 1000,
|
|
68
|
+
httpsStatus: 1
|
|
69
|
+
},
|
|
70
|
+
format: 'data.musicList'
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 获取艺术家作品
|
|
76
|
+
*/
|
|
77
|
+
artist(id, limit = 50) {
|
|
78
|
+
return {
|
|
79
|
+
method: 'GET',
|
|
80
|
+
url: 'http://www.kuwo.cn/api/www/artist/artistMusic',
|
|
81
|
+
body: {
|
|
82
|
+
artistid: id,
|
|
83
|
+
pn: 1,
|
|
84
|
+
rn: limit,
|
|
85
|
+
httpsStatus: 1
|
|
86
|
+
},
|
|
87
|
+
format: 'data.list'
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 获取播放列表
|
|
93
|
+
*/
|
|
94
|
+
playlist(id) {
|
|
95
|
+
return {
|
|
96
|
+
method: 'GET',
|
|
97
|
+
url: 'http://www.kuwo.cn/api/www/playlist/playListInfo',
|
|
98
|
+
body: {
|
|
99
|
+
pid: id,
|
|
100
|
+
pn: 1,
|
|
101
|
+
rn: 1000,
|
|
102
|
+
httpsStatus: 1
|
|
103
|
+
},
|
|
104
|
+
format: 'data.musicList'
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 获取音频播放链接
|
|
110
|
+
*/
|
|
111
|
+
url(id, br = 320) {
|
|
112
|
+
return {
|
|
113
|
+
method: 'GET',
|
|
114
|
+
url: 'http://www.kuwo.cn/api/v1/www/music/playUrl',
|
|
115
|
+
body: {
|
|
116
|
+
mid: id,
|
|
117
|
+
type: 'music',
|
|
118
|
+
httpsStatus: 1
|
|
119
|
+
},
|
|
120
|
+
decode: 'kuwo_url'
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 获取歌词
|
|
126
|
+
*/
|
|
127
|
+
lyric(id) {
|
|
128
|
+
return {
|
|
129
|
+
method: 'GET',
|
|
130
|
+
url: 'http://m.kuwo.cn/newh5/singles/songinfoandlrc',
|
|
131
|
+
body: {
|
|
132
|
+
musicId: id,
|
|
133
|
+
httpsStatus: 1
|
|
134
|
+
},
|
|
135
|
+
decode: 'kuwo_lyric'
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 获取封面图片
|
|
141
|
+
*/
|
|
142
|
+
async pic(id, size = 300) {
|
|
143
|
+
const format = this.meting.isFormat;
|
|
144
|
+
const data = await this.meting.format(false).song(id);
|
|
145
|
+
this.meting.isFormat = format;
|
|
146
|
+
const songData = JSON.parse(data);
|
|
147
|
+
const url = songData.data.pic || songData.data.albumpic;
|
|
148
|
+
return JSON.stringify({ url: url });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 格式化酷我音乐数据
|
|
153
|
+
*/
|
|
154
|
+
format(data) {
|
|
155
|
+
return {
|
|
156
|
+
id: data.rid,
|
|
157
|
+
name: data.name,
|
|
158
|
+
artist: data.artist ? data.artist.split('&') : [],
|
|
159
|
+
album: data.album || '',
|
|
160
|
+
pic_id: data.rid,
|
|
161
|
+
url_id: data.rid,
|
|
162
|
+
lyric_id: data.rid,
|
|
163
|
+
source: 'kuwo'
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 处理酷我音乐的解码逻辑
|
|
169
|
+
*/
|
|
170
|
+
async handleDecode(decodeType, data) {
|
|
171
|
+
if (decodeType === 'kuwo_url') {
|
|
172
|
+
return this.urlDecode(data);
|
|
173
|
+
} else if (decodeType === 'kuwo_lyric') {
|
|
174
|
+
return this.lyricDecode(data);
|
|
175
|
+
}
|
|
176
|
+
return data;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 酷我音乐 URL 解码
|
|
181
|
+
*/
|
|
182
|
+
urlDecode(result) {
|
|
183
|
+
const data = JSON.parse(result);
|
|
184
|
+
|
|
185
|
+
let url;
|
|
186
|
+
if (data.code === 200 && data.data && data.data.url) {
|
|
187
|
+
url = {
|
|
188
|
+
url: data.data.url,
|
|
189
|
+
br: 128
|
|
190
|
+
};
|
|
191
|
+
} else {
|
|
192
|
+
url = {
|
|
193
|
+
url: '',
|
|
194
|
+
br: -1
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return JSON.stringify(url);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 酷我音乐歌词解码
|
|
203
|
+
*/
|
|
204
|
+
lyricDecode(result) {
|
|
205
|
+
const data = JSON.parse(result);
|
|
206
|
+
|
|
207
|
+
let lyric = '';
|
|
208
|
+
if (data.data && data.data.lrclist && data.data.lrclist.length > 0) {
|
|
209
|
+
data.data.lrclist.forEach(item => {
|
|
210
|
+
const time = parseFloat(item.time);
|
|
211
|
+
const min = Math.floor(time / 60).toString().padStart(2, '0');
|
|
212
|
+
const sec = Math.floor(time % 60).toString().padStart(2, '0');
|
|
213
|
+
const msec = ((time % 1) * 100).toFixed(0).padStart(2, '0');
|
|
214
|
+
|
|
215
|
+
lyric += `[${min}:${sec}.${msec}]${item.lineLyric}\n`;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const lyricData = {
|
|
220
|
+
lyric: lyric,
|
|
221
|
+
tlyric: ''
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
return JSON.stringify(lyricData);
|
|
225
|
+
}
|
|
226
|
+
}
|