mirror of
https://gitlab.com/Binaryify/neteasecloudmusicapi.git
synced 2025-05-23 22:37:41 +08:00
upgrade version 2.0,add login api,upgrade api verison,add document and unit test
This commit is contained in:
parent
35f37afd77
commit
a2e4d26401
@ -1,20 +0,0 @@
|
||||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
|
||||
# Change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# We recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
@ -1,6 +1,4 @@
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
|
||||
- 4.0
|
||||
- 6.2
|
||||
|
21
LICENSE
21
LICENSE
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2016 Binaryify
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
77
README.MD
77
README.MD
@ -1,5 +1,5 @@
|
||||
# NeteaseCloudMusicApi
|
||||
一个调用网易云音乐 API 的 node 模块
|
||||
网易云音乐 nodejs 接口
|
||||
<p>
|
||||
<a href="https://www.npmjs.com/package/NeteaseCloudMusicApi"><img src="https://img.shields.io/npm/v/NeteaseCloudMusicApi.svg" alt="Version"></a>
|
||||
<a href="https://www.npmjs.com/package/NeteaseCloudMusicApi"><img src="https://img.shields.io/npm/l/NeteaseCloudMusicApi.svg" alt="License"></a>
|
||||
@ -9,64 +9,35 @@
|
||||
<a href="https://travis-ci.org/Binaryify/NeteaseCloudMusicApi"><img src="https://api.travis-ci.org/Binaryify/NeteaseCloudMusicApi.svg?branch=master" /></a>
|
||||
</p>
|
||||
|
||||

|
||||
|
||||
## Start
|
||||
## 版本新特性
|
||||
增加使用文档,完成项目重构,增加更完善的单元测试,版本升级到2.0,升级 api 到 v2+,支持登录并获取用户信息和创建的歌单,可通过获取音乐 url 接口获取用户歌单里的的音乐,获取每日推荐歌单和每日推荐音乐
|
||||
|
||||
## 环境要求
|
||||
需要 NodeJS 6.0+ 环境
|
||||
|
||||
## 安装
|
||||
``` shell
|
||||
npm install NeteaseCloudMusicApi
|
||||
$ git clone git@github.com:Binaryify/NeteaseCloudMusicApi.git
|
||||
$ npm install
|
||||
```
|
||||
## 运行
|
||||
``` shell
|
||||
$ node app.js
|
||||
```
|
||||
|
||||
## Usage
|
||||
``` javascript
|
||||
var api = require('NeteaseCloudMusicApi').api
|
||||
api.search('年度之歌',function(data){
|
||||
console.log(data)
|
||||
})
|
||||
```
|
||||
or
|
||||
``` javascript
|
||||
import {api} from 'NeteaseCloudMusicApi'
|
||||
api.search('年度之歌',data => {
|
||||
console.log(data)
|
||||
})
|
||||
## 使用文档
|
||||
|
||||
[文档地址](https://binaryify.github.io/NeteaseCloudMusicApi)
|
||||
|
||||
## 单元测试
|
||||
|
||||
``` shell
|
||||
$ npm test
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### search
|
||||
``` javascript
|
||||
api.search(name:String,[callback:function,onlySong:Boolean default:true,limit:Number default:3, offset:Number default:0])
|
||||
```
|
||||
说明:onlySong默认为true,如果为false,则返回一个对象,包含songs和mvs,songs和mvs均为数组
|
||||
|
||||
### lrc
|
||||
``` javascript
|
||||
api.lrc(id:Number,[callback:function,lv:Number default:-1])
|
||||
```
|
||||
|
||||
### song
|
||||
|
||||
``` javascript
|
||||
api.song(id:Number,[callback:function])
|
||||
```
|
||||
|
||||
### getArtistAlbums
|
||||
|
||||
``` javascript
|
||||
api.getArtistAlbums(id:Number,[callback:function,limit:Number default:3, offset:Number default:0])
|
||||
```
|
||||
|
||||
## getAlbums
|
||||
|
||||
``` javascript
|
||||
api.getAlbums(id:Number,[callback:function])
|
||||
```
|
||||
|
||||
## getPlaylists
|
||||
|
||||
``` javascript
|
||||
api.Playlists(id:Number,[callback:function])
|
||||
```
|
||||

|
||||

