From a2e4d2640187c5a9f58db5e55d88867bdd1a0b51 Mon Sep 17 00:00:00 2001 From: binaryify Date: Sat, 1 Apr 2017 18:42:51 +0800 Subject: [PATCH] upgrade version 2.0,add login api,upgrade api verison,add document and unit test --- .DS_Store | Bin 6148 -> 6148 bytes .babelrc | 3 -- .editorconfig | 20 ------- .travis.yml | 2 - LICENSE | 21 -------- README.MD | 77 +++++++++----------------- app.js | 39 ++++++++++++++ build/app.js | 28 ---------- build/component/getAlbums.js | 32 ----------- build/component/getArtistAlbums.js | 35 ------------ build/component/getPlaylists | 32 ----------- build/component/getPlaylists.js | 32 ----------- build/component/lrc.js | 35 ------------ build/component/search.js | 51 ------------------ build/component/song.js | 34 ------------ build/config.js | 18 ------- build/util.js | 10 ---- docs/README.md | 10 ++-- package.json | 25 ++++----- router/logWeb.js | 26 +++++++++ router/login.js | 34 ++++++++++++ router/loginCellphone.js | 34 ++++++++++++ router/lyric.js | 18 +++++++ router/musicUrl.js | 31 +++++++++++ router/playlistDetail.js | 68 +++++++++++++++++++++++ router/playlistTracks.js | 30 +++++++++++ router/recommendResource.js | 24 +++++++++ router/recommendSongs.js | 27 ++++++++++ router/search.js | 20 +++++++ router/userPlaylist.js | 24 +++++++++ src/app.js | 16 ------ src/component/getAlbums.js | 19 ------- src/component/getArtistAlbums.js | 19 ------- src/component/getPlaylists.js | 19 ------- src/component/lrc.js | 19 ------- src/component/search.js | 32 ----------- src/component/song.js | 19 ------- src/config.js | 12 ----- src/util.js | 3 -- test/login.test.js | 70 ++++++++++++++++++++++++ test/lyric.test.js | 20 +++++++ test/musicUrl.test.js | 34 ++++++++++++ test/search.test.js | 23 ++++++++ test/test.js | 34 ------------ util/crypto.js | 66 +++++++++++++++++++++++ util/util.js | 83 +++++++++++++++++++++++++++++ 46 files changed, 714 insertions(+), 614 deletions(-) delete mode 100644 .babelrc delete mode 100644 .editorconfig delete mode 100644 LICENSE create mode 100644 app.js delete mode 100644 build/app.js delete mode 100644 build/component/getAlbums.js delete mode 100644 build/component/getArtistAlbums.js delete mode 100644 build/component/getPlaylists delete mode 100644 build/component/getPlaylists.js delete mode 100644 build/component/lrc.js delete mode 100644 build/component/search.js delete mode 100644 build/component/song.js delete mode 100644 build/config.js delete mode 100644 build/util.js create mode 100644 router/logWeb.js create mode 100644 router/login.js create mode 100644 router/loginCellphone.js create mode 100644 router/lyric.js create mode 100644 router/musicUrl.js create mode 100644 router/playlistDetail.js create mode 100644 router/playlistTracks.js create mode 100644 router/recommendResource.js create mode 100644 router/recommendSongs.js create mode 100644 router/search.js create mode 100644 router/userPlaylist.js delete mode 100644 src/app.js delete mode 100644 src/component/getAlbums.js delete mode 100644 src/component/getArtistAlbums.js delete mode 100644 src/component/getPlaylists.js delete mode 100644 src/component/lrc.js delete mode 100644 src/component/search.js delete mode 100644 src/component/song.js delete mode 100644 src/config.js delete mode 100644 src/util.js create mode 100644 test/login.test.js create mode 100644 test/lyric.test.js create mode 100644 test/musicUrl.test.js create mode 100644 test/search.test.js delete mode 100644 test/test.js create mode 100644 util/crypto.js create mode 100644 util/util.js diff --git a/.DS_Store b/.DS_Store index 49b2b5af99b181d5e0698ef3bcb5e9303d623945..bad972f5fdd30862c23a4b6766aacc4f7586ac07 100644 GIT binary patch delta 662 zcmZWnzi-n(6n@VxsaqQ2{A@%)3PebVM##`Y#DGZBp+pR^nyO0FLa?1ndcyIgw%d}1 z5QhE%R2dMgU0IOD#Kg$L%E-V!z=9az62}6;NvH4Weed1(-Mc$hj+K`wVP^hhFLiSL z5{mEC4|uAI0*a#rVJZDd@0!$c73B*G;>?-QtTe}0SQ-_Dc&JL7MAt?=p)^!AcURZ! z3EPm<{r<{oK9{+9M;YWY{d``@WmZ>i4+fI7c;&|3^5ahLsQ+y6{54D#qK^=nVgPS= z5CR8W(Deu$gJ9%%Lu2R{bxwzB7?`NvCYJ7?&JdsC36=&K9v9j{o)7 z>Y8n9R-2T14^2%cX2mKocj&TCjq-bpy-yUXUCp3YJA3cDKg_vo;i@0WkPYT5$+&50 z9l}Y~&t(e_rlbVRP=qS%z#hDSS8xjN;Uj#8Z}0B)qu~2NHo+2aD#(>?7lMO^zCiAmM1bs~^$jK}&F)+Bn$i&RT%Er#Y z$;r*b!^6)L8=R3}9$b=GQd;bkSQHK71tgYaBqbKb3&;d#rlbN{;h8BV86l~8t~se? zsd@fIK8Yo%lOtH1lA!V&9Lf&K3m8Cvlan)EK%%H?wo_a{&Ff YS&-v9^JIPzM-Gr8phlL>5h81t0gWa=aR2}S diff --git a/.babelrc b/.babelrc deleted file mode 100644 index af0f0c3..0000000 --- a/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["es2015"] -} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 04ba039..0000000 --- a/.editorconfig +++ /dev/null @@ -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 diff --git a/.travis.yml b/.travis.yml index 9733ba3..8eaf77a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ language: node_js node_js: - - - 4.0 - 6.2 diff --git a/LICENSE b/LICENSE deleted file mode 100644 index facc240..0000000 --- a/LICENSE +++ /dev/null @@ -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. \ No newline at end of file diff --git a/README.MD b/README.MD index b0072bb..ce4409a 100644 --- a/README.MD +++ b/README.MD @@ -1,5 +1,5 @@ # NeteaseCloudMusicApi -一个调用网易云音乐 API 的 node 模块 +网易云音乐 nodejs 接口

Version License @@ -9,64 +9,35 @@

-![](http://binaryify.github.io/images/api.jpg) -## 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]) -``` +![单元测试](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/screenshot1.png) +![单元测试](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/screenshot2.png) ## License [The MIT License (MIT)](LICENSE) diff --git a/app.js b/app.js new file mode 100644 index 0000000..f6a9979 --- /dev/null +++ b/app.js @@ -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 \ No newline at end of file diff --git a/build/app.js b/build/app.js deleted file mode 100644 index 6b66f80..0000000 --- a/build/app.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/build/component/getAlbums.js b/build/component/getAlbums.js deleted file mode 100644 index ec2d6b3..0000000 --- a/build/component/getAlbums.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/build/component/getArtistAlbums.js b/build/component/getArtistAlbums.js deleted file mode 100644 index 85b3391..0000000 --- a/build/component/getArtistAlbums.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/build/component/getPlaylists b/build/component/getPlaylists deleted file mode 100644 index 3be62f2..0000000 --- a/build/component/getPlaylists +++ /dev/null @@ -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; diff --git a/build/component/getPlaylists.js b/build/component/getPlaylists.js deleted file mode 100644 index e4c8ef5..0000000 --- a/build/component/getPlaylists.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/build/component/lrc.js b/build/component/lrc.js deleted file mode 100644 index cc79f5e..0000000 --- a/build/component/lrc.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/build/component/search.js b/build/component/search.js deleted file mode 100644 index 50ff324..0000000 --- a/build/component/search.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/build/component/song.js b/build/component/song.js deleted file mode 100644 index d88a6ee..0000000 --- a/build/component/song.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/build/config.js b/build/config.js deleted file mode 100644 index 7a686ef..0000000 --- a/build/config.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/build/util.js b/build/util.js deleted file mode 100644 index 6800069..0000000 --- a/build/util.js +++ /dev/null @@ -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; \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 99da9c2..f7e449a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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` 返回数据如下图: ![搜索音乐](https://raw.githubusercontent.com/Binaryify/NeteaseCloudMusicApi/master/static/%E6%8E%A8%E8%8D%90%E6%AD%8C%E5%8D%95.png) + ### 获取每日推荐歌曲 说明:调用此接口,可获得每日推荐歌曲(需要登录) 接口地址: diff --git a/package.json b/package.json index aad3968..3dc99af 100644 --- a/package.json +++ b/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" } -} +} \ No newline at end of file diff --git a/router/logWeb.js b/router/logWeb.js new file mode 100644 index 0000000..04388dd --- /dev/null +++ b/router/logWeb.js @@ -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 \ No newline at end of file diff --git a/router/login.js b/router/login.js new file mode 100644 index 0000000..ae76cd3 --- /dev/null +++ b/router/login.js @@ -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 \ No newline at end of file diff --git a/router/loginCellphone.js b/router/loginCellphone.js new file mode 100644 index 0000000..c908c61 --- /dev/null +++ b/router/loginCellphone.js @@ -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 \ No newline at end of file diff --git a/router/lyric.js b/router/lyric.js new file mode 100644 index 0000000..fec3915 --- /dev/null +++ b/router/lyric.js @@ -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 \ No newline at end of file diff --git a/router/musicUrl.js b/router/musicUrl.js new file mode 100644 index 0000000..e3b72a6 --- /dev/null +++ b/router/musicUrl.js @@ -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 \ No newline at end of file diff --git a/router/playlistDetail.js b/router/playlistDetail.js new file mode 100644 index 0000000..1a653ba --- /dev/null +++ b/router/playlistDetail.js @@ -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 = /\ { + 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 \ No newline at end of file diff --git a/router/recommendResource.js b/router/recommendResource.js new file mode 100644 index 0000000..abe4b14 --- /dev/null +++ b/router/recommendResource.js @@ -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 \ No newline at end of file diff --git a/router/recommendSongs.js b/router/recommendSongs.js new file mode 100644 index 0000000..9480d3d --- /dev/null +++ b/router/recommendSongs.js @@ -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 \ No newline at end of file diff --git a/router/search.js b/router/search.js new file mode 100644 index 0000000..2c1bab5 --- /dev/null +++ b/router/search.js @@ -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 \ No newline at end of file diff --git a/router/userPlaylist.js b/router/userPlaylist.js new file mode 100644 index 0000000..2165f06 --- /dev/null +++ b/router/userPlaylist.js @@ -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 \ No newline at end of file diff --git a/src/app.js b/src/app.js deleted file mode 100644 index 07860bb..0000000 --- a/src/app.js +++ /dev/null @@ -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} diff --git a/src/component/getAlbums.js b/src/component/getAlbums.js deleted file mode 100644 index 449cf90..0000000 --- a/src/component/getAlbums.js +++ /dev/null @@ -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 } diff --git a/src/component/getArtistAlbums.js b/src/component/getArtistAlbums.js deleted file mode 100644 index 8a24613..0000000 --- a/src/component/getArtistAlbums.js +++ /dev/null @@ -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 } diff --git a/src/component/getPlaylists.js b/src/component/getPlaylists.js deleted file mode 100644 index 71b781b..0000000 --- a/src/component/getPlaylists.js +++ /dev/null @@ -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 } diff --git a/src/component/lrc.js b/src/component/lrc.js deleted file mode 100644 index fc02ef0..0000000 --- a/src/component/lrc.js +++ /dev/null @@ -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 } diff --git a/src/component/search.js b/src/component/search.js deleted file mode 100644 index 9568e22..0000000 --- a/src/component/search.js +++ /dev/null @@ -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 } diff --git a/src/component/song.js b/src/component/song.js deleted file mode 100644 index 146d4ba..0000000 --- a/src/component/song.js +++ /dev/null @@ -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 } diff --git a/src/config.js b/src/config.js deleted file mode 100644 index 5d52d4e..0000000 --- a/src/config.js +++ /dev/null @@ -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 } diff --git a/src/util.js b/src/util.js deleted file mode 100644 index c33769a..0000000 --- a/src/util.js +++ /dev/null @@ -1,3 +0,0 @@ -const deepCopy = obj => JSON.parse(JSON.stringify(obj)) - -export { deepCopy } diff --git a/test/login.test.js b/test/login.test.js new file mode 100644 index 0000000..6136eca --- /dev/null +++ b/test/login.test.js @@ -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) + ) + }) +}) \ No newline at end of file diff --git a/test/lyric.test.js b/test/lyric.test.js new file mode 100644 index 0000000..2b788e1 --- /dev/null +++ b/test/lyric.test.js @@ -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) + }) + }) +}) \ No newline at end of file diff --git a/test/musicUrl.test.js b/test/musicUrl.test.js new file mode 100644 index 0000000..550a83b --- /dev/null +++ b/test/musicUrl.test.js @@ -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) + } + ) + }) +}) \ No newline at end of file diff --git a/test/search.test.js b/test/search.test.js new file mode 100644 index 0000000..8342002 --- /dev/null +++ b/test/search.test.js @@ -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) + }) + }) +}) \ No newline at end of file diff --git a/test/test.js b/test/test.js deleted file mode 100644 index e4ec9d6..0000000 --- a/test/test.js +++ /dev/null @@ -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) -}) diff --git a/util/crypto.js b/util/crypto.js new file mode 100644 index 0000000..3deab7f --- /dev/null +++ b/util/crypto.js @@ -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 { + 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 +} \ No newline at end of file