├── README.md ├── app.js ├── crypto.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # netmusic-node 2 | 网易云音乐接口 3 | 4 | ``` 5 | npm i 6 | 7 | node app.js或者pm2 forever之类启动 8 | 9 | ``` 10 | 11 | 直接访问服务器地址 12 | 如http://localhost:3000/v1/fm //fm电台 13 | 14 | ## 完整应用实例 15 | [网易云音乐-微信小程序](https://github.com/sqaiyan/NeteaseMusicWxMiniApp) 16 | 17 | [网易云音乐-VUE版本spa](https://github.com/sqaiyan/neteasemusic) 18 | 19 | 欢迎star issue 20 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var Encrypt = require('./crypto.js'); 2 | var express = require('express'); 3 | var http = require('http'); 4 | var crypto = require('crypto'); 5 | var reqhttp = require("request"); 6 | var app = express(); 7 | var dir = "/v1"; 8 | var cookie = null; 9 | var user = {}; 10 | var jsessionid = randomString('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKMNOPQRSTUVWXYZ\\/+',176) + ':' + (new Date).getTime(); 11 | var nuid = randomString('0123456789abcdefghijklmnopqrstuvwxyz',32); 12 | function randomString(pattern, length){ 13 | return Array.apply(null, {length: length}).map(() => (pattern[Math.floor(Math.random() * pattern.length)])).join(''); 14 | } 15 | 16 | var baseCookie=`JSESSIONID-WYYY=${jsessionid}; _iuqxldmzr_=32; _ntes_nnid=${nuid},${(new Date).getTime()}; _ntes_nuid=${nuid}`; 17 | function createWebAPIRequest(path, data, c, response, method) { 18 | method = method ? method : "POST" 19 | var music_req = ''; 20 | var cryptoreq = Encrypt(data); 21 | var http_client = http.request({ 22 | hostname: 'music.163.com', 23 | method: method, 24 | path: path, 25 | headers: { 26 | 'Accept': '*/*', 27 | 'Accept-Language': 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4', 28 | 'Connection': 'keep-alive', 29 | 'Content-Type': 'application/x-www-form-urlencoded', 30 | 'Referer': 'http://music.163.com', 31 | 'Host': 'music.163.com', 32 | 'Cookie': cookie, 33 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/602.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/602.1' 34 | } 35 | }, function(res) { 36 | res.on('error', function(err) { 37 | response.status(502).send('fetch error'); 38 | }); 39 | res.setEncoding('utf8'); 40 | if(res.statusCode != 200) { 41 | createWebAPIRequest(path, data, c, response, method); 42 | return; 43 | } else { 44 | res.on('data', function(chunk) { 45 | music_req += chunk; 46 | }); 47 | res.on('end', function() { 48 | if(music_req == '') { 49 | createWebAPIRequest(path, data, c, response, method); 50 | return; 51 | } 52 | if(res.headers['set-cookie']) { 53 | cookie =baseCookie +';'+ res.headers['set-cookie']; 54 | response.send({ 55 | code: 200, 56 | i: JSON.parse(music_req) 57 | }); 58 | user = JSON.parse(music_req) 59 | return; 60 | } 61 | response.send(music_req); 62 | }) 63 | } 64 | }); 65 | http_client.write('params=' + cryptoreq.params + '&encSecKey=' + cryptoreq.encSecKey); 66 | http_client.end(); 67 | } 68 | 69 | function createRequest(path, method, data, callback) { 70 | var ne_req = ''; 71 | var http_client = http.request({ 72 | hostname: 'music.163.com', 73 | method: method, 74 | path: path, 75 | headers: { 76 | 'Referer': 'http://music.163.com', 77 | 'Cookie': 'appver=1.5.6', 78 | 'Content-Type': 'application/x-www-form-urlencoded', 79 | }, 80 | }, function(res) { 81 | res.setEncoding('utf8'); 82 | res.on('data', function(chunk) { 83 | ne_req += chunk; 84 | }); 85 | res.on('end', function() { 86 | callback(ne_req); 87 | }) 88 | }); 89 | if(method == 'POST') { 90 | http_client.write(data); 91 | } 92 | http_client.end(); 93 | } 94 | app.get(dir + '/mine', function(request, response) { 95 | response.send(user); 96 | }); 97 | //手机登录 98 | app.get(dir + '/login/cellphone', function(request, response) { 99 | var phone = request.query.phone; 100 | var md5sum = crypto.createHash('md5'); 101 | md5sum.update(request.query.password); 102 | var data = { 103 | 'phone': phone, 104 | 'password': md5sum.digest('hex'), 105 | 'rememberLogin': 'true' 106 | }; 107 | createWebAPIRequest('/weapi/login/cellphone', data, null, response) 108 | }); 109 | //邮箱登录-已失效 110 | app.get(dir + '/login', function(request, response) { 111 | var email = request.query.email; 112 | var md5sum = crypto.createHash('md5'); 113 | md5sum.update(request.query.password); 114 | var data = { 115 | 'username': email, 116 | 'password': md5sum.digest('hex'), 117 | 'rememberLogin': 'true' 118 | }; 119 | createWebAPIRequest('/weapi/login', data, null, response) 120 | }); 121 | 122 | //登录信息刷新 123 | app.get(dir + '/login/refresh', function(request, response) { 124 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 125 | var csrf = "" 126 | for(i in cookie) { 127 | if(cookie[i].name == '__csrf') { 128 | csrf = cookie.value 129 | } 130 | } 131 | csrf = request.query.t 132 | var data = { 133 | "csrf_token": csrf 134 | }; 135 | createWebAPIRequest('/weapi/login/token/refresh?csrf_token=' + csrf, data, cookie, response) 136 | }); 137 | 138 | //banner-获取是老数据,基本无用 139 | app.get(dir + '/banner', function(request, response) { 140 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 141 | var data = { 142 | "csrf_token": "" 143 | } 144 | createWebAPIRequest('/api/v2/banner/get', data, cookie, response, 'GET') 145 | }); 146 | 147 | //歌单类型列表 148 | app.get(dir + '/playlist/catlist', function(request, response) { 149 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 150 | var data = { 151 | "csrf_token": "" 152 | }; 153 | createWebAPIRequest('/weapi/playlist/catalogue', data, cookie, response) 154 | }) 155 | //歌单类型列表-热门类型 156 | app.get(dir + '/playlist/hot', function(request, response) { 157 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 158 | var data = {}; 159 | createWebAPIRequest('/api/playlist/hottags', data, cookie, response) 160 | }) 161 | 162 | //推荐新音乐 163 | app.get(dir + '/personalized/newsong', function(request, response) { 164 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 165 | var data = { 166 | type: "recommend" 167 | }; 168 | createWebAPIRequest('/api/personalized/newsong', data, cookie, response) 169 | }) 170 | //推荐歌单 171 | app.get(dir + '/personalized', function(request, response) { 172 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 173 | var data = {}; 174 | createWebAPIRequest('/api/personalized/playlist', data, cookie, response) 175 | }) 176 | //推荐mv 177 | app.get(dir + '/personalized/mv', function(request, response) { 178 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 179 | var data = {}; 180 | createWebAPIRequest('/api/personalized/mv', data, cookie, response) 181 | }) 182 | //独家放送 183 | app.get(dir + '/personalized/privatecontent', function(request, response) { 184 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 185 | var data = {}; 186 | createWebAPIRequest('/api/personalized/privatecontent', data, cookie, response) 187 | }) 188 | //推荐dj 189 | app.get(dir + '/personalized/djprogram', function(request, response) { 190 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 191 | var data = {}; 192 | createWebAPIRequest('/api/personalized/djprogram', data, cookie, response) 193 | }) 194 | //推荐dj 195 | app.get(dir + '/personalized/topic', function(request, response) { 196 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 197 | var data = {}; 198 | createWebAPIRequest('/weapi/personalized/topic', data, cookie, response) 199 | }) 200 | 201 | //每日推荐歌曲 202 | app.get(dir + '/recommend/songs', function(request, response) { 203 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 204 | var data = { 205 | "offset": 0, 206 | "total": true, 207 | "limit": 20, 208 | "csrf_token": "" 209 | }; 210 | createWebAPIRequest('/weapi/v1/discovery/recommend/songs', data, cookie, response) 211 | }); 212 | //取消推荐 213 | app.get(dir + '/recommend/dislike', function(request, response) { 214 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 215 | var data = { 216 | resId: request.query.id, 217 | resType: request.query.type, 218 | alg: request.query.alg, //'itembased2', 219 | "csrf_token": "" 220 | }; 221 | createWebAPIRequest('/weapi/discovery/recommend/dislike', data, cookie, response) 222 | }); 223 | 224 | // 每日推荐歌单 225 | app.get(dir + '/recommend/resource', function(request, response) { 226 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 227 | var data = { 228 | 'offset': 0, 229 | 'limit': 20, 230 | 'total': 'True', 231 | "csrf_token": "" 232 | }; 233 | createWebAPIRequest('/weapi/v1/discovery/recommend/resource', data, cookie, response) 234 | }); 235 | //收藏单曲到歌单,从歌单删除歌曲 op=del,add;pid=歌单id,tracks=歌曲id 236 | app.get(dir + '/playlist/tracks', function(request, response) { 237 | var op = request.query.op 238 | var pid = request.query.pid; 239 | var tracks = request.query.tracks; 240 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 241 | var data = { 242 | "op": op, 243 | "pid": pid, 244 | "tracks": tracks, 245 | "trackIds": JSON.stringify([tracks]), 246 | "csrf_token": "", 247 | }; 248 | createWebAPIRequest('/weapi/playlist/manipulate/tracks', data, cookie, response) 249 | }); 250 | //搜索 251 | app.get(dir + '/search', function(request, response) { 252 | var keywords = request.query.keywords || ''; 253 | var type = request.query.type || 1; 254 | var offset = request.query.offset || '0'; 255 | var limit = request.query.limit || 20; 256 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 257 | var data = { 258 | "s": keywords, 259 | "offset": offset, 260 | "limit": limit, 261 | "type": type 262 | }; 263 | createWebAPIRequest('/weapi/cloudsearch/get/web', data, cookie, response) 264 | }); 265 | //搜索 multimatch 266 | app.get(dir + '/search/multimatch', function(request, response) { 267 | var keywords = request.query.keywords || ''; 268 | var type = request.query.type || 1; 269 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 270 | var data = { 271 | "csrf_token": "", 272 | type: type || 1, 273 | s: keywords || '' 274 | }; 275 | createWebAPIRequest('/weapi/search/suggest/multimatch', data, cookie, response) 276 | }); 277 | //搜索 hot 278 | app.get(dir + '/search/hot', function(request, response) { 279 | var data = { 280 | type: 1111 281 | }; 282 | createWebAPIRequest('/weapi/search/hot', data, cookie, response) 283 | }); 284 | //搜索 suggest 285 | app.get(dir + '/search/suggest', function(request, response) { 286 | var keywords = request.query.keywords || ''; 287 | var type = request.query.type || 1; 288 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 289 | var data = { 290 | "csrf_token": "", 291 | type: type || 1, 292 | s: keywords || '' 293 | }; 294 | createWebAPIRequest('/weapi/search/suggest/web', data, cookie, response) 295 | }); 296 | //fm, 297 | app.get(dir + '/fm', function(request, response) { 298 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 299 | var data = { 300 | "csrf_token": "" 301 | } 302 | createWebAPIRequest('/weapi/v1/radio/get', data, cookie, response) 303 | }); 304 | 305 | //歌词 306 | app.get(dir + '/lyric', function(request, response) { 307 | var id = request.query.id; 308 | createRequest('/api/song/lyric?os=osx&id=' + id + '&lv=-1&kv=-1&tv=-1', 'GET', null, function(res) { 309 | response.setHeader("Content-Type", "application/json"); 310 | response.send(res); 311 | }); 312 | }); 313 | 314 | //热门歌手 315 | app.get(dir + '/top/artist', function(request, response) { 316 | var data = { 317 | 'offset': request.query.offset, 318 | 'total': false, 319 | "type": request.query.type, 320 | 'limit': request.query.limit 321 | } 322 | createWebAPIRequest('/weapi/artist/top', data, cookie, response); 323 | // createRequest('/api/artist/top, 'GET', null, function(res) { 324 | // response.setHeader("Content-Type", "application/json"); 325 | // response.send(res); 326 | // }); 327 | }); 328 | //新歌上架 ,type ALL, ZH,EA,KR,JP 329 | app.get(dir + '/top/songs', function(request, response) { 330 | var data = { 331 | 'type': request.query.type, 332 | 'area': request.query.type, 333 | 'cat': request.query.type, 334 | "csrf_token": "" 335 | } 336 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 337 | createWebAPIRequest('/weapi/v1/discovery/new/songs', data, cookie, response); 338 | }); 339 | //新碟上架 ,type ALL, ZH,EA,KR,JP 340 | app.get(dir + '/top/album', function(request, response) { 341 | var data = { 342 | 'offset': request.query.offset, 343 | 'total': true, 344 | 'limit': request.query.limit, 345 | 'area': request.query.type, 346 | "csrf_token": "" 347 | } 348 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 349 | createWebAPIRequest('/weapi/album/new', data, cookie, response); 350 | }); 351 | //mv 排行,type ALL, ZH,EA,KR,JP 352 | app.get(dir + '/top/mv', function(request, response) { 353 | var data = { 354 | 'offset': request.query.offset, 355 | 'total': true, 356 | 'limit': request.query.limit, 357 | 'area': request.query.type, 358 | 'type': request.query.type, 359 | "csrf_token": "" 360 | } 361 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 362 | createWebAPIRequest('/weapi/mv/toplist', data, cookie, response); 363 | }); 364 | //mv 最新mv,type ALL, ZH,EA,KR,JP 365 | app.get(dir + '/top/mv/first', function(request, response) { 366 | var data = { 367 | 'offset': request.query.offset, 368 | 'total': true, 369 | 'limit': request.query.limit, 370 | 'area': request.query.type, 371 | "csrf_token": "" 372 | } 373 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 374 | createWebAPIRequest('/weapi/mv/first', data, cookie, response); 375 | }); 376 | //分类歌单 377 | app.get(dir + '/top/playlist', function(request, response) { 378 | var data = { 379 | 'offset': request.query.offset, 380 | 'order': request.query.order || 'hot', 381 | 'limit': request.query.limit, 382 | 'cat': request.query.type, 383 | "csrf_token": "" 384 | } 385 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 386 | createWebAPIRequest('/weapi/playlist/list', data, cookie, response); 387 | }); 388 | //精品歌单 389 | app.get(dir + '/top/playlist/highquality', function(request, response) { 390 | var data = { 391 | 'cat': request.query.type, 392 | 'offset': request.query.offset, 393 | "limit": request.query.limit, 394 | "csrf_token": "" 395 | } 396 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 397 | createWebAPIRequest('/weapi/playlist/highquality/list', data, cookie, response); 398 | }); 399 | //simi ,相似歌单,歌曲,关注的用户 400 | app.get(dir + '/simi/playlist', function(request, response) { 401 | var data = { 402 | 'songid': request.query.id, 403 | "csrf_token": "" 404 | } 405 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 406 | createWebAPIRequest('/weapi/discovery/simiPlaylist', data, cookie, response); 407 | }); 408 | app.get(dir + '/simi/song', function(request, response) { 409 | var data = { 410 | 'songid': request.query.id, 411 | "csrf_token": "" 412 | } 413 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 414 | createWebAPIRequest('/weapi/v1/discovery/simiSong', data, cookie, response); 415 | }); 416 | app.get(dir + '/simi/user', function(request, response) { 417 | var data = { 418 | 'songid': request.query.id, 419 | "csrf_token": "" 420 | } 421 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 422 | createWebAPIRequest('/weapi/discovery/simiUser', data, cookie, response); 423 | }); 424 | //评论 425 | app.get(dir + '/comments', function(request, response) { 426 | var id = request.query.id; 427 | var limit = request.query.limit; 428 | var offset = request.query.offset; 429 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 430 | var type = request.query.type == 'hot' ? 'hotcomments' : 'comments'; 431 | var data = { 432 | "rid": id, 433 | "offset": offset, 434 | "limit": limit, 435 | "total": false, 436 | "csrf_token": "" 437 | }; 438 | createWebAPIRequest('/weapi/v1/resource/' + type + '/' + id, data, cookie, response) 439 | }); 440 | 441 | //艺术家 442 | app.get(dir + '/artist', function(request, response) { 443 | var id = request.query.id; 444 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 445 | var data = { 446 | "csrf_token": "" 447 | }; 448 | createWebAPIRequest('/weapi/v1/artist/' + id, data, cookie, response) 449 | }); 450 | //关注歌手 451 | app.get(dir + '/artist/sub', function(req, response) { 452 | var cookie = req.get('Cookie') ? req.get('Cookie') : (req.query.cookie ? req.query.cookie : ''); 453 | var type = req.query.type; 454 | var url = '/weapi/artist/'; 455 | var data; 456 | if(type == 1) { 457 | url += "sub"; 458 | data = { 459 | artistId: req.query.id 460 | } 461 | } else { 462 | url += "unsub"; 463 | data = { 464 | artistIds: [req.query.id], 465 | } 466 | } 467 | createWebAPIRequest(url, data, cookie, response) 468 | 469 | }) 470 | //艺术家-专辑 471 | app.get(dir + '/artist/album', function(request, response) { 472 | var id = request.query.id; 473 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 474 | var data = { 475 | "offset": request.query.offset, 476 | "limit": request.query.limit, 477 | "csrf_token": "" 478 | }; 479 | createWebAPIRequest('/weapi/artist/albums/' + id, data, cookie, response) 480 | }); 481 | //艺术家-mv 482 | app.get(dir + '/artist/mv', function(request, response) { 483 | var id = request.query.id; 484 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 485 | var data = { 486 | artistId: id, 487 | "total": true, 488 | "offset": request.query.offset, 489 | "limit": request.query.limit, 490 | "csrf_token": "" 491 | }; 492 | createWebAPIRequest('/weapi/artist/mvs', data, cookie, response) 493 | }); 494 | //艺术家 信息 495 | app.get(dir + '/artist/desc', function(request, response) { 496 | var id = request.query.id; 497 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 498 | var data = { 499 | id: id, 500 | "csrf_token": "" 501 | }; 502 | createWebAPIRequest('/weapi/artist/introduction', data, cookie, response) 503 | }); 504 | //艺术家 ,相似歌手 505 | app.get(dir + '/artist/simi', function(request, response) { 506 | var id = request.query.id; 507 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 508 | var data = { 509 | artistid: id, 510 | "csrf_token": "" 511 | }; 512 | createWebAPIRequest('/weapi/discovery/simiArtist', data, cookie, response) 513 | }); 514 | //个人信息,歌单,收藏,mv,dj数量 515 | app.get(dir + '/user/subcount', function(request, response) { 516 | var id = request.query.id; 517 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 518 | var data = { 519 | userId: id, 520 | "csrf_token": "" 521 | }; 522 | createWebAPIRequest('/weapi/subcount', data, cookie, response) 523 | }); 524 | //云盘数据 525 | app.get(dir + '/user/cloud', function(request, response) { 526 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 527 | console.log(request.get('Cookie') + '\n' + request.query.cookie + '\n' + cookie); 528 | var data = { 529 | limit: request.query.limit, 530 | offset: request.query.offset, 531 | "csrf_token": "" 532 | }; 533 | createWebAPIRequest('/weapi/v1/cloud/get', data, request.query.cookie, response) 534 | }); 535 | //云盘数据 536 | app.get(dir + '/user/cloud/search', function(request, response) { 537 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 538 | var data = { 539 | byids: request.query.id, 540 | id: request.query.id, 541 | "csrf_token": "" 542 | }; 543 | createWebAPIRequest('/weapi/v1/cloud/get/byids', data, cookie, response) 544 | }); 545 | //mv detail 546 | app.get(dir + '/mv', function(request, response) { 547 | var id = request.query.id; 548 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 549 | var data = { 550 | id: id, 551 | "csrf_token": "" 552 | }; 553 | //createWebAPIRequest('/weapi/v1/mv/detail/', data, cookie, response) 554 | createWebAPIRequest('/api/mv/detail?id=' + id + '&type=mp4', data, cookie, response) 555 | }); 556 | //simi mv 557 | app.get(dir + '/mv/simi', function(request, response) { 558 | var id = parseInt(request.query.id); 559 | var br = parseInt(request.query.br); 560 | var data = { 561 | mvid: id, 562 | "csrf_token": "" 563 | }; 564 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 565 | createWebAPIRequest('/weapi/discovery/simiMV', data, cookie, response) 566 | }); 567 | //mv播放地址 568 | app.get(dir + '/mv/url', function(request, response) { 569 | // var id = parseInt(request.query.id); 570 | // var br = parseInt(request.query.br); 571 | // var data = { 572 | // "ids": [id], 573 | // id: id, 574 | // "br": br, 575 | // "csrf_token": "" 576 | // }; 577 | // var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 578 | // createWebAPIRequest('/weapi/song/enhance/play/mv/url', data, cookie, response) 579 | var url = request.query.url 580 | var headers = { 581 | "Referer": "http://music.163.com/", 582 | "Cookie": "appver=1.5.0.75771;", 583 | 'Content-Type': 'video/mp4', 584 | 'Location': url 585 | } 586 | var options = { 587 | header: headers, 588 | url: url 589 | } 590 | reqhttp(options).pipe(response) 591 | }); 592 | //单曲详情 593 | app.get(dir + '/music/detail', function(request, response) { 594 | var id = parseInt(request.query.id); 595 | var data = { 596 | "id": id, 597 | 'c': JSON.stringify([{ 598 | id: id 599 | }]), 600 | "ids": '[' + id + ']', 601 | "csrf_token": "" 602 | }; 603 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 604 | createWebAPIRequest('/weapi/v3/song/detail', data, cookie, response) 605 | }); 606 | //专辑详情 607 | app.get(dir + '/album/detail', function(request, response) { 608 | var id = parseInt(request.query.id); 609 | var data = { 610 | "csrf_token": "" 611 | }; 612 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 613 | createWebAPIRequest('/weapi/v1/album/' + id, data, cookie, response) 614 | }); 615 | //单曲播放地址 616 | app.get(dir + '/music/url', function(request, response) { 617 | var id = parseInt(request.query.id); 618 | var br = parseInt(request.query.br); 619 | var data = { 620 | "ids": [id], 621 | "br": br, 622 | "csrf_token": "" 623 | }; 624 | createWebAPIRequest('/weapi/song/enhance/player/url', data, null, response) 625 | }); 626 | //用户详情 627 | app.get(dir + '/user/detail', function(request, response) { 628 | var id = parseInt(request.query.uid); 629 | var data = { 630 | "csrf_token": "" 631 | }; 632 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 633 | createWebAPIRequest('/api/v1/user/detail/' + id, data, cookie, response, 'GET') 634 | }); 635 | //用户歌单 636 | app.get(dir + '/user/playlist', function(request, response) { 637 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 638 | var data = { 639 | "offset": request.query.offset || '0', 640 | "uid": request.query.uid, 641 | "limit": request.query.limit || 20, 642 | "csrf_token": "" 643 | }; 644 | createWebAPIRequest('/weapi/user/playlist', data, cookie, response) 645 | }); 646 | //用户电台 647 | app.get(dir + '/user/radio', function(request, response) { 648 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 649 | var data = { 650 | "userId": request.query.uid, 651 | "csrf_token": "" 652 | }; 653 | createWebAPIRequest('/weapi/djradio/get/byuser', data, cookie, response) 654 | }); 655 | //用户关注列表 656 | app.get(dir + '/user/follows', function(request, response) { 657 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 658 | var data = { 659 | offset: request.query.offset || '0', 660 | limit: request.query.limit || 1000, 661 | order: true 662 | } 663 | createWebAPIRequest('/weapi/user/getfollows/' + request.query.id, data, cookie, response) 664 | }); 665 | //关注,取消关注,用户 666 | app.get(dir + '/follow', function(request, response) { 667 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 668 | var data = { 669 | "csrf_token": "" 670 | } 671 | var url = request.query.type == 'add' ? 'follow' : "delfollow" 672 | createWebAPIRequest('/weapi/user/' + url + '/' + request.query.id, data, cookie, response) 673 | }); 674 | //用户粉丝列表 675 | app.get(dir + '/user/followeds', function(request, response) { 676 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 677 | var data = { 678 | 'userId': request.query.id, 679 | "csrf_token": "" 680 | } 681 | createWebAPIRequest('/weapi/user/getfolloweds/', data, cookie, response) 682 | }); 683 | //歌单详情 684 | app.get(dir + '/playlist/detail', function(request, response) { 685 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 686 | var data = { 687 | "id": request.query.id, 688 | "offset": request.query.offset || '0', 689 | "total": false, 690 | "n": request.query.limit || 20, 691 | "limit": request.query.limit || 20, 692 | "csrf_token": "" 693 | }; 694 | createWebAPIRequest('/weapi/v3/playlist/detail', data, cookie, response) 695 | 696 | }); 697 | //歌单详情-旧,获取封面 698 | app.get(dir + '/playlist/img', function(request, response) { 699 | createWebAPIRequest('/api/playlist/detail?id=' + request.query.id, null, null, response) 700 | }); 701 | 702 | //签到 703 | app.get(dir + '/daily_signin', function(request, response) { 704 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 705 | var data = { 706 | 'type': request.query.type, 707 | } 708 | createWebAPIRequest('/weapi/point/dailyTask', data, cookie, response) 709 | 710 | }); 711 | 712 | //听歌记录 uid,type 0所以,1 week, 713 | app.get(dir + '/record', function(request, response) { 714 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 715 | var data = { 716 | 'type': request.query.type, 717 | uid: request.query.uid, 718 | "csrf_token": "" 719 | } 720 | createWebAPIRequest('/weapi/v1/play/record', data, cookie, response) 721 | }); 722 | //红心歌曲 723 | app.get(dir + '/likelist', function(request, response) { 724 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 725 | var data = { 726 | uid: request.query.uid, 727 | "csrf_token": "" 728 | } 729 | createWebAPIRequest('/weapi/song/like/get', data, cookie, response) 730 | }); 731 | //红心歌曲 732 | app.get(dir + '/like/album', function(request, response) { 733 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 734 | var data = { 735 | uid: request.query.uid, 736 | "csrf_token": "" 737 | } 738 | createWebAPIRequest('/weapi/album/like/get', data, cookie, response) 739 | }); 740 | //program-like 741 | app.get(dir + '/program/like', function(request, response) { 742 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 743 | var data = { 744 | 'threadId': request.query.id, 745 | "csrf_token": "" 746 | } 747 | createWebAPIRequest('/weapi/resource/like', data, cookie, response) 748 | }); 749 | //电台类型列表 750 | app.get(dir + '/djradio/catelist', function(request, response) { 751 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 752 | var data = { 753 | "csrf_token": "" 754 | } 755 | createWebAPIRequest('/weapi/djradio/category/get', data, cookie, response) 756 | }); 757 | //推荐节目 758 | app.get(dir + '/program/recommend', function(request, response) { 759 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 760 | var data = { 761 | cateId: request.query.type, 762 | "csrf_token": "" 763 | } 764 | createWebAPIRequest('/weapi/program/recommend/v1', data, cookie, response) 765 | }); 766 | //精选电台 767 | app.get(dir + '/djradio/recommend', function(request, response) { 768 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 769 | var data = { 770 | "csrf_token": "" 771 | } 772 | createWebAPIRequest('/weapi/djradio/recommend/v1', data, cookie, response) 773 | }); 774 | //精选电台-分类电台 775 | app.get(dir + '/djradio/recommend/type', function(request, response) { 776 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 777 | var data = { 778 | cateId: request.query.type, 779 | "csrf_token": "" 780 | } 781 | createWebAPIRequest('/weapi/djradio/recommend', data, cookie, response) 782 | }); 783 | //分类电台 784 | app.get(dir + '/djradio/hot', function(request, response) { 785 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 786 | var data = { 787 | 'cat': request.query.type, 788 | cateId: request.query.type, 789 | type: request.query.type, 790 | categoryId: request.query.type, 791 | category: request.query.type, 792 | limit: request.query.limit, 793 | offset: request.query.offset, 794 | "csrf_token": "" 795 | } 796 | createWebAPIRequest('/weapi/djradio/hot/v1', data, cookie, response) 797 | }); 798 | //dj单期节目program-detail 799 | app.get(dir + '/program/detail', function(request, response) { 800 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 801 | var data = { 802 | 'id': request.query.id, 803 | "csrf_token": "" 804 | } 805 | createWebAPIRequest('/weapi/dj/program/detail', data, cookie, response) 806 | }); 807 | //dj主播 radio 808 | app.get(dir + '/dj/program', function(request, response) { 809 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 810 | var data = { 811 | 'asc': request.query.asc, 812 | 'radioId': request.query.id, 813 | 'limit': request.query.limit, 814 | 'offset': request.query.offset, 815 | "csrf_token": "" 816 | } 817 | createWebAPIRequest('/weapi/dj/program/byradio', data, cookie, response) 818 | }); 819 | 820 | //djradio detail 821 | app.get(dir + '/dj/detail', function(request, response) { 822 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 823 | var data = { 824 | 'id': request.query.id, 825 | "csrf_token": "" 826 | } 827 | createWebAPIRequest('/weapi/djradio/get', data, cookie, response) 828 | }); 829 | 830 | //用户动态 831 | app.get(dir + '/event/get', function(request, response) { 832 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 833 | var data = { 834 | 'time': -1, 835 | 'offset': request.query.offset || '0', 836 | 'pagesize': request.query.limit || 20, 837 | 'getcounts': true, 838 | "csrf_token": "" 839 | } 840 | createWebAPIRequest('/weapi/event/get/' + request.query.id, data, cookie, response) 841 | }); 842 | //朋友 843 | app.get(dir + '/event/list', function(request, response) { 844 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 845 | var data = { 846 | 'time': -1, 847 | 'offset': request.query.offset || '0', 848 | 'pagesize': request.query.limit || 20, 849 | 'getcounts': true, 850 | "csrf_token": "" 851 | } 852 | createWebAPIRequest('/weapi/v2/event/get/', data, cookie, response) 853 | }); 854 | //dj 订阅 855 | app.get(dir + '/dj/sub', function(request, response) { 856 | var id = request.query.id; 857 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 858 | var data = { 859 | "id": id, 860 | "csrf_token": "" 861 | } 862 | createWebAPIRequest("/weapi/djradio/" + (request.query.t == 1 ? 'sub' : 'unsub'), data, cookie, response) 863 | }); 864 | //program like act 865 | app.get(dir + '/resource/like', function(request, response) { 866 | var id = request.query.id; 867 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 868 | var data = { 869 | "threadId": id, 870 | "csrf_token": "" 871 | } 872 | createWebAPIRequest("/weapi/resource/" + (request.query.t == 1 ? 'like' : 'unlike'), data, cookie, response) 873 | }); 874 | //comment like act 875 | app.get(dir + '/comment/like', function(request, response) { 876 | var id = request.query.id; 877 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 878 | var data = { 879 | "threadId": request.query.origin, 880 | commentId: id, 881 | "csrf_token": "" 882 | } 883 | createWebAPIRequest("/weapi/v1/comment/" + (request.query.t == 1 ? 'like' : 'unlike'), data, cookie, response) 884 | }); 885 | //歌曲喜欢和删除 op=like or trash,songid, 886 | app.get(dir + '/song/tracks', function(request, response) { 887 | var op = request.query.op 888 | var pid = request.query.id; 889 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 890 | var url = op == 'like' ? '/weapi/radio/like' : '/weapi/radio/trash/add' 891 | var data = op == 'like' ? { 892 | "alg": request.query.r != 'del' ? 'itembased' : 'RT', 893 | "trackId": pid, 894 | "like": request.query.r != 'del' ? 'true' : 'false', 895 | "time": 2, 896 | "csrf_token": "" 897 | } : { 898 | "alg": 'RT', 899 | "songId": pid, 900 | "time": 2, 901 | "csrf_token": "" 902 | }; 903 | createWebAPIRequest(url, data, cookie, response) 904 | }); 905 | 906 | //用户电台 907 | app.get(dir + '/user/dj', function(request, response) { 908 | var id = request.query.id; 909 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 910 | var data = { 911 | 'offset': request.query.offset || '0', 912 | 'limit': request.query.limit || 20, 913 | "csrf_token": "" 914 | } 915 | createWebAPIRequest('/weapi/dj/program/' + id, data, cookie, response) 916 | }); 917 | 918 | app.get(dir + '/log/web', function(request, response) { 919 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 920 | var data = { 921 | "action": request.query.action, 922 | "json": request.query.json, 923 | "csrf_token": "", 924 | }; 925 | createWebAPIRequest('/weapi/log/web', data, cookie, response) 926 | }); 927 | app.get(dir + '/id2url', function(req, res) { 928 | res.setHeader("Content-Type", "application/json"); 929 | res.send(id2Url(req.query.id)); 930 | }) 931 | //toplist 932 | app.get(dir + '/toplist', function(request, response) { 933 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 934 | var data = { 935 | "csrf_token": "", 936 | }; 937 | createWebAPIRequest('/weapi/toplist', data, cookie, response) 938 | }) 939 | //playlistall 940 | app.get(dir + '/playlist/all', function(request, response) { 941 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 942 | var data = { 943 | "csrf_token": "", 944 | }; 945 | createWebAPIRequest('/weapi/playlist/category/list', data, cookie, response) 946 | }) 947 | 948 | //排行榜详细 949 | app.get(dir + '/toplist/detail', function(request, response) { 950 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 951 | var data = { 952 | id: request.query.id, 953 | limit: 20, 954 | "csrf_token": "", 955 | }; 956 | createWebAPIRequest('/weapi/toplist/detail', data, cookie, response) 957 | }) 958 | //艺术家分类 959 | app.get(dir + '/toplist/artist', function(request, response) { 960 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 961 | var data = { 962 | type: request.query.type, 963 | "csrf_token": "", 964 | }; 965 | createWebAPIRequest('/weapi/toplist/artist', data, cookie, response) 966 | }) 967 | 968 | //我的收藏-歌手 969 | app.get(dir + '/sublist/artist', function(request, response) { 970 | var data = { 971 | offset: request.query.offset || 0, 972 | limit: request.query.limit || 0 973 | } 974 | createWebAPIRequest('/weapi/artist/sublist', data, null, response) 975 | }) 976 | //我的收藏-专辑 977 | app.get(dir + '/sublist/album', function(request, response) { 978 | var data = { 979 | offset: request.query.offset || 0, 980 | limit: request.query.limit || 0 981 | } 982 | createWebAPIRequest('/weapi/album/sublist', data, null, response) 983 | }) 984 | //我的收藏-MV 985 | app.get(dir + '/sublist/mv', function(request, response) { 986 | var data = { 987 | offset: request.query.offset || 0, 988 | limit: request.query.limit || 0 989 | } 990 | createWebAPIRequest('/weapi/mv/sublist', data, null, response) 991 | }) 992 | //我的收藏-歌手 993 | app.get(dir + '/sublist/radio', function(request, response) { 994 | var data = { 995 | offset: request.query.offset || 0, 996 | limit: request.query.limit || 0 997 | } 998 | createWebAPIRequest('/weapi/djradio/get/subed', data, null, response) 999 | }) 1000 | //我的收藏-专栏 1001 | app.get(dir + '/sublist/topic', function(request, response) { 1002 | var data = { 1003 | offset: request.query.offset || 0, 1004 | limit: request.query.limit || 0 1005 | } 1006 | createWebAPIRequest('/weapi/topic/sublist', data, null, response) 1007 | }) 1008 | //短视频-播放地址 1009 | app.get(dir + '/video/playurl', function(request, response) { 1010 | var data = { 1011 | ids: JSON.stringify([request.query.id]), 1012 | resolution: request.query.br, 1013 | csrf_token: '' 1014 | } 1015 | createWebAPIRequest('/weapi/cloudvideo/playurl', data, null, response) 1016 | }) 1017 | //短视频-detail 1018 | app.get(dir + '/video/detail', function(request, response) { 1019 | var data = { 1020 | id: request.query.id 1021 | } 1022 | createWebAPIRequest('/weapi/cloudvideo/v1/video/detail', data, null, response) 1023 | }) 1024 | //短视频-simi 1025 | app.get(dir + '/video/rcmd', function(request, response) { 1026 | var data = { 1027 | id: request.query.id, 1028 | type: 1 1029 | } 1030 | createWebAPIRequest('/weapi/cloudvideo/v1/allvideo/rcmd', data, null, response) 1031 | }) 1032 | //短视频-statistic 1033 | app.get(dir + '/video/statistic', function(request, response) { 1034 | var data = { 1035 | id: request.query.id, 1036 | } 1037 | createWebAPIRequest('/weapi/cloudvideo/v1/video/statistic', data, null, response) 1038 | }) 1039 | //topic detail 1040 | app.get(dir + '/topic/detail', function(request, response) { 1041 | var data = { 1042 | id: request.query.id, 1043 | csrf_token: '', 1044 | type: "web", 1045 | mobile: !0 1046 | } 1047 | createWebAPIRequest('/weapi/web/topic/get', data, null, response) 1048 | }) 1049 | //歌单收藏-取消收藏 1050 | app.get(dir + '/playlist/fav', function(request, response) { 1051 | var cookie = request.get('Cookie') ? request.get('Cookie') : (request.query.cookie ? request.query.cookie : ''); 1052 | var data = { 1053 | id: request.query.id, 1054 | csrf_token: '' 1055 | } 1056 | var url = '/weapi/playlist/' + (request.query.type == 1 ? 'subscribe' : 'unsubscribe') + "?csrf_token=''"; 1057 | console.log(url); 1058 | createWebAPIRequest(url, data, cookie, response) 1059 | }) 1060 | app.all('*', function(req, res, next) { 1061 | res.header("Access-Control-Allow-Origin", "*"); 1062 | res.header("Access-Control-Allow-Headers", "X-Requested-With"); 1063 | res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); 1064 | res.header("X-Powered-By", ' 3.2.1') 1065 | res.header("Content-Type", "application/json;charset=utf-8"); 1066 | next(); 1067 | }); 1068 | var server = app.listen(3000, function() { 1069 | console.log("启动App"); 1070 | }); 1071 | 1072 | function id2Url(pic_str) { 1073 | var magic = str2Arr('3go8&$8*3*3h0k(2)2') 1074 | var songId = str2Arr(pic_str) 1075 | for(var i = 0; i < songId.length; i++) { 1076 | songId[i] = songId[i] ^ magic[i % magic.length] 1077 | } 1078 | var md5 = crypto.createHash('md5'); 1079 | md5 = md5.update(arr2Str(songId)) 1080 | console.info(md5); 1081 | var res = md5.digest('base64') 1082 | res = res.replace(/\//g, '_') 1083 | res = res.replace(/\+/, '-') 1084 | return res 1085 | } 1086 | 1087 | function str2Arr(str) { 1088 | var bytes = [] 1089 | for(var i = 0; i < str.length; i++) { 1090 | bytes.push(str.charAt(i).charCodeAt(0)) 1091 | } 1092 | return bytes 1093 | } 1094 | 1095 | function arr2Str(bytes) { 1096 | var str = '' 1097 | for(var i = 0; i < bytes.length; i++) { 1098 | str += String.fromCharCode(bytes[i]) 1099 | } 1100 | return str 1101 | } -------------------------------------------------------------------------------- /crypto.js: -------------------------------------------------------------------------------- 1 | // 参考 https://github.com/darknessomi/musicbox/wiki/ 2 | 'use strict' 3 | const crypto = require('crypto'); 4 | const bigInt = require('big-integer'); 5 | const modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7' 6 | const nonce = '0CoJUm6Qyw8W8jud' 7 | const pubKey = '010001' 8 | 9 | String.prototype.hexEncode = function(){ 10 | var hex, i; 11 | 12 | var result = ""; 13 | for (i=0; i