|
||||
|
||||
## License
|
||||
[The MIT License (MIT)](LICENSE)
|
||||
|
39
app.js
Normal file
39
app.js
Normal file
@ -0,0 +1,39 @@
|
||||
const express = require('express')
|
||||
const http = require('http')
|
||||
const app = express()
|
||||
|
||||
//手机登录
|
||||
app.use('/login/cellphone', require('./router/loginCellphone'))
|
||||
|
||||
app.use('/login', require('./router/login'))
|
||||
// 获取每日推荐歌曲
|
||||
app.use('/recommend/songs', require('./router/recommendSongs'))
|
||||
// 获取每日推荐歌单
|
||||
app.use('/recommend/resource', require('./router/recommendResource'))
|
||||
|
||||
app.use('/lyric', require('./router/lyric'))
|
||||
|
||||
app.use('/user/playlist', require('./router/userPlaylist'))
|
||||
|
||||
app.use('/playlist/detail', require('./router/playlistDetail'))
|
||||
|
||||
app.use('/playlist/tracks', require('./router/playlistTracks'))
|
||||
// 获取音乐 url
|
||||
app.use('/music/url', require('./router/musicUrl'))
|
||||
// 搜歌
|
||||
app.use('/search', require('.//router/search'))
|
||||
|
||||
app.use('/log/web', require('./router/logWeb'))
|
||||
|
||||
process.on('SIGHUP', () => {
|
||||
console.log('server: bye bye')
|
||||
process.exit()
|
||||
})
|
||||
|
||||
const port = process.env.PORT || 3000
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`server running @${port}`)
|
||||
})
|
||||
|
||||
module.exports = app
|
28
build/app.js
28
build/app.js
@ -1,28 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.api = undefined;
|
||||
|
||||
var _search = require('./component/search');
|
||||
|
||||
var _song = require('./component/song');
|
||||
|
||||
var _lrc = require('./component/lrc');
|
||||
|
||||
var _getArtistAlbums = require('./component/getArtistAlbums');
|
||||
|
||||
var _getAlbums = require('./component/getAlbums');
|
||||
|
||||
var _getPlaylists = require('./component/getPlaylists');
|
||||
|
||||
var api = {
|
||||
search: _search.search,
|
||||
song: _song.song,
|
||||
lrc: _lrc.lrc,
|
||||
getArtistAlbums: _getArtistAlbums.getArtistAlbums,
|
||||
getAlbums: _getAlbums.getAlbums,
|
||||
getPlaylists: _getPlaylists.getPlaylists
|
||||
};
|
||||
exports.api = api;
|
@ -1,32 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getAlbums = undefined;
|
||||
|
||||
var _request = require('request');
|
||||
|
||||
var _request2 = _interopRequireDefault(_request);
|
||||
|
||||
var _config = require('../config');
|
||||
|
||||
var _util = require('../util');
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var getAlbums = function getAlbums(id, callback) {
|
||||
var option = (0, _util.deepCopy)(_config.globalOption);
|
||||
var url = _config.origin + '/api/album/' + id;
|
||||
var method = 'get';
|
||||
Object.assign(option, { url: url, method: method });
|
||||
(0, _request2.default)(option, function (err, res, body) {
|
||||
if (!err && res.statusCode == 200) {
|
||||
var info = JSON.parse(body);
|
||||
callback && callback(JSON.stringify(info, '', 2));
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.getAlbums = getAlbums;
|
@ -1,35 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getArtistAlbums = undefined;
|
||||
|
||||
var _request = require('request');
|
||||
|
||||
var _request2 = _interopRequireDefault(_request);
|
||||
|
||||
var _config = require('../config');
|
||||
|
||||
var _util = require('../util');
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var getArtistAlbums = function getArtistAlbums(id, callback) {
|
||||
var limit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 3;
|
||||
var offset = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
||||
|
||||
var option = (0, _util.deepCopy)(_config.globalOption);
|
||||
var url = _config.origin + '/api/artist/albums/' + id + '?offset=' + offset + '&limit=' + limit;
|
||||
var method = 'GET';
|
||||
Object.assign(option, { url: url, method: method });
|
||||
(0, _request2.default)(option, function (err, res, body) {
|
||||
if (!err && res.statusCode == 200) {
|
||||
var info = JSON.parse(body);
|
||||
callback && callback(JSON.stringify(info, '', 2));
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.getArtistAlbums = getArtistAlbums;
|
@ -1,32 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getAlbums = undefined;
|
||||
|
||||
var _request = require('request');
|
||||
|
||||
var _request2 = _interopRequireDefault(_request);
|
||||
|
||||
var _config = require('../config');
|
||||
|
||||
var _util = require('../util');
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var getPlaylists = function getPlaylists(id, callback) {
|
||||
var option = (0, _util.deepCopy)(_config.globalOption);
|
||||
var url = _config.origin + '/api/playlist/detail?id=' + id;
|
||||
var method = 'get';
|
||||
Object.assign(option, { url: url, method: method });
|
||||
(0, _request2.default)(option, function (err, res, body) {
|
||||
if (!err && res.statusCode == 200) {
|
||||
var info = JSON.parse(body);
|
||||
callback && callback(JSON.stringify(info, '', 2));
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.getPlaylists = getPlaylists;
|
@ -1,32 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getPlaylists = undefined;
|
||||
|
||||
var _request = require('request');
|
||||
|
||||
var _request2 = _interopRequireDefault(_request);
|
||||
|
||||
var _config = require('../config');
|
||||
|
||||
var _util = require('../util');
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var getPlaylists = function getPlaylists(id, callback) {
|
||||
var option = (0, _util.deepCopy)(_config.globalOption);
|
||||
var url = _config.origin + '/api/playlist/detail?id=' + id;
|
||||
var method = 'get';
|
||||
Object.assign(option, { url: url, method: method });
|
||||
(0, _request2.default)(option, function (err, res, body) {
|
||||
if (!err && res.statusCode == 200) {
|
||||
var info = JSON.parse(body);
|
||||
callback && callback(JSON.stringify(info, '', 2));
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.getPlaylists = getPlaylists;
|
@ -1,35 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.lrc = undefined;
|
||||
|
||||
var _request = require('request');
|
||||
|
||||
var _request2 = _interopRequireDefault(_request);
|
||||
|
||||
var _config = require('../config');
|
||||
|
||||
var _util = require('../util');
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var lrc = function lrc(id) {
|
||||
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||||
var lv = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1;
|
||||
|
||||
var option = (0, _util.deepCopy)(_config.globalOption);
|
||||
var url = _config.origin + '/api/song/lyric?lv=' + lv + '&id=' + id;
|
||||
var method = 'GET';
|
||||
Object.assign(option, { url: url, method: method });
|
||||
(0, _request2.default)(option, function (err, res, body) {
|
||||
if (!err && res.statusCode == 200) {
|
||||
var info = JSON.parse(body);
|
||||
callback && callback(JSON.stringify(info, '', 2));
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.lrc = lrc;
|
@ -1,51 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.search = undefined;
|
||||
|
||||
var _request = require('request');
|
||||
|
||||
var _request2 = _interopRequireDefault(_request);
|
||||
|
||||
var _config = require('../config');
|
||||
|
||||
var _util = require('../util');
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var search = function search() {
|
||||
var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
||||
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||||
var onlySong = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
||||
var limit = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 3;
|
||||
var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
|
||||
|
||||
var option = (0, _util.deepCopy)(_config.globalOption);
|
||||
var url = _config.origin + '/api/search/get';
|
||||
var form = {
|
||||
s: name,
|
||||
limit: limit,
|
||||
type: 1,
|
||||
offset: offset
|
||||
};
|
||||
var method = 'POST';
|
||||
Object.assign(option, { url: url, form: form, method: method });
|
||||
(0, _request2.default)(option, function (err, res, body) {
|
||||
if (!err && res.statusCode == 200) {
|
||||
var info = JSON.parse(body);
|
||||
var data = void 0;
|
||||
if (onlySong) {
|
||||
data = info.result.songs;
|
||||
} else {
|
||||
data = { songs: info.result.songs, mvs: info.result.mvs };
|
||||
}
|
||||
callback && callback(JSON.stringify(data, '', 2));
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.search = search;
|
@ -1,34 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.song = undefined;
|
||||
|
||||
var _request = require('request');
|
||||
|
||||
var _request2 = _interopRequireDefault(_request);
|
||||
|
||||
var _config = require('../config');
|
||||
|
||||
var _util = require('../util');
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
var song = function song(id) {
|
||||
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
||||
|
||||
var option = (0, _util.deepCopy)(_config.globalOption);
|
||||
var url = _config.origin + '/api/song/detail?ids=%5B' + id + '%5d';
|
||||
var method = 'GET';
|
||||
Object.assign(option, { url: url, method: method });
|
||||
(0, _request2.default)(option, function (err, res, body) {
|
||||
if (!err && res.statusCode == 200) {
|
||||
var info = JSON.parse(body);
|
||||
callback && callback(JSON.stringify(info, '', 2));
|
||||
} else {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.song = song;
|
@ -1,18 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
var origin = 'http://music.163.com';
|
||||
|
||||
var globalOption = {
|
||||
headers: {
|
||||
'Origin': origin,
|
||||
'Referer': origin,
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
proxy: false
|
||||
};
|
||||
|
||||
exports.origin = origin;
|
||||
exports.globalOption = globalOption;
|
@ -1,10 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
var deepCopy = function deepCopy(obj) {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
};
|
||||
|
||||
exports.deepCopy = deepCopy;
|
@ -7,17 +7,18 @@
|
||||
|
||||
## 安装
|
||||
``` shell
|
||||
npm install NeteaseCloudMusicApi
|
||||
$ git clone git@github.com:Binaryify/NeteaseCloudMusicApi.git
|
||||
$ npm install
|
||||
```
|
||||
## 使用
|
||||
## 运行
|
||||
``` shell
|
||||
node app.js
|
||||
$ node app.js
|
||||
```
|
||||
|
||||
服务器启动,默认端口为3000
|
||||
|
||||
|
||||
## 接口
|
||||
## 接口文档
|
||||
|
||||
### 登录
|
||||
登录有两个接口
|
||||
@ -89,6 +90,7 @@ node app.js
|
||||
`/recommend/resource`
|
||||
返回数据如下图:
|
||||

|
||||
|
||||
### 获取每日推荐歌曲
|
||||
说明:调用此接口,可获得每日推荐歌曲(需要登录)
|
||||
接口地址:
|
||||
|
25
package.json
25
package.json
@ -1,20 +1,21 @@
|
||||
{
|
||||
"name": "NeteaseCloudMusicApi",
|
||||
"version": "1.5.2",
|
||||
"description": "网易云音乐nodejs版接口模块",
|
||||
"main": "build/app.js",
|
||||
"version": "2.0.0",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"test": "node test/test.js",
|
||||
"build": "babel src/ -d build/"
|
||||
"start": "node app.js",
|
||||
"test": "mocha -r intelli-espower-loader -t 20000 test"
|
||||
},
|
||||
"keywords": ["NeteaseCloudMusic","网易云音乐","网易云"],
|
||||
"author": "traveller",
|
||||
"license": "MIT",
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"request": "^2.72.0"
|
||||
"big-integer": "^1.6.17",
|
||||
"express": "^4.15.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.9.1",
|
||||
"babel-preset-es2015": "^6.9.0"
|
||||
"intelli-espower-loader": "^1.0.1",
|
||||
"mocha": "^3.2.0",
|
||||
"power-assert": "^1.4.2"
|
||||
}
|
||||
}
|
||||
}
|
26
router/logWeb.js
Normal file
26
router/logWeb.js
Normal file
@ -0,0 +1,26 @@
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
const data = {
|
||||
"action": req.query.action,
|
||||
"json": req.query.json,
|
||||
"csrf_token": "",
|
||||
}
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/log/web',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
music_req => res.send(music_req),
|
||||
err => res.status(502).send('fetch error')
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
|
||||
module.exports = router
|
34
router/login.js
Normal file
34
router/login.js
Normal file
@ -0,0 +1,34 @@
|
||||
const express = require("express")
|
||||
const crypto = require('crypto')
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const email = req.query.email
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
const md5sum = crypto.createHash('md5')
|
||||
md5sum.update(req.query.password)
|
||||
const data = {
|
||||
'username': email,
|
||||
'password': md5sum.digest('hex'),
|
||||
'rememberLogin': 'true'
|
||||
}
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/login',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
(music_req, cookie) => {
|
||||
console.log(music_req)
|
||||
res.set({
|
||||
'Set-Cookie': cookie,
|
||||
})
|
||||
res.send(music_req)
|
||||
},
|
||||
err => res.status(502).send('fetch error')
|
||||
)
|
||||
})
|
||||
|
||||
module.exports = router
|
34
router/loginCellphone.js
Normal file
34
router/loginCellphone.js
Normal file
@ -0,0 +1,34 @@
|
||||
const express = require("express")
|
||||
const crypto = require('crypto')
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const phone = req.query.phone
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
const md5sum = crypto.createHash('md5')
|
||||
md5sum.update(req.query.password)
|
||||
const data = {
|
||||
'phone': phone,
|
||||
'password': md5sum.digest('hex'),
|
||||
'rememberLogin': 'true'
|
||||
}
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/login/cellphone',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
(music_req, cookie) => {
|
||||
console.log(music_req)
|
||||
res.set({
|
||||
'Set-Cookie': cookie,
|
||||
})
|
||||
res.send(music_req)
|
||||
},
|
||||
err => res.status(502).send('fetch error')
|
||||
)
|
||||
})
|
||||
|
||||
module.exports = router
|
18
router/lyric.js
Normal file
18
router/lyric.js
Normal file
@ -0,0 +1,18 @@
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const id = req.query.id
|
||||
createRequest('/api/song/lyric?os=osx&id=' + id + '&lv=-1&kv=-1&tv=-1', 'GET', null)
|
||||
.then(result => {
|
||||
res.setHeader("Content-Type", "application/json")
|
||||
res.send(result)
|
||||
})
|
||||
.catch(err => {
|
||||
res.status(502).send('fetch error')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
module.exports = router
|
31
router/musicUrl.js
Normal file
31
router/musicUrl.js
Normal file
@ -0,0 +1,31 @@
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const id = parseInt(req.query.id)
|
||||
const br = parseInt(req.query.br || 999000)
|
||||
const data = {
|
||||
"ids": [id],
|
||||
"br": br,
|
||||
"csrf_token": ""
|
||||
}
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/song/enhance/player/url',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
music_req => {
|
||||
res.setHeader("Content-Type", "application/json")
|
||||
res.send(music_req)
|
||||
},
|
||||
err => {
|
||||
res.status(502).send('fetch error')
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
module.exports = router
|
68
router/playlistDetail.js
Normal file
68
router/playlistDetail.js
Normal file
@ -0,0 +1,68 @@
|
||||
const http = require('http')
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
let detail, imgurl
|
||||
const data = {
|
||||
"id": req.query.id,
|
||||
"offset": 0,
|
||||
"total": true,
|
||||
"limit": 1000,
|
||||
"n": 1000,
|
||||
"csrf_token": ""
|
||||
}
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/v3/playlist/detail',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
music_req=> {
|
||||
console.log(music_req)
|
||||
detail = music_req
|
||||
mergeRes()
|
||||
},
|
||||
err =>{
|
||||
res.status(502).send('fetch error')
|
||||
}
|
||||
)
|
||||
|
||||
// FIXME:i dont know the api to get coverimgurl
|
||||
// so i get it by parsing html
|
||||
const http_client = http.get({
|
||||
hostname: 'music.163.com',
|
||||
path: '/playlist?id=' + req.query.id,
|
||||
headers: {
|
||||
'Referer': 'http://music.163.com',
|
||||
},
|
||||
}, function (res) {
|
||||
res.setEncoding('utf8')
|
||||
let html = ''
|
||||
res.on('data', function (chunk) {
|
||||
html += chunk
|
||||
})
|
||||
res.on('end', function () {
|
||||
console.log('end', html)
|
||||
const regImgCover = /\<img src=\"(.*)\" class="j-img"/ig
|
||||
imgurl = regImgCover.exec(html)[1]
|
||||
mergeRes()
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
function mergeRes() {
|
||||
if (imgurl != undefined && detail != undefined) {
|
||||
detail = JSON.parse(detail)
|
||||
detail.playlist.picUrl = imgurl
|
||||
res.send(detail)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
module.exports = router
|
30
router/playlistTracks.js
Normal file
30
router/playlistTracks.js
Normal file
@ -0,0 +1,30 @@
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const op = req.query.op
|
||||
const pid = req.query.pid
|
||||
const tracks = req.query.tracks
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
// console.log('COOKIESS', cookie)
|
||||
const data = {
|
||||
"op": op,
|
||||
"pid": pid,
|
||||
"tracks": tracks,
|
||||
"trackIds": JSON.stringify([tracks]),
|
||||
"csrf_token": "",
|
||||
}
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/playlist/manipulate/tracks',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
music_req => res.send(music_req),
|
||||
err => res.status(502).send('fetch error')
|
||||
|
||||
)
|
||||
})
|
||||
|
||||
module.exports = router
|
24
router/recommendResource.js
Normal file
24
router/recommendResource.js
Normal file
@ -0,0 +1,24 @@
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
const data = {
|
||||
"csrf_token": ""
|
||||
}
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/v1/discovery/recommend/resource',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
music_req => res.send(music_req),
|
||||
err => res.status(502).send('fetch error')
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
|
||||
module.exports = router
|
27
router/recommendSongs.js
Normal file
27
router/recommendSongs.js
Normal file
@ -0,0 +1,27 @@
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/",(req,res)=>{
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
const data = {
|
||||
"offset": 0,
|
||||
"total": true,
|
||||
"limit": 20,
|
||||
"csrf_token": ""
|
||||
}
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/v1/discovery/recommend/songs',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
music_req => res.send(music_req),
|
||||
err => res.status(502).send('fetch error')
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
|
||||
module.exports=router
|
20
router/search.js
Normal file
20
router/search.js
Normal file
@ -0,0 +1,20 @@
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const keywords = req.query.keywords
|
||||
const type = req.query.type || 1
|
||||
const limit = req.query.limit || 30
|
||||
const data = 's=' + keywords + '&limit=' + limit + '&type=' + type + '&offset=0'
|
||||
createRequest('/api/search/pc/', 'POST', data)
|
||||
.then(result => {
|
||||
res.setHeader("Content-Type", "application/json")
|
||||
res.send(result)
|
||||
})
|
||||
.catch(err => {
|
||||
res.status(502).send('fetch error')
|
||||
})
|
||||
})
|
||||
|
||||
module.exports = router
|
24
router/userPlaylist.js
Normal file
24
router/userPlaylist.js
Normal file
@ -0,0 +1,24 @@
|
||||
const express = require("express")
|
||||
const router = express()
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const cookie = req.get('Cookie') ? req.get('Cookie') : ''
|
||||
const data = {
|
||||
"offset": 0,
|
||||
"uid": req.query.uid,
|
||||
"limit": 1000,
|
||||
"csrf_token": ""
|
||||
}
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/user/playlist',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
music_req => res.send(music_req),
|
||||
err => res.status(502).send('fetch error')
|
||||
)
|
||||
})
|
||||
|
||||
module.exports = router
|
16
src/app.js
16
src/app.js
@ -1,16 +0,0 @@
|
||||
import { search } from './component/search'
|
||||
import { song } from './component/song'
|
||||
import { lrc } from './component/lrc'
|
||||
import { getArtistAlbums } from './component/getArtistAlbums'
|
||||
import { getAlbums } from './component/getAlbums'
|
||||
import { getPlaylists } from './component/getPlaylists'
|
||||
|
||||
let api = {
|
||||
search: search,
|
||||
song: song,
|
||||
lrc: lrc,
|
||||
getArtistAlbums: getArtistAlbums,
|
||||
getAlbums: getAlbums,
|
||||
getPlaylists: getPlaylists
|
||||
}
|
||||
export {api}
|
@ -1,19 +0,0 @@
|
||||
import request from 'request'
|
||||
import { origin, globalOption } from '../config'
|
||||
import { deepCopy } from '../util'
|
||||
|
||||
const getAlbums = (id, callback) => {
|
||||
const option = deepCopy(globalOption)
|
||||
const url = `${origin}/api/album/${id}`
|
||||
const method = 'get'
|
||||
Object.assign(option, {url, method})
|
||||
request(option, (err, res, body) => {
|
||||
if(!err && res.statusCode == 200) {
|
||||
let info = JSON.parse(body)
|
||||
callback && callback(JSON.stringify(info, '', 2))
|
||||
} else {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
export { getAlbums }
|
@ -1,19 +0,0 @@
|
||||
import request from 'request'
|
||||
import { origin, globalOption } from '../config'
|
||||
import { deepCopy } from '../util'
|
||||
|
||||
const getArtistAlbums = (id, callback, limit = 3, offset = 0) => {
|
||||
const option = deepCopy(globalOption)
|
||||
const url = `${origin}/api/artist/albums/${id}?offset=${offset}&limit=${limit}`
|
||||
const method = 'GET'
|
||||
Object.assign(option, {url, method})
|
||||
request(option, (err, res, body) => {
|
||||
if(!err && res.statusCode == 200) {
|
||||
let info = JSON.parse(body)
|
||||
callback && callback(JSON.stringify(info, '', 2))
|
||||
} else {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
export { getArtistAlbums }
|
@ -1,19 +0,0 @@
|
||||
import request from 'request'
|
||||
import { origin, globalOption } from '../config'
|
||||
import { deepCopy } from '../util'
|
||||
|
||||
const getPlaylists = (id, callback) => {
|
||||
const option = deepCopy(globalOption)
|
||||
const url = `${origin}/api/playlist/detail?id=${id}`
|
||||
const method = 'get'
|
||||
Object.assign(option, {url, method})
|
||||
request(option, (err, res, body) => {
|
||||
if(!err && res.statusCode == 200) {
|
||||
let info = JSON.parse(body)
|
||||
callback && callback(JSON.stringify(info, '', 2))
|
||||
} else {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
export { getPlaylists }
|
@ -1,19 +0,0 @@
|
||||
import request from 'request'
|
||||
import { origin, globalOption } from '../config'
|
||||
import { deepCopy } from '../util'
|
||||
|
||||
const lrc = (id, callback = null, lv = -1) => {
|
||||
const option = deepCopy(globalOption)
|
||||
const url = `${origin}/api/song/lyric?lv=${lv}&id=${id}`
|
||||
const method = 'GET'
|
||||
Object.assign(option, { url, method })
|
||||
request(option, (err, res, body) => {
|
||||
if (!err && res.statusCode == 200) {
|
||||
let info = JSON.parse(body)
|
||||
callback && callback(JSON.stringify(info, '', 2))
|
||||
} else {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
export { lrc }
|
@ -1,32 +0,0 @@
|
||||
import request from 'request'
|
||||
import { origin, globalOption } from '../config'
|
||||
import { deepCopy } from '../util'
|
||||
|
||||
const search = (name = null, callback = null,onlySong=true, limit = 3, offset = 0) => {
|
||||
const option = deepCopy(globalOption)
|
||||
const url = `${origin}/api/search/get`
|
||||
const form = {
|
||||
s: name,
|
||||
limit,
|
||||
type: 1,
|
||||
offset
|
||||
}
|
||||
const method = 'POST'
|
||||
Object.assign(option, { url, form, method })
|
||||
request(option, (err, res, body) => {
|
||||
if (!err && res.statusCode == 200) {
|
||||
let info = JSON.parse(body)
|
||||
let data
|
||||
if(onlySong){
|
||||
data=info.result.songs
|
||||
}else{
|
||||
data={songs:info.result.songs,mvs:info.result.mvs}
|
||||
}
|
||||
callback&&callback(JSON.stringify(data,'',2))
|
||||
} else {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export { search }
|
@ -1,19 +0,0 @@
|
||||
import request from 'request'
|
||||
import { origin, globalOption } from '../config'
|
||||
import { deepCopy } from '../util'
|
||||
|
||||
const song = (id, callback = null) => {
|
||||
const option = deepCopy(globalOption)
|
||||
const url = `${origin}/api/song/detail?ids=%5B${id}%5d`
|
||||
const method = 'GET'
|
||||
Object.assign(option, { url, method })
|
||||
request(option, (err, res, body) => {
|
||||
if (!err && res.statusCode == 200) {
|
||||
let info = JSON.parse(body);
|
||||
callback && callback(JSON.stringify(info, '', 2))
|
||||
} else {
|
||||
console.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
export { song }
|
@ -1,12 +0,0 @@
|
||||
const origin = 'http://music.163.com'
|
||||
|
||||
const globalOption = {
|
||||
headers: {
|
||||
'Origin': origin,
|
||||
'Referer': origin,
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
proxy:false
|
||||
}
|
||||
|
||||
export { origin, globalOption }
|
@ -1,3 +0,0 @@
|
||||
const deepCopy = obj => JSON.parse(JSON.stringify(obj))
|
||||
|
||||
export { deepCopy }
|
70
test/login.test.js
Normal file
70
test/login.test.js
Normal file
@ -0,0 +1,70 @@
|
||||
const assert = require('assert')
|
||||
const crypto = require('crypto')
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
|
||||
|
||||
describe('测试登录是否正常', () => {
|
||||
it('手机登录 code 应该等于200', done => {
|
||||
const phone = "换成你的手机号"
|
||||
const password = "换成你的密码"
|
||||
let cookie = ''
|
||||
const md5sum = crypto.createHash('md5')
|
||||
md5sum.update(password)
|
||||
const data = {
|
||||
'phone': phone,
|
||||
'password': md5sum.digest('hex'),
|
||||
'rememberLogin': 'true'
|
||||
}
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/login/cellphone',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
(music_req, cookie) => {
|
||||
const result = JSON.parse(music_req)
|
||||
console.log({
|
||||
loginType: result.loginType,
|
||||
code: result.code,
|
||||
account: result.account
|
||||
})
|
||||
assert(result.code === 200)
|
||||
done()
|
||||
},
|
||||
err => done(err)
|
||||
)
|
||||
})
|
||||
|
||||
it('邮箱登录 code 应该等于200', done => {
|
||||
const email = "换成你的163网易邮箱"
|
||||
const password = "换成你的密码"
|
||||
const cookie = ''
|
||||
const md5sum = crypto.createHash('md5')
|
||||
md5sum.update(password)
|
||||
const data = {
|
||||
'username': email,
|
||||
'password': md5sum.digest('hex'),
|
||||
'rememberLogin': 'true'
|
||||
}
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/login',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
(music_req, cookie) => {
|
||||
const result = JSON.parse(music_req)
|
||||
console.log({
|
||||
loginType: result.loginType,
|
||||
code: result.code,
|
||||
account: result.account
|
||||
})
|
||||
assert(result.code === 200)
|
||||
done()
|
||||
},
|
||||
err => done(err)
|
||||
)
|
||||
})
|
||||
})
|
20
test/lyric.test.js
Normal file
20
test/lyric.test.js
Normal file
@ -0,0 +1,20 @@
|
||||
const assert = require('assert')
|
||||
const crypto = require('crypto')
|
||||
const { createRequest } = require("../util/util")
|
||||
const phone = "换成你的账号"
|
||||
const password = "换成你的密码"
|
||||
|
||||
describe('测试获取歌词是否正常', () => {
|
||||
it('数据应该有 lrc 字段', done => {
|
||||
const id = 347230
|
||||
createRequest('/api/song/lyric?os=osx&id=' + id + '&lv=-1&kv=-1&tv=-1', 'GET', null)
|
||||
.then(result => {
|
||||
console.log(JSON.parse(result).lrc)
|
||||
assert(typeof JSON.parse(result).lrc!=='undefined')
|
||||
done()
|
||||
})
|
||||
.catch(err => {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
34
test/musicUrl.test.js
Normal file
34
test/musicUrl.test.js
Normal file
@ -0,0 +1,34 @@
|
||||
const assert = require('assert')
|
||||
const crypto = require('crypto')
|
||||
const { createWebAPIRequest } = require("../util/util")
|
||||
const phone = "换成你的账号"
|
||||
const password = "换成你的密码"
|
||||
|
||||
describe('测试获取歌曲是否正常', () => {
|
||||
it('歌曲的 url 不应该为空', done => {
|
||||
const id = 347230
|
||||
const br = 999000
|
||||
const data = {
|
||||
"ids": [id],
|
||||
"br": br,
|
||||
"csrf_token": ""
|
||||
}
|
||||
const cookie = ''
|
||||
|
||||
createWebAPIRequest(
|
||||
'music.163.com',
|
||||
'/weapi/song/enhance/player/url',
|
||||
'POST',
|
||||
data,
|
||||
cookie,
|
||||
music_req => {
|
||||
console.log(JSON.parse(music_req).data[0].url)
|
||||
assert(!!JSON.parse(music_req).data[0].url)
|
||||
done()
|
||||
},
|
||||
err => {
|
||||
done(err)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
23
test/search.test.js
Normal file
23
test/search.test.js
Normal file
@ -0,0 +1,23 @@
|
||||
const assert = require('assert')
|
||||
const crypto = require('crypto')
|
||||
const { createRequest } = require("../util/util")
|
||||
const phone = "换成你的账号"
|
||||
const password = "换成你的密码"
|
||||
|
||||
describe('测试搜索是否正常', () => {
|
||||
it('获取到的数据的 name 应该和搜索关键词一致', done => {
|
||||
const keywords = "海阔天空"
|
||||
const type = 1
|
||||
const limit = 30
|
||||
const data = 's=' + keywords + '&limit=' + limit + '&type=' + type + '&offset=0'
|
||||
createRequest('/api/search/pc/', 'POST', data)
|
||||
.then(result => {
|
||||
console.log(JSON.parse(result).result.songs[0].mp3Url)
|
||||
assert(JSON.parse(result).result.songs[0].name === '海阔天空')
|
||||
done()
|
||||
})
|
||||
.catch(err => {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
34
test/test.js
34
test/test.js
@ -1,34 +0,0 @@
|
||||
// import { api } from '../src/app.js'
|
||||
// const { api } =require('../src/app.js')
|
||||
var api=require('../build/app.js').api
|
||||
api.search("年度之歌",data => {
|
||||
console.log("################Search API#################")
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
|
||||
api.song('308169',data => {
|
||||
console.log("################Song API#################")
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
|
||||
api.lrc('5243023',data => {
|
||||
console.log("################Lrc API#################")
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
api.getArtistAlbums('9952', data => {
|
||||
console.log('####################Artist Albums##############')
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
api.getAlbums('32311', data => {
|
||||
console.log("####################Albums####################")
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
api.getPlaylists('311785002', data => {
|
||||
console.log("####################Playlists####################")
|
||||
console.log(data)
|
||||
})
|
66
util/crypto.js
Normal file
66
util/crypto.js
Normal file
@ -0,0 +1,66 @@
|
||||
// 参考 https://github.com/darknessomi/musicbox/wiki/
|
||||
'use strict'
|
||||
const crypto = require('crypto')
|
||||
const bigInt = require('big-integer')
|
||||
const modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
|
||||
const nonce = '0CoJUm6Qyw8W8jud'
|
||||
const pubKey = '010001'
|
||||
|
||||
String.prototype.hexEncode = function(){
|
||||
let hex, i
|
||||
|
||||
let result = ""
|
||||
for (i=0; i<this.length; i++) {
|
||||
hex = this.charCodeAt(i).toString(16)
|
||||
result += (""+hex).slice(-4)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function createSecretKey(size) {
|
||||
const keys = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
let key = ""
|
||||
for (let i = 0; i < size; i++) {
|
||||
let pos = Math.random() * keys.length
|
||||
pos = Math.floor(pos)
|
||||
key = key + keys.charAt(pos)
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
function aesEncrypt(text, secKey) {
|
||||
const _text = text
|
||||
const lv = new Buffer('0102030405060708', "binary")
|
||||
const _secKey = new Buffer(secKey, "binary")
|
||||
const cipher = crypto.createCipheriv('AES-128-CBC', _secKey, lv)
|
||||
let encrypted = cipher.update(_text, 'utf8', 'base64')
|
||||
encrypted += cipher.final('base64')
|
||||
return encrypted
|
||||
}
|
||||
|
||||
function zfill(str, size) {
|
||||
while (str.length < size) str = "0" + str
|
||||
return str
|
||||
}
|
||||
|
||||
function rsaEncrypt(text, pubKey, modulus) {
|
||||
const _text = text.split('').reverse().join('')
|
||||
const biText = bigInt(new Buffer(_text).toString('hex'), 16),
|
||||
biEx = bigInt(pubKey, 16),
|
||||
biMod = bigInt(modulus, 16),
|
||||
biRet = biText.modPow(biEx, biMod)
|
||||
return zfill(biRet.toString(16), 256)
|
||||
}
|
||||
|
||||
function Encrypt(obj) {
|
||||
const text = JSON.stringify(obj)
|
||||
const secKey = createSecretKey(16)
|
||||
const encText = aesEncrypt(aesEncrypt(text, nonce), secKey)
|
||||
const encSecKey = rsaEncrypt(secKey, pubKey, modulus)
|
||||
return {
|
||||
params: encText,
|
||||
encSecKey: encSecKey
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Encrypt
|
83
util/util.js
Normal file
83
util/util.js
Normal file
@ -0,0 +1,83 @@
|
||||
const Encrypt = require('./crypto.js')
|
||||
const http = require('http')
|
||||
function createWebAPIRequest(host, path, method, data, cookie, callback, errorcallback) {
|
||||
let music_req = ''
|
||||
const cryptoreq = Encrypt(data)
|
||||
const http_client = http.request({
|
||||
hostname: host,
|
||||
method: method,
|
||||
path: path,
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
|
||||
'Connection': 'keep-alive',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Referer': 'http://music.163.com',
|
||||
'Host': 'music.163.com',
|
||||
'Cookie': cookie,
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36',
|
||||
|
||||
},
|
||||
}, function (res) {
|
||||
res.on('error', function (err) {
|
||||
errorcallback(err)
|
||||
})
|
||||
res.setEncoding('utf8')
|
||||
if (res.statusCode != 200) {
|
||||
createWebAPIRequest(host, path, method, data, cookie, callback)
|
||||
return
|
||||
} else {
|
||||
res.on('data', function (chunk) {
|
||||
music_req += chunk
|
||||
})
|
||||
res.on('end', function () {
|
||||
if (music_req == '') {
|
||||
createWebAPIRequest(host, path, method, data, cookie, callback)
|
||||
return
|
||||
}
|
||||
if (res.headers['set-cookie']) {
|
||||
callback(music_req, res.headers['set-cookie'])
|
||||
} else {
|
||||
callback(music_req)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
http_client.write('params=' + cryptoreq.params + '&encSecKey=' + cryptoreq.encSecKey)
|
||||
http_client.end()
|
||||
}
|
||||
|
||||
function createRequest(path, method, data, callback, errorcallback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let ne_req = ''
|
||||
const http_client = http.request({
|
||||
hostname: 'music.163.com',
|
||||
method: method,
|
||||
path: path,
|
||||
headers: {
|
||||
'Referer': 'http://music.163.com',
|
||||
'Cookie': 'appver=2.0.2',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
}, res => {
|
||||
res.setEncoding('utf8')
|
||||
res.on('error', err => {
|
||||
reject(err)
|
||||
})
|
||||
res.on('data', chunk => {
|
||||
ne_req += chunk
|
||||
})
|
||||
res.on('end', () => {
|
||||
resolve(ne_req)
|
||||
})
|
||||
})
|
||||
if (method == 'POST') {
|
||||
http_client.write(data)
|
||||
}
|
||||
http_client.end()
|
||||
})
|
||||
}
|
||||
module.exports = {
|
||||
createWebAPIRequest,
|
||||
createRequest
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user