unblock-netease-music
Advanced tools
Comparing version 0.1.4 to 0.2.2
20
app.js
var express = require('express'); | ||
var favicon = require('serve-favicon'); | ||
var logger = require('morgan'); | ||
var bodyParser = require('body-parser'); | ||
var proxy = require('./middleware') | ||
@@ -14,2 +14,3 @@ var routes = require('./routes/index'); | ||
})); | ||
app.use(proxy); | ||
@@ -26,19 +27,4 @@ app.use('/', routes); | ||
// error handlers | ||
// development error handler | ||
// will print stacktrace | ||
if (app.get('env') === 'development') { | ||
app.use(function(err, req, res, next) { | ||
res.status(err.status || 500); | ||
res.send({ | ||
message: err.message, | ||
error: err | ||
}); | ||
}); | ||
} | ||
// production error handler | ||
// no stacktraces leaked to user | ||
app.use(function(err, req, res, next) { | ||
console.error(err); | ||
res.status(err.status || 500); | ||
@@ -45,0 +31,0 @@ res.send({ |
{ | ||
"name": "unblock-netease-music", | ||
"version": "0.1.4", | ||
"version": "0.2.2", | ||
"scripts": { | ||
@@ -12,6 +12,4 @@ "start": "node ./bin/www" | ||
"async": "^2.0.0-rc.2", | ||
"base-64": "^0.1.0", | ||
"body-parser": "~1.13.2", | ||
"colors": "^1.1.2", | ||
"cookie-parser": "~1.3.5", | ||
"debug": "~2.2.0", | ||
@@ -21,5 +19,3 @@ "express": "~4.13.1", | ||
"morgan": "~1.6.1", | ||
"python-shell": "^0.4.0", | ||
"request": "^2.69.0", | ||
"serve-favicon": "~2.3.0" | ||
"request": "^2.69.0" | ||
}, | ||
@@ -26,0 +22,0 @@ "description": "A proxy server for Netease Music...", |
@@ -7,4 +7,3 @@ # UnblockNeteaseMusic | ||
1. Python 2.7 installed and added to path. | ||
2. Node.js 4.x+ | ||
1. Node.js 4.x+ | ||
@@ -11,0 +10,0 @@ # How to use |
@@ -5,80 +5,48 @@ var express = require('express'); | ||
var colors = require('colors'); | ||
var request = require('request'); | ||
var waterfall = require("async/waterfall"); | ||
var utils = new Utils(); | ||
router.get('/*', function(req, res) { | ||
var url = req.originalUrl; | ||
if(!/^http/.test(url)){ | ||
url = "http://223.252.199.7" + url; | ||
} | ||
var options = { | ||
url: url, | ||
headers: req.headers, | ||
method: 'get' | ||
}; | ||
request(options) | ||
.on('error', function(err) { | ||
console.error(err) | ||
}) | ||
.pipe(res); | ||
}); | ||
router.post('/*', function(req, res, next) { | ||
if (/mp3$|flac$/.test(req.originalUrl)) { | ||
return request.get(req.originalUrl).pipe(res); | ||
} | ||
utils.defaultPost(req.headers, req.body, req.originalUrl, function(err, headers, body) { | ||
if (err) { | ||
return console.error(err); | ||
} else { | ||
// console.log(body); | ||
// console.log(utils); | ||
next(); | ||
} | ||
}); | ||
}); | ||
router.post('/eapi/v3/song/detail', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/v3/playlist/detail', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/v1/album/*', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/batch', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/cloudsearch/pc', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/v1/artist', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/batch', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/v1/search/get', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/song/enhance/privilege', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/v1/discovery/new/songs', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
}); | ||
router.post('/eapi/v1/play/record', function(req, res, next) { | ||
utils.modifyDetailApi(); | ||
res.defaultBody = utils.netease.modifyDetailApi(res.defaultBody); | ||
next(); | ||
@@ -88,7 +56,44 @@ }); | ||
router.post('/eapi/song/enhance/player/url', function(req, res, next) { | ||
if (utils.getPlaybackReturnCode() != 200 || utils.getPlaybackBitrate() < 320000) { | ||
utils.modifyPlayerApi(function(err) { | ||
if (err) { | ||
return console.error(err.red); | ||
} else { | ||
if (utils.netease.getPlaybackReturnCode(res.defaultBody) != 200 || utils.netease.getPlaybackBitrate(res.defaultBody) < 320000) { | ||
waterfall([ | ||
function(callback) { | ||
var songId = utils.netease.getPlaybackSongId(res.defaultBody); | ||
callback(null, songId); | ||
}, | ||
function(songId, callback) { | ||
utils.netease.getSongDetail(songId, function(err, detail) { | ||
if (err) { | ||
console.error(err); | ||
} else { | ||
callback(null, detail); | ||
} | ||
}); | ||
}, | ||
function(detail, callback) { | ||
var songName = utils.netease.getSongName(detail); | ||
var artist = utils.netease.getArtistName(detail); | ||
utils.kugou.search(songName, artist, function(err, hash, bitrate) { | ||
if (err) { | ||
console.error(err); | ||
} else { | ||
callback(null, hash, bitrate); | ||
} | ||
}); | ||
}, | ||
function(hash, bitrate, callback) { | ||
utils.kugou.getUrl(hash, function(err, url) { | ||
if (err) { | ||
console.error(err); | ||
} else { | ||
callback(null, url, bitrate); | ||
} | ||
}); | ||
} | ||
], function(err, url, bitrate) { | ||
if(err) { | ||
console.error(err); | ||
res.status = 500; | ||
res.send(); | ||
}else{ | ||
res.defaultBody = utils.netease.modifyPlayerApiCustom(url, bitrate, res.defaultBody); | ||
next(); | ||
@@ -98,3 +103,3 @@ } | ||
} else { | ||
console.log('Playback bitrate is not changed. The song URL is '.green + utils.getPlaybackUrl().green); | ||
console.log('Playback bitrate is not changed. The song URL is '.green + utils.netease.getPlaybackUrl(res.defaultBody).green); | ||
next(); | ||
@@ -105,7 +110,44 @@ } | ||
router.post('/eapi/song/enhance/download/url', function(req, res, next) { | ||
if (utils.getDownloadReturnCode() != 200 || utils.getDownloadBitrate() < 320000) { | ||
utils.modifyDownloadApi(function(err) { | ||
if (err) { | ||
return console.error(err.red); | ||
} else { | ||
if (utils.netease.getDownloadReturnCode(res.defaultBody) != 200 || utils.netease.getDownloadBitrate(res.defaultBody) < 320000) { | ||
waterfall([ | ||
function(callback) { | ||
var songId = utils.netease.getDownloadSongId(res.defaultBody); | ||
callback(null, songId); | ||
}, | ||
function(songId, callback) { | ||
utils.netease.getSongDetail(songId, function(err, detail) { | ||
if (err) { | ||
console.error(err); | ||
} else { | ||
callback(null, detail); | ||
} | ||
}); | ||
}, | ||
function(detail, callback) { | ||
var songName = utils.netease.getSongName(detail); | ||
var artist = utils.netease.getArtistName(detail); | ||
utils.kugou.search(songName, artist, function(err, hash, bitrate) { | ||
if (err) { | ||
console.error(err); | ||
} else { | ||
callback(null, hash, bitrate); | ||
} | ||
}); | ||
}, | ||
function(hash, bitrate, callback) { | ||
utils.kugou.getUrl(hash, function(err, url) { | ||
if (err) { | ||
console.error(err); | ||
} else { | ||
callback(null, url, bitrate); | ||
} | ||
}); | ||
} | ||
], function(err, url, bitrate) { | ||
if(err) { | ||
console.error(err); | ||
res.status = 500; | ||
res.send(); | ||
}else{ | ||
res.defaultBody = utils.netease.modifyDownloadApiCustom(url, bitrate, res.defaultBody); | ||
next(); | ||
@@ -115,3 +157,3 @@ } | ||
} else { | ||
console.log('Download bitrate is not changed. The song URL is '.green + utils.getPlaybackUrl().green); | ||
console.log('Download bitrate is not changed. The song URL is '.green + utils.netease.getDownloadUrl(res.defaultBody).green); | ||
next(); | ||
@@ -123,7 +165,6 @@ } | ||
// console.log(utils.headers); | ||
// console.log(utils.body); | ||
res.set(utils.headers); | ||
res.send(utils.body); | ||
// console.log(res.defaultBody); | ||
res.send(res.defaultBody); | ||
}); | ||
module.exports = router; |
@@ -1,292 +0,10 @@ | ||
var request = require('request'); | ||
var md5 = require('md5'); | ||
var base64 = require('base-64'); | ||
var PythonShell = require('python-shell'); | ||
var waterfall = require("async/waterfall"); | ||
var colors = require('colors'); | ||
var netease = require('./netease'); | ||
var kugou = require('./kugou'); | ||
var baseUrl = "http://223.252.199.7"; | ||
var utils = function() { | ||
this.body = ''; | ||
this.headers = ''; | ||
this.netease = new netease(); | ||
this.kugou = new kugou(); | ||
} | ||
utils.prototype.defaultPost = function(headers, body, url, callback) { | ||
var _this = this; | ||
_this.post(headers, body, url, function(err, headers, body) { | ||
if (err) { | ||
console.error(err); | ||
return callback(err); | ||
} else { | ||
_this.body = body; | ||
_this.headers = headers; | ||
delete _this.headers['content-encoding']; | ||
callback(null, headers, body); | ||
} | ||
}) | ||
} | ||
utils.prototype.post = function(headers, body, url, callback) { | ||
// console.log(headers); | ||
var _this = this; | ||
body = new Buffer(body); | ||
if(!/^http/.test(url)) { | ||
url = baseUrl + url; | ||
} | ||
// console.log(url); | ||
var options = { | ||
url: url, | ||
headers: headers, | ||
method: 'post', | ||
body: body, | ||
gzip: true | ||
}; | ||
request(options, function(err, res, body) { | ||
if (err) { | ||
console.error(err); | ||
return callback(err); | ||
} else { | ||
// console.log(res.headers); | ||
callback(null, res.headers, body); | ||
} | ||
}); | ||
} | ||
utils.prototype.get = function(headers, url, callback) { | ||
var _this = this; | ||
if(!/^http/.test(url)) { | ||
url = baseUrl + url; | ||
} | ||
// console.log(url); | ||
var options = { | ||
url: url, | ||
headers: headers, | ||
method: 'get', | ||
gzip: true | ||
}; | ||
request(options, function(err, res, body) { | ||
if (err) { | ||
console.error(err); | ||
return callback(err); | ||
} else { | ||
// console.log(res.headers); | ||
// console.log(body); | ||
callback(null, res.headers, body); | ||
} | ||
}); | ||
} | ||
utils.prototype.getPlaybackBitrate = function() { | ||
// console.log(this.body); | ||
var body = JSON.parse(this.body); | ||
return body["data"][0]["br"]; | ||
} | ||
utils.prototype.getPlaybackReturnCode = function() { | ||
var body = JSON.parse(this.body); | ||
return body["data"][0]["code"]; | ||
} | ||
utils.prototype.getPlaybackUrl = function() { | ||
var body = JSON.parse(this.body); | ||
return body["data"][0]["url"]; | ||
} | ||
utils.prototype.getDownloadBitrate = function() { | ||
// console.log(this.body); | ||
var body = JSON.parse(this.body); | ||
return body["data"]["br"]; | ||
} | ||
utils.prototype.getDownloadReturnCode = function() { | ||
var body = JSON.parse(this.body); | ||
return body["data"]["code"]; | ||
} | ||
utils.prototype.getDownloadUrl = function() { | ||
var body = JSON.parse(this.body); | ||
return body["data"]["url"]; | ||
} | ||
utils.prototype.getEncId = function(dfsId, callback) { | ||
// var magicBytes = new Buffer('3go8&$8*3*3h0k(2)2'); | ||
// var songId = new Buffer(dfsId.toString()); | ||
// for (var i = 0; i < songId.length; i++) { | ||
// songId[i] = songId[i] ^ magicBytes[i % magicBytes.length]; | ||
// } | ||
// // console.log(songId); | ||
// var hash = md5(songId.toString()); | ||
// return base64.encode(hash) | ||
// .replace('/', '_') | ||
// .replace('+', '-'); | ||
var options = { | ||
mode: 'text', | ||
args: [dfsId] | ||
}; | ||
PythonShell.run('./utils/get_enc_id.py', options, function(err, results) { | ||
if (err) { | ||
console.error(err.red); | ||
return callback(err); | ||
} else { | ||
callback(null, results[0]); | ||
} | ||
}); | ||
} | ||
utils.prototype.generateUrl = function(dfsId, callback) { | ||
var s = (new Date()).getSeconds() % 2 + 1; | ||
this.getEncId(dfsId, function(err, encId) { | ||
if (err) { | ||
console.error(err.red); | ||
return callback(err); | ||
} else { | ||
var url = "http://m" + s + ".music.126.net/" + encId + "/" + dfsId + ".mp3"; | ||
callback(null, url) | ||
} | ||
}); | ||
} | ||
utils.prototype.getDfsId = function(pageContent) { | ||
var body = JSON.parse(pageContent); | ||
// Downgrade if we don't have higher quality... | ||
var nQuality = 'h'; | ||
if (nQuality == "h" && !!!body["songs"][0]["h"]) { | ||
nQuality = "m"; | ||
} | ||
if (nQuality == "m" && !!!body["songs"][0]["m"]) { | ||
nQuality = "l"; | ||
} | ||
if (nQuality == "l" && !!!body["songs"][0]["l"]) { | ||
nQuality = "b"; | ||
} | ||
if (nQuality == "b" && !!!body["songs"][0]["b"]) { | ||
console.log('Song url not found.'.red) | ||
} | ||
return body["songs"][0][nQuality]["fid"]; | ||
} | ||
utils.prototype.getUrl = function(songId, callback) { | ||
var _this = this; | ||
waterfall([ | ||
function(cb) { | ||
// Make post data | ||
var data = [{ | ||
id: songId, | ||
v: 0 | ||
}]; | ||
data = "c=" + JSON.stringify(data); | ||
cb(null, data); | ||
}, | ||
function(data, cb) { | ||
// Make post header | ||
var header = { | ||
'host': 'music.163.com', | ||
'cookie': 'os=pc', | ||
'content-length': data.length, | ||
'content-type': 'application/x-www-form-urlencoded' | ||
}; | ||
cb(null, header, data); | ||
}, | ||
function(header, data, cb) { | ||
// Do post and get dfsId | ||
_this.post(header, data, "/api/v2/song/detail", function(err, res, body) { | ||
if (err) { | ||
console.error(err.red); | ||
return cb(err); | ||
} else { | ||
var dfsId = _this.getDfsId(body); | ||
return cb(null, dfsId); | ||
} | ||
}); | ||
}, | ||
function(dfsId, cb) { | ||
// Generate url | ||
_this.generateUrl(dfsId, function(err, url) { | ||
if (err) { | ||
console.error(err.red); | ||
return cb(err); | ||
} else { | ||
cb(null, url); | ||
} | ||
}) | ||
} | ||
], function(err, url) { | ||
if (err) { | ||
console.error(err.red); | ||
return callback(err); | ||
} else { | ||
callback(null, url); | ||
} | ||
}); | ||
} | ||
utils.prototype.modifyDetailApi = function() { | ||
console.log("Song Detail API Injected".green); | ||
this.body = this.body | ||
.replace(/\"pl\":\d+/g, '"pl":320000') | ||
.replace(/\"dl\":\d+/g, '"dl":320000') | ||
.replace(/\"st\":-?\d+/g, '"st":0') | ||
.replace(/\"subp\":\d+/g, '"subp":1'); | ||
// console.log(this.body); | ||
} | ||
utils.prototype.modifyPlayerApi = function(callback) { | ||
console.log("Player API Injected".green); | ||
var _this = this; | ||
var body = JSON.parse(_this.body); | ||
var songId = body["data"][0]["id"]; | ||
_this.getUrl(songId, function(err, newUrl) { | ||
if (err) { | ||
console.error(err.red); | ||
return callback(err); | ||
} else { | ||
var newUrl = newUrl; | ||
console.log("New URL is ".green + newUrl.green); | ||
body["data"][0]["url"] = newUrl; | ||
body["data"][0]["br"] = 320000; | ||
body["data"][0]["code"] = "200"; | ||
_this.body = JSON.stringify(body); | ||
callback(null); | ||
} | ||
}); | ||
} | ||
utils.prototype.modifyDownloadApi = function(callback) { | ||
console.log("Download API Injected".green); | ||
var _this = this; | ||
var body = JSON.parse(_this.body); | ||
var songId = body["data"]["id"]; | ||
_this.getUrl(songId, function(err, newUrl) { | ||
if (err) { | ||
console.error(err.red); | ||
return callback(err); | ||
} else { | ||
var newUrl = newUrl; | ||
console.log("New URL is ".green + newUrl.green); | ||
body["data"]["url"] = newUrl; | ||
body["data"]["br"] = 320000; | ||
body["data"]["code"] = "200"; | ||
_this.body = JSON.stringify(body); | ||
callback(null); | ||
} | ||
}); | ||
} | ||
module.exports = utils; |
@@ -1,6 +0,29 @@ | ||
var utils = new(require('./index')); | ||
var netease = new(require('./netease')); | ||
utils.getUrl('399953237', function(err, url){ | ||
netease.getMusicDetail('589979', function(err, detail){ | ||
console.log(err); | ||
console.log(url); | ||
console.log(detail['songs'][0]); | ||
}); | ||
// var kugou = new(require('./kugou')); | ||
// | ||
// kugou.getUrl('efba483eb717cc872436075748bcfcf8', function(err, url){ | ||
// console.log(url); | ||
// }); | ||
// var request = require('request'); | ||
// | ||
// var options = { | ||
// url: 'http://media.store.kugou.com/v1/get_res_privilege', | ||
// method: 'post', | ||
// body: '{"appid":1001,"behavior":"play","clientver":"8043","relate":1,"resource":[{"album_id":"544828","hash":"c70b75dd07aabe2ae76b0cdaff007057","id":0,"name":"刘瑞琦 - 晴天.flac","type":"audio"}],"token":"","userid":87549184,"vip":1}', | ||
// gzip: true | ||
// }; | ||
// request(options, function(err, res, body) { | ||
// if (err) { | ||
// console.error(err); | ||
// } else { | ||
// // console.log(res.headers); | ||
// console.log(body); | ||
// } | ||
// }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
17162
8
12
424
53
1
- Removedbase-64@^0.1.0
- Removedcookie-parser@~1.3.5
- Removedpython-shell@^0.4.0
- Removedserve-favicon@~2.3.0
- Removedbase-64@0.1.0(transitive)
- Removedcookie@0.1.3(transitive)
- Removedcookie-parser@1.3.5(transitive)
- Removedms@0.7.2(transitive)
- Removedpython-shell@0.4.0(transitive)
- Removedserve-favicon@2.3.2(transitive)