@eldment/meting-mcp 1.6.2 → 1.6.3
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/README.md +29 -7
- package/package.json +6 -1
- package/src/index.js +6 -4
- package/src/mcp-server.js +63 -31
- package/src/meting.js +21 -22
- package/src/providers/baidu.js +91 -89
- package/src/providers/base.js +13 -13
- package/src/providers/index.js +7 -7
- package/src/providers/kugou.js +118 -113
- package/src/providers/kuwo.js +63 -57
- package/src/providers/netease.js +105 -98
- package/src/providers/tencent.js +98 -93
package/src/providers/kuwo.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BaseProvider from
|
|
1
|
+
import BaseProvider from "./base.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* 酷我音乐平台提供者
|
|
@@ -6,7 +6,7 @@ import BaseProvider from './base.js';
|
|
|
6
6
|
export default class KuwoProvider extends BaseProvider {
|
|
7
7
|
constructor(meting) {
|
|
8
8
|
super(meting);
|
|
9
|
-
this.name =
|
|
9
|
+
this.name = "kuwo";
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -14,11 +14,13 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
14
14
|
*/
|
|
15
15
|
getHeaders() {
|
|
16
16
|
return {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
Cookie:
|
|
18
|
+
"Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1623339177,1623339183; _ga=GA1.2.1195980605.1579367081; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1623339982; kw_token=3E7JFQ7MRPL; _gid=GA1.2.747985028.1623339179; _gat=1",
|
|
19
|
+
csrf: "3E7JFQ7MRPL",
|
|
20
|
+
Host: "www.kuwo.cn",
|
|
21
|
+
Referer: "http://www.kuwo.cn/",
|
|
22
|
+
"User-Agent":
|
|
23
|
+
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36",
|
|
22
24
|
};
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -27,15 +29,15 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
27
29
|
*/
|
|
28
30
|
search(keyword, option = {}) {
|
|
29
31
|
return {
|
|
30
|
-
method:
|
|
31
|
-
url:
|
|
32
|
+
method: "GET",
|
|
33
|
+
url: "http://www.kuwo.cn/api/www/search/searchMusicBykeyWord",
|
|
32
34
|
body: {
|
|
33
35
|
key: keyword,
|
|
34
36
|
pn: option.page || 1,
|
|
35
37
|
rn: option.limit || 30,
|
|
36
|
-
httpsStatus: 1
|
|
38
|
+
httpsStatus: 1,
|
|
37
39
|
},
|
|
38
|
-
format:
|
|
40
|
+
format: "data.list",
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
43
|
|
|
@@ -44,13 +46,13 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
44
46
|
*/
|
|
45
47
|
song(id) {
|
|
46
48
|
return {
|
|
47
|
-
method:
|
|
48
|
-
url:
|
|
49
|
+
method: "GET",
|
|
50
|
+
url: "http://www.kuwo.cn/api/www/music/musicInfo",
|
|
49
51
|
body: {
|
|
50
52
|
mid: id,
|
|
51
|
-
httpsStatus: 1
|
|
53
|
+
httpsStatus: 1,
|
|
52
54
|
},
|
|
53
|
-
format:
|
|
55
|
+
format: "data",
|
|
54
56
|
};
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -59,15 +61,15 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
59
61
|
*/
|
|
60
62
|
album(id) {
|
|
61
63
|
return {
|
|
62
|
-
method:
|
|
63
|
-
url:
|
|
64
|
+
method: "GET",
|
|
65
|
+
url: "http://www.kuwo.cn/api/www/album/albumInfo",
|
|
64
66
|
body: {
|
|
65
67
|
albumId: id,
|
|
66
68
|
pn: 1,
|
|
67
69
|
rn: 1000,
|
|
68
|
-
httpsStatus: 1
|
|
70
|
+
httpsStatus: 1,
|
|
69
71
|
},
|
|
70
|
-
format:
|
|
72
|
+
format: "data.musicList",
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -76,15 +78,15 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
76
78
|
*/
|
|
77
79
|
artist(id, limit = 50) {
|
|
78
80
|
return {
|
|
79
|
-
method:
|
|
80
|
-
url:
|
|
81
|
+
method: "GET",
|
|
82
|
+
url: "http://www.kuwo.cn/api/www/artist/artistMusic",
|
|
81
83
|
body: {
|
|
82
84
|
artistid: id,
|
|
83
85
|
pn: 1,
|
|
84
86
|
rn: limit,
|
|
85
|
-
httpsStatus: 1
|
|
87
|
+
httpsStatus: 1,
|
|
86
88
|
},
|
|
87
|
-
format:
|
|
89
|
+
format: "data.list",
|
|
88
90
|
};
|
|
89
91
|
}
|
|
90
92
|
|
|
@@ -93,15 +95,15 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
93
95
|
*/
|
|
94
96
|
playlist(id) {
|
|
95
97
|
return {
|
|
96
|
-
method:
|
|
97
|
-
url:
|
|
98
|
+
method: "GET",
|
|
99
|
+
url: "http://www.kuwo.cn/api/www/playlist/playListInfo",
|
|
98
100
|
body: {
|
|
99
101
|
pid: id,
|
|
100
102
|
pn: 1,
|
|
101
103
|
rn: 1000,
|
|
102
|
-
httpsStatus: 1
|
|
104
|
+
httpsStatus: 1,
|
|
103
105
|
},
|
|
104
|
-
format:
|
|
106
|
+
format: "data.musicList",
|
|
105
107
|
};
|
|
106
108
|
}
|
|
107
109
|
|
|
@@ -110,14 +112,14 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
110
112
|
*/
|
|
111
113
|
url(id, br = 320) {
|
|
112
114
|
return {
|
|
113
|
-
method:
|
|
114
|
-
url:
|
|
115
|
+
method: "GET",
|
|
116
|
+
url: "http://www.kuwo.cn/api/v1/www/music/playUrl",
|
|
115
117
|
body: {
|
|
116
118
|
mid: id,
|
|
117
|
-
type:
|
|
118
|
-
httpsStatus: 1
|
|
119
|
+
type: "music",
|
|
120
|
+
httpsStatus: 1,
|
|
119
121
|
},
|
|
120
|
-
decode:
|
|
122
|
+
decode: "kuwo_url",
|
|
121
123
|
};
|
|
122
124
|
}
|
|
123
125
|
|
|
@@ -126,13 +128,13 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
126
128
|
*/
|
|
127
129
|
lyric(id) {
|
|
128
130
|
return {
|
|
129
|
-
method:
|
|
130
|
-
url:
|
|
131
|
+
method: "GET",
|
|
132
|
+
url: "http://m.kuwo.cn/newh5/singles/songinfoandlrc",
|
|
131
133
|
body: {
|
|
132
134
|
musicId: id,
|
|
133
|
-
httpsStatus: 1
|
|
135
|
+
httpsStatus: 1,
|
|
134
136
|
},
|
|
135
|
-
decode:
|
|
137
|
+
decode: "kuwo_lyric",
|
|
136
138
|
};
|
|
137
139
|
}
|
|
138
140
|
|
|
@@ -155,12 +157,12 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
155
157
|
return {
|
|
156
158
|
id: data.rid,
|
|
157
159
|
name: data.name,
|
|
158
|
-
artist: data.artist ? data.artist.split(
|
|
159
|
-
album: data.album ||
|
|
160
|
+
artist: data.artist ? data.artist.split("&") : [],
|
|
161
|
+
album: data.album || "",
|
|
160
162
|
pic_id: data.rid,
|
|
161
163
|
url_id: data.rid,
|
|
162
164
|
lyric_id: data.rid,
|
|
163
|
-
source:
|
|
165
|
+
source: "kuwo",
|
|
164
166
|
};
|
|
165
167
|
}
|
|
166
168
|
|
|
@@ -168,9 +170,9 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
168
170
|
* 处理酷我音乐的解码逻辑
|
|
169
171
|
*/
|
|
170
172
|
async handleDecode(decodeType, data) {
|
|
171
|
-
if (decodeType ===
|
|
173
|
+
if (decodeType === "kuwo_url") {
|
|
172
174
|
return this.urlDecode(data);
|
|
173
|
-
} else if (decodeType ===
|
|
175
|
+
} else if (decodeType === "kuwo_lyric") {
|
|
174
176
|
return this.lyricDecode(data);
|
|
175
177
|
}
|
|
176
178
|
return data;
|
|
@@ -181,20 +183,20 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
181
183
|
*/
|
|
182
184
|
urlDecode(result) {
|
|
183
185
|
const data = JSON.parse(result);
|
|
184
|
-
|
|
186
|
+
|
|
185
187
|
let url;
|
|
186
188
|
if (data.code === 200 && data.data && data.data.url) {
|
|
187
189
|
url = {
|
|
188
190
|
url: data.data.url,
|
|
189
|
-
br: 128
|
|
191
|
+
br: 128,
|
|
190
192
|
};
|
|
191
193
|
} else {
|
|
192
194
|
url = {
|
|
193
|
-
url:
|
|
194
|
-
br: -1
|
|
195
|
+
url: "",
|
|
196
|
+
br: -1,
|
|
195
197
|
};
|
|
196
198
|
}
|
|
197
|
-
|
|
199
|
+
|
|
198
200
|
return JSON.stringify(url);
|
|
199
201
|
}
|
|
200
202
|
|
|
@@ -203,24 +205,28 @@ export default class KuwoProvider extends BaseProvider {
|
|
|
203
205
|
*/
|
|
204
206
|
lyricDecode(result) {
|
|
205
207
|
const data = JSON.parse(result);
|
|
206
|
-
|
|
207
|
-
let lyric =
|
|
208
|
+
|
|
209
|
+
let lyric = "";
|
|
208
210
|
if (data.data && data.data.lrclist && data.data.lrclist.length > 0) {
|
|
209
|
-
data.data.lrclist.forEach(item => {
|
|
211
|
+
data.data.lrclist.forEach((item) => {
|
|
210
212
|
const time = parseFloat(item.time);
|
|
211
|
-
const min = Math.floor(time / 60)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
213
|
+
const min = Math.floor(time / 60)
|
|
214
|
+
.toString()
|
|
215
|
+
.padStart(2, "0");
|
|
216
|
+
const sec = Math.floor(time % 60)
|
|
217
|
+
.toString()
|
|
218
|
+
.padStart(2, "0");
|
|
219
|
+
const msec = ((time % 1) * 100).toFixed(0).padStart(2, "0");
|
|
220
|
+
|
|
215
221
|
lyric += `[${min}:${sec}.${msec}]${item.lineLyric}\n`;
|
|
216
222
|
});
|
|
217
223
|
}
|
|
218
|
-
|
|
224
|
+
|
|
219
225
|
const lyricData = {
|
|
220
226
|
lyric: lyric,
|
|
221
|
-
tlyric:
|
|
227
|
+
tlyric: "",
|
|
222
228
|
};
|
|
223
|
-
|
|
229
|
+
|
|
224
230
|
return JSON.stringify(lyricData);
|
|
225
231
|
}
|
|
226
|
-
}
|
|
232
|
+
}
|
package/src/providers/netease.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import crypto from
|
|
2
|
-
import BaseProvider from
|
|
1
|
+
import crypto from "crypto";
|
|
2
|
+
import BaseProvider from "./base.js";
|
|
3
3
|
|
|
4
4
|
// eapi 相关常量
|
|
5
|
-
const EAPI_KEY =
|
|
6
|
-
const EAPI_IV = Buffer.from(
|
|
5
|
+
const EAPI_KEY = "e82ckenh8dichen8";
|
|
6
|
+
const EAPI_IV = Buffer.from("0102030405060708");
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* 网易云音乐平台提供者
|
|
@@ -11,7 +11,7 @@ const EAPI_IV = Buffer.from('0102030405060708');
|
|
|
11
11
|
export default class NeteaseProvider extends BaseProvider {
|
|
12
12
|
constructor(meting) {
|
|
13
13
|
super(meting);
|
|
14
|
-
this.name =
|
|
14
|
+
this.name = "netease";
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -22,13 +22,18 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
22
22
|
const deviceId = this._generateDeviceId();
|
|
23
23
|
|
|
24
24
|
return {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
Referer: "music.163.com",
|
|
26
|
+
Cookie: `osver=android; appver=8.7.01; os=android; deviceId=${deviceId}; channel=netease; requestId=${timestamp}_${Math.floor(
|
|
27
|
+
Math.random() * 1000
|
|
28
|
+
)
|
|
29
|
+
.toString()
|
|
30
|
+
.padStart(4, "0")}; __remember_me=true`,
|
|
31
|
+
"User-Agent":
|
|
32
|
+
"Mozilla/5.0 (Linux; Android 11; M2007J3SC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045714 Mobile Safari/537.36 NeteaseMusic/8.7.01",
|
|
33
|
+
Accept: "*/*",
|
|
34
|
+
"Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
|
|
35
|
+
Connection: "keep-alive",
|
|
36
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
32
37
|
};
|
|
33
38
|
}
|
|
34
39
|
|
|
@@ -37,17 +42,17 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
37
42
|
*/
|
|
38
43
|
search(keyword, option = {}) {
|
|
39
44
|
return {
|
|
40
|
-
method:
|
|
41
|
-
url:
|
|
45
|
+
method: "POST",
|
|
46
|
+
url: "http://music.163.com/api/cloudsearch/pc",
|
|
42
47
|
body: {
|
|
43
48
|
s: keyword,
|
|
44
49
|
type: option.type || 1,
|
|
45
50
|
limit: option.limit || 30,
|
|
46
|
-
total:
|
|
47
|
-
offset:
|
|
51
|
+
total: "true",
|
|
52
|
+
offset: option.page && option.limit ? (option.page - 1) * option.limit : 0,
|
|
48
53
|
},
|
|
49
|
-
encode:
|
|
50
|
-
format:
|
|
54
|
+
encode: "netease_eapi",
|
|
55
|
+
format: "result.songs",
|
|
51
56
|
};
|
|
52
57
|
}
|
|
53
58
|
|
|
@@ -56,13 +61,13 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
56
61
|
*/
|
|
57
62
|
song(id) {
|
|
58
63
|
return {
|
|
59
|
-
method:
|
|
60
|
-
url:
|
|
64
|
+
method: "POST",
|
|
65
|
+
url: "http://music.163.com/api/v3/song/detail/",
|
|
61
66
|
body: {
|
|
62
|
-
c: `[{"id":${id},"v":0}]
|
|
67
|
+
c: `[{"id":${id},"v":0}]`,
|
|
63
68
|
},
|
|
64
|
-
encode:
|
|
65
|
-
format:
|
|
69
|
+
encode: "netease_eapi",
|
|
70
|
+
format: "songs",
|
|
66
71
|
};
|
|
67
72
|
}
|
|
68
73
|
|
|
@@ -71,18 +76,18 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
71
76
|
*/
|
|
72
77
|
album(id) {
|
|
73
78
|
return {
|
|
74
|
-
method:
|
|
79
|
+
method: "POST",
|
|
75
80
|
url: `http://music.163.com/api/v1/album/${id}`,
|
|
76
81
|
body: {
|
|
77
|
-
total:
|
|
78
|
-
offset:
|
|
82
|
+
total: "true",
|
|
83
|
+
offset: "0",
|
|
79
84
|
id: id,
|
|
80
|
-
limit:
|
|
81
|
-
ext:
|
|
82
|
-
private_cloud:
|
|
85
|
+
limit: "1000",
|
|
86
|
+
ext: "true",
|
|
87
|
+
private_cloud: "true",
|
|
83
88
|
},
|
|
84
|
-
encode:
|
|
85
|
-
format:
|
|
89
|
+
encode: "netease_eapi",
|
|
90
|
+
format: "songs",
|
|
86
91
|
};
|
|
87
92
|
}
|
|
88
93
|
|
|
@@ -91,16 +96,16 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
91
96
|
*/
|
|
92
97
|
artist(id, limit = 50) {
|
|
93
98
|
return {
|
|
94
|
-
method:
|
|
99
|
+
method: "POST",
|
|
95
100
|
url: `http://music.163.com/api/v1/artist/${id}`,
|
|
96
101
|
body: {
|
|
97
|
-
ext:
|
|
98
|
-
private_cloud:
|
|
102
|
+
ext: "true",
|
|
103
|
+
private_cloud: "true",
|
|
99
104
|
top: limit,
|
|
100
|
-
id: id
|
|
105
|
+
id: id,
|
|
101
106
|
},
|
|
102
|
-
encode:
|
|
103
|
-
format:
|
|
107
|
+
encode: "netease_eapi",
|
|
108
|
+
format: "hotSongs",
|
|
104
109
|
};
|
|
105
110
|
}
|
|
106
111
|
|
|
@@ -109,16 +114,16 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
109
114
|
*/
|
|
110
115
|
playlist(id) {
|
|
111
116
|
return {
|
|
112
|
-
method:
|
|
113
|
-
url:
|
|
117
|
+
method: "POST",
|
|
118
|
+
url: "http://music.163.com/api/v6/playlist/detail",
|
|
114
119
|
body: {
|
|
115
|
-
s:
|
|
120
|
+
s: "0",
|
|
116
121
|
id: id,
|
|
117
|
-
n:
|
|
118
|
-
t:
|
|
122
|
+
n: "1000",
|
|
123
|
+
t: "0",
|
|
119
124
|
},
|
|
120
|
-
encode:
|
|
121
|
-
format:
|
|
125
|
+
encode: "netease_eapi",
|
|
126
|
+
format: "playlist.tracks",
|
|
122
127
|
};
|
|
123
128
|
}
|
|
124
129
|
|
|
@@ -127,14 +132,14 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
127
132
|
*/
|
|
128
133
|
url(id, br = 320) {
|
|
129
134
|
return {
|
|
130
|
-
method:
|
|
131
|
-
url:
|
|
135
|
+
method: "POST",
|
|
136
|
+
url: "http://music.163.com/api/song/enhance/player/url",
|
|
132
137
|
body: {
|
|
133
138
|
ids: [id],
|
|
134
|
-
br: br * 1000
|
|
139
|
+
br: br * 1000,
|
|
135
140
|
},
|
|
136
|
-
encode:
|
|
137
|
-
decode:
|
|
141
|
+
encode: "netease_eapi",
|
|
142
|
+
decode: "netease_url",
|
|
138
143
|
};
|
|
139
144
|
}
|
|
140
145
|
|
|
@@ -143,17 +148,17 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
143
148
|
*/
|
|
144
149
|
lyric(id) {
|
|
145
150
|
return {
|
|
146
|
-
method:
|
|
147
|
-
url:
|
|
151
|
+
method: "POST",
|
|
152
|
+
url: "http://music.163.com/api/song/lyric",
|
|
148
153
|
body: {
|
|
149
154
|
id: id,
|
|
150
|
-
os:
|
|
155
|
+
os: "linux",
|
|
151
156
|
lv: -1,
|
|
152
157
|
kv: -1,
|
|
153
|
-
tv: -1
|
|
158
|
+
tv: -1,
|
|
154
159
|
},
|
|
155
|
-
encode:
|
|
156
|
-
decode:
|
|
160
|
+
encode: "netease_eapi",
|
|
161
|
+
decode: "netease_lyric",
|
|
157
162
|
};
|
|
158
163
|
}
|
|
159
164
|
|
|
@@ -177,20 +182,20 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
177
182
|
pic_id: data.al.pic_str || data.al.pic,
|
|
178
183
|
url_id: data.id,
|
|
179
184
|
lyric_id: data.id,
|
|
180
|
-
source:
|
|
185
|
+
source: "netease",
|
|
181
186
|
};
|
|
182
|
-
|
|
187
|
+
|
|
183
188
|
if (data.al.picUrl) {
|
|
184
189
|
const match = data.al.picUrl.match(/\/(\d+)\./);
|
|
185
190
|
if (match) {
|
|
186
191
|
result.pic_id = match[1];
|
|
187
192
|
}
|
|
188
193
|
}
|
|
189
|
-
|
|
190
|
-
data.ar.forEach(artist => {
|
|
194
|
+
|
|
195
|
+
data.ar.forEach((artist) => {
|
|
191
196
|
result.artist.push(artist.name);
|
|
192
197
|
});
|
|
193
|
-
|
|
198
|
+
|
|
194
199
|
return result;
|
|
195
200
|
}
|
|
196
201
|
|
|
@@ -198,7 +203,7 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
198
203
|
* 处理网易云音乐的编码逻辑
|
|
199
204
|
*/
|
|
200
205
|
async handleEncode(api) {
|
|
201
|
-
if (api.encode ===
|
|
206
|
+
if (api.encode === "netease_eapi") {
|
|
202
207
|
return this.eapiEncrypt(api);
|
|
203
208
|
}
|
|
204
209
|
return api;
|
|
@@ -209,25 +214,25 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
209
214
|
*/
|
|
210
215
|
async eapiEncrypt(api) {
|
|
211
216
|
const text = JSON.stringify(api.body);
|
|
212
|
-
const url = api.url.replace(/https?:\/\/[^\/]+/,
|
|
217
|
+
const url = api.url.replace(/https?:\/\/[^\/]+/, "");
|
|
213
218
|
|
|
214
219
|
// 构建 eapi 加密消息
|
|
215
220
|
const message = `nobody${url}use${text}md5forencrypt`;
|
|
216
|
-
const digest = crypto.createHash(
|
|
221
|
+
const digest = crypto.createHash("md5").update(message).digest("hex");
|
|
217
222
|
const data = `${url}-36cd479b6b5-${text}-36cd479b6b5-${digest}`;
|
|
218
223
|
|
|
219
224
|
// AES-128-ECB 加密
|
|
220
|
-
const cipher = crypto.createCipheriv(
|
|
225
|
+
const cipher = crypto.createCipheriv("aes-128-ecb", Buffer.from(EAPI_KEY, "utf8"), null);
|
|
221
226
|
cipher.setAutoPadding(true);
|
|
222
|
-
let encrypted = cipher.update(data,
|
|
223
|
-
encrypted += cipher.final(
|
|
227
|
+
let encrypted = cipher.update(data, "utf8", "hex");
|
|
228
|
+
encrypted += cipher.final("hex");
|
|
224
229
|
|
|
225
230
|
// 转换 URL 路径
|
|
226
|
-
api.url = api.url.replace(
|
|
231
|
+
api.url = api.url.replace("/api/", "/eapi/");
|
|
227
232
|
|
|
228
233
|
// 构建 eapi 请求体
|
|
229
234
|
api.body = {
|
|
230
|
-
params: encrypted.toUpperCase()
|
|
235
|
+
params: encrypted.toUpperCase(),
|
|
231
236
|
};
|
|
232
237
|
|
|
233
238
|
return api;
|
|
@@ -239,25 +244,25 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
239
244
|
urlDecode(result) {
|
|
240
245
|
const data = JSON.parse(result);
|
|
241
246
|
let url;
|
|
242
|
-
|
|
247
|
+
|
|
243
248
|
if (data.data[0].uf && data.data[0].uf.url) {
|
|
244
249
|
data.data[0].url = data.data[0].uf.url;
|
|
245
250
|
}
|
|
246
|
-
|
|
251
|
+
|
|
247
252
|
if (data.data[0].url) {
|
|
248
253
|
url = {
|
|
249
254
|
url: data.data[0].url,
|
|
250
255
|
size: data.data[0].size,
|
|
251
|
-
br: data.data[0].br / 1000
|
|
256
|
+
br: data.data[0].br / 1000,
|
|
252
257
|
};
|
|
253
258
|
} else {
|
|
254
259
|
url = {
|
|
255
|
-
url:
|
|
260
|
+
url: "",
|
|
256
261
|
size: 0,
|
|
257
|
-
br: -1
|
|
262
|
+
br: -1,
|
|
258
263
|
};
|
|
259
264
|
}
|
|
260
|
-
|
|
265
|
+
|
|
261
266
|
return JSON.stringify(url);
|
|
262
267
|
}
|
|
263
268
|
|
|
@@ -267,10 +272,10 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
267
272
|
lyricDecode(result) {
|
|
268
273
|
const data = JSON.parse(result);
|
|
269
274
|
const lyricData = {
|
|
270
|
-
lyric:
|
|
271
|
-
tlyric:
|
|
275
|
+
lyric: data.lrc && data.lrc.lyric ? data.lrc.lyric : "",
|
|
276
|
+
tlyric: data.tlyric && data.tlyric.lyric ? data.tlyric.lyric : "",
|
|
272
277
|
};
|
|
273
|
-
|
|
278
|
+
|
|
274
279
|
return JSON.stringify(lyricData);
|
|
275
280
|
}
|
|
276
281
|
|
|
@@ -283,21 +288,22 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
283
288
|
const min = 1884815360; // 112.74.200.0
|
|
284
289
|
const max = 1884890111; // 112.74.243.255
|
|
285
290
|
const randomInt = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
286
|
-
|
|
291
|
+
|
|
287
292
|
return [
|
|
288
|
-
(randomInt >>> 24) &
|
|
289
|
-
(randomInt >>> 16) &
|
|
290
|
-
(randomInt >>> 8) &
|
|
291
|
-
randomInt &
|
|
292
|
-
].join(
|
|
293
|
+
(randomInt >>> 24) & 0xff,
|
|
294
|
+
(randomInt >>> 16) & 0xff,
|
|
295
|
+
(randomInt >>> 8) & 0xff,
|
|
296
|
+
randomInt & 0xff,
|
|
297
|
+
].join(".");
|
|
293
298
|
}
|
|
294
299
|
|
|
295
300
|
/**
|
|
296
301
|
* 生成随机十六进制字符串
|
|
297
302
|
*/
|
|
298
303
|
_getRandomHex(length) {
|
|
299
|
-
return crypto
|
|
300
|
-
.
|
|
304
|
+
return crypto
|
|
305
|
+
.randomBytes(Math.ceil(length / 2))
|
|
306
|
+
.toString("hex")
|
|
301
307
|
.slice(0, length);
|
|
302
308
|
}
|
|
303
309
|
|
|
@@ -307,7 +313,7 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
307
313
|
_generateDeviceId() {
|
|
308
314
|
// 生成类似移动端的设备 ID
|
|
309
315
|
const randomBytes = crypto.randomBytes(16);
|
|
310
|
-
const deviceId = randomBytes.toString(
|
|
316
|
+
const deviceId = randomBytes.toString("hex").toUpperCase();
|
|
311
317
|
return deviceId;
|
|
312
318
|
}
|
|
313
319
|
|
|
@@ -315,21 +321,22 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
315
321
|
* 网易云音乐 ID 加密
|
|
316
322
|
*/
|
|
317
323
|
_encryptId(id) {
|
|
318
|
-
const magic =
|
|
319
|
-
const song_id = String(id).split(
|
|
320
|
-
|
|
324
|
+
const magic = "3go8&$8*3*3h0k(2)2".split("");
|
|
325
|
+
const song_id = String(id).split("");
|
|
326
|
+
|
|
321
327
|
for (let i = 0; i < song_id.length; i++) {
|
|
322
328
|
song_id[i] = String.fromCharCode(
|
|
323
329
|
song_id[i].charCodeAt(0) ^ magic[i % magic.length].charCodeAt(0)
|
|
324
330
|
);
|
|
325
331
|
}
|
|
326
|
-
|
|
327
|
-
const result = crypto
|
|
328
|
-
.
|
|
329
|
-
.
|
|
330
|
-
.
|
|
331
|
-
.replace(
|
|
332
|
-
|
|
332
|
+
|
|
333
|
+
const result = crypto
|
|
334
|
+
.createHash("md5")
|
|
335
|
+
.update(song_id.join(""), "binary")
|
|
336
|
+
.digest("base64")
|
|
337
|
+
.replace(/\//g, "_")
|
|
338
|
+
.replace(/\+/g, "-");
|
|
339
|
+
|
|
333
340
|
return result;
|
|
334
341
|
}
|
|
335
342
|
|
|
@@ -337,11 +344,11 @@ export default class NeteaseProvider extends BaseProvider {
|
|
|
337
344
|
* 大数运算相关工具方法
|
|
338
345
|
*/
|
|
339
346
|
_bchexdec(hex) {
|
|
340
|
-
return BigInt(
|
|
347
|
+
return BigInt("0x" + hex);
|
|
341
348
|
}
|
|
342
349
|
|
|
343
350
|
_str2hex(str) {
|
|
344
|
-
return Buffer.from(str,
|
|
351
|
+
return Buffer.from(str, "utf8").toString("hex");
|
|
345
352
|
}
|
|
346
353
|
|
|
347
354
|
/**
|