Bladeren bron

fix netease interface

Dotos 8 jaren geleden
bovenliggende
commit
8d616a13c9
4 gewijzigde bestanden met toevoegingen van 254 en 150 verwijderingen
  1. 46 44
      package.json
  2. 122 35
      routes/netease.js
  3. 53 62
      utils/Crypto.js
  4. 33 9
      utils/utils.js

+ 46 - 44
package.json

@@ -1,45 +1,47 @@
 {
-  "name": "JsonBird",
-  "version": "1.4.0",
-  "description": "A remote data interface proxy service",
-  "author": {
-    "name": "xCss",
-    "mail": "yy.liu@foxmail.com"
-  },
-  "license": "MIT",
-  "private": true,
-  "scripts": {
-    "start": "node ./bin/www",
-    "super": "supervisor ./bin/www"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/xCss/JsonBird.git"
-  },
-  "keywords": [
-    "JsonBird",
-    "proxy",
-    "data interface proxy",
-    "remote data interface proxy"
-  ],
-  "bugs": {
-    "url": "https://github.com/xCss/JsonBird/issues"
-  },
-  "readme": "./readme.md",
-  "homepage": "https://github.com/xCss/JsonBird#readme",
-  "dependencies": {
-    "big-integer": "^1.6.17",
-    "blueimp-md5": "^2.7.0",
-    "body-parser": "~1.15.1",
-    "cookie-parser": "~1.4.3",
-    "debug": "~2.2.0",
-    "express": "~4.13.4",
-    "express-generator": "^4.13.4",
-    "helmet": "^2.3.0",
-    "js-base64": "^2.1.9",
-    "morgan": "~1.7.0",
-    "pug": "^2.0.0-beta6",
-    "serve-favicon": "~2.3.0",
-    "superagent": "^2.3.0"
-  }
-}
+    "name": "JsonBird",
+    "version": "1.4.0",
+    "description": "A remote data interface proxy service",
+    "author": {
+        "name": "xCss",
+        "mail": "yy.liu@foxmail.com"
+    },
+    "license": "MIT",
+    "private": true,
+    "scripts": {
+        "start": "supervisor node ./bin/www",
+        "super": "supervisor ./bin/www"
+    },
+    "repository": {
+        "type": "git",
+        "url": "git+https://github.com/xCss/JsonBird.git"
+    },
+    "keywords": [
+        "JsonBird",
+        "proxy",
+        "data interface proxy",
+        "remote data interface proxy"
+    ],
+    "bugs": {
+        "url": "https://github.com/xCss/JsonBird/issues"
+    },
+    "readme": "./readme.md",
+    "homepage": "https://github.com/xCss/JsonBird#readme",
+    "dependencies": {
+        "big-integer": "^1.6.17",
+        "blueimp-md5": "^2.7.0",
+        "body-parser": "~1.15.1",
+        "cookie-parser": "~1.4.3",
+        "debug": "~2.2.0",
+        "express": "~4.13.4",
+        "express-generator": "^4.13.4",
+        "helmet": "^2.3.0",
+        "js-base64": "^2.1.9",
+        "morgan": "~1.7.0",
+        "pug": "^2.0.0-beta6",
+        "querystring": "^0.2.0",
+        "request": "^2.81.0",
+        "serve-favicon": "~2.3.0",
+        "superagent": "^2.3.0"
+    }
+}

+ 122 - 35
routes/netease.js

@@ -2,43 +2,130 @@ var express = require('express');
 var request = require('superagent');
 var router = express.Router();
 
-/* GET users listing. */
-router.get('/', function(req, res, next) {
-    res.header("Content-Type", "application/json;charset=utf-8");
-    //console.log('ref:' + req.header('referer'));
-    var id = req.query.id;
-    var playlist_id = req.query.playlist_id;
-    var headers = {};
-    headers['Cookie'] = 'appver=1.5.0.75771;';
-    headers['referer'] = 'http://music.163.com';
-    headers['User-Agent'] = req.headers['user-agent'];
+const util = require('../utils/utils')
+
+const links = {
+    song: '/weapi/v3/song/detail',
+    song_url: '/weapi/song/enhance/player/url',
+    playlist: '/weapi/v3/playlist/detail'
+}
 
-    var url = 'http://music.163.com/api/song/detail/?id=' + id + '&ids=%5B' + id + '%5D';
-    if (playlist_id) {
-        url = 'http://music.163.com/api/playlist/detail/?id=' + playlist_id;
+/* GET users listing. */
+router.get('/:channel', function(req, res, next) {
+    const id = req.query.id
+    const br = req.query.br || 999000
+    const channel = req.params['channel']
+    let config = {
+        path: links[channel],
+        params: {
+            "ids": [id],
+            "br": 999000,
+            "csrf_token": ""
+        }
     }
-    netease_http(headers, url, next, function(data) {
-        var songs = data.songs;
-        songs.map(function(item) {
-            var url = item['mp3Url'];
-            item['sslUrl'] = url.replace('http://m', 'https://p');
-            return item;
-        });
-        data.songs = songs;
-        res.send(data)
-            // var output = {
-            //     data: data,
-            //     status: {
-            //         code: 200,
-            //         message: ''
-            //     }
-            // };
-            // if (req.query.callback) {
-            //     return res.jsonp(output)
-            // } else {
-            //     return res.send(output);
-            // }
-    });
+    switch (channel) {
+        case 'playlist':
+            config['params'] = {
+                "id": id,
+                "offset": 0,
+                "total": true,
+                "limit": 1000,
+                "n": 1000,
+                "csrf_token": ""
+            }
+            break;
+        case 'song':
+            config['params'] = {
+                'c': JSON.stringify([{ id: id }]),
+                "ids": '[' + id + ']',
+                "csrf_token": ""
+            }
+            break;
+        default:
+            res.send({
+                data: {},
+                status: {
+                    code: -1,
+                    msg: 'no support url. Please set `song` or `playlist`'
+                }
+            })
+            break;
+    }
+    util.requestServer(config).then(ret => {
+        if (channel == 'song') {
+            config['path'] = links.song_url
+            config['params'] = {
+                "ids": [id],
+                "br": br,
+                "csrf_token": ""
+            }
+            util.requestServer(config).then(rt => {
+                let song = ret.songs[0]
+                song['mp3'] = rt.data[0]
+                res.send({
+                    data: song,
+                    status: {
+                        code: 200,
+                        msg: ''
+                    }
+                })
+            }).catch(ex => {
+                res.send({
+                    data: {},
+                    status: {
+                        code: -1,
+                        msg: 'something happend. Please checked your id or url'
+                    }
+                })
+            })
+        } else {
+            res.send(ret)
+        }
+    }).catch(err => {
+        res.send({
+            data: {},
+            status: {
+                code: -1,
+                msg: 'something happend. Please checked your id or url'
+            }
+        })
+    })
+
+    // res.header("Content-Type", "application/json;charset=utf-8");
+    // //console.log('ref:' + req.header('referer'));
+    // var id = req.query.id;
+    // var playlist_id = req.query.playlist_id;
+    // var headers = {};
+    // headers['Cookie'] = 'appver=1.5.0.75771;';
+    // headers['referer'] = 'http://music.163.com';
+    // headers['User-Agent'] = req.headers['user-agent'];
+
+    // var url = 'http://music.163.com/api/song/detail/?id=' + id + '&ids=%5B' + id + '%5D';
+    // if (playlist_id) {
+    //     url = 'http://music.163.com/api/playlist/detail/?id=' + playlist_id;
+    // }
+    // netease_http(headers, url, next, function(data) {
+    //     var songs = data.songs;
+    //     songs.map(function(item) {
+    //         var url = item['mp3Url'];
+    //         item['sslUrl'] = url.replace('http://m', 'https://p');
+    //         return item;
+    //     });
+    //     data.songs = songs;
+    //     res.send(data)
+    //         // var output = {
+    //         //     data: data,
+    //         //     status: {
+    //         //         code: 200,
+    //         //         message: ''
+    //         //     }
+    //         // };
+    //         // if (req.query.callback) {
+    //         //     return res.jsonp(output)
+    //         // } else {
+    //         //     return res.send(output);
+    //         // }
+    // });
 });
 
 function netease_http(headers, url, next, callback) {

+ 53 - 62
utils/Crypto.js

@@ -1,75 +1,66 @@
-var crypto = require('crypto');
-var bigInt = require('big-integer');
+// 参考 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'
 
-function addPadding(encText, modulus) {
-    var ml = modulus.length;
-    for (i = 0; ml > 0 && modulus[i] == '0'; i++) ml--;
-    var num = ml - encText.length,
-        prefix = '';
-    for (var i = 0; i < num; i++) {
-        prefix += '0';
+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 prefix + encText;
+    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) {
-    var cipher = crypto.createCipheriv('AES-128-CBC', secKey, '0102030405060708');
-    return cipher.update(text, 'utf-8', 'base64') + cipher.final('base64');
+    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
 }
 
-/**
- * RSA Encryption algorithm.
- * @param text {string} - raw data to encrypt
- * @param exponent {string} - public exponent
- * @param modulus {string} - modulus
- * @returns {string} - encrypted data: reverseText^pubKey%modulus
- */
-function rsaEncrypt(text, exponent, modulus) {
-    var rText = '',
-        radix = 16;
-    for (var i = text.length - 1; i >= 0; i--) rText += text[i]; //reverse text
-    var biText = bigInt(new Buffer(rText).toString('hex'), radix),
-        biEx = bigInt(exponent, radix),
-        biMod = bigInt(modulus, radix),
-        biRet = biText.modPow(biEx, biMod);
-    return addPadding(biRet.toString(radix), modulus);
+function zfill(str, size) {
+    while (str.length < size) str = "0" + str
+    return str
 }
 
-function createSecretKey(size) {
-    var keys = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-    var key = "";
-    for (var i = 0; i < size; i++) {
-        var pos = Math.random() * keys.length;
-        pos = Math.floor(pos);
-        key = key + keys.charAt(pos)
-    }
-    return key;
+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)
 }
-var modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7';
-var nonce = '0CoJUm6Qyw8W8jud';
-var pubKey = '010001';
-var Crypto = {
-    MD5: function(text) {
-        return crypto.createHash('md5').update(text).digest('hex');
-    },
-    aesRsaEncrypt: function(text) {
-        var secKey = createSecretKey(16);
-        return {
-            params: aesEncrypt(aesEncrypt(text, nonce), secKey),
-            encSecKey: rsaEncrypt(secKey, pubKey, modulus)
-        }
-    },
-    encrypted_id: function(id) {
-        var magic = Buffer.from('3go8&$8*3*3h0k(2)2', 'ascii');
-        var len = magic.length;
-        var sid = Buffer.from(id, 'ascii');
-        for (var i in sid) {
-            sid[i] = sid[i] ^ magic[i % len];
-        }
-        sid = crypto.createHash('md5').update(sid).digest();
-        return sid.toString('base64').replace(/\//g, '_').replace(/\+/g, '-');
+
+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 = Crypto;
+module.exports = Encrypt

+ 33 - 9
utils/utils.js

@@ -1,10 +1,34 @@
-module.exports = {
-    urlParams: {
-        get: function(key) {
-            return '';
-        },
-        set: function(param) {
-            return '';
-        },
+const Encrypt = require('./crypto');
+const request = require('request');
+const qs = require('querystring');
+
+let options = {
+    method: 'POST',
+    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': 'appver=2.0.2;',
+        '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',
     }
-};
+}
+const requestServer = (config) => {
+    options['uri'] = `http://music.163.com${config.path}`
+    let params = Encrypt(config.params)
+    return new Promise((resolve, reject) => {
+        request.post({ url: options.uri, form: params }, (err, ret, body) => {
+            if (!err && ret.statusCode === 200) {
+                resolve(JSON.parse(body))
+            } else {
+                reject(err)
+            }
+        })
+    })
+}
+
+module.exports = {
+    requestServer
+}