request.js 8.0 KB
Newer Older
N
Nzix 已提交
1
const encrypt = require('./crypto')
N
Nzix 已提交
2 3
const request = require('request')
const queryString = require('querystring')
T
trazyn 已提交
4
const PacProxyAgent = require('pac-proxy-agent')
L
lizhenyuls 已提交
5
const zlib = require('zlib')
N
Nzix 已提交
6

7 8 9 10
// request.debug = true // 开启可看到更详细信息

const chooseUserAgent = ua => {
  const userAgentList = [
H
huggy 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
    // iOS 13.5.1 14.0 beta with safari
    'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1',
    'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.',
    // iOS with qq micromsg
    'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/602.1.50 (KHTML like Gecko) Mobile/14A456 QQ/6.5.7.408 V1_IPH_SQ_6.5.7_1_APP_A Pixel/750 Core/UIWebView NetType/4G Mem/103',
    'Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.15(0x17000f27) NetType/WIFI Language/zh',
    // Android -> Huawei Xiaomi 
    'Mozilla/5.0 (Linux; Android 9; PCT-AL10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.311 Mobile Safari/537.36',
    'Mozilla/5.0 (Linux; U; Android 9; zh-cn; Redmi Note 8 Build/PKQ1.190616.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.141 Mobile Safari/537.36 XiaoMi/MiuiBrowser/12.5.22',
    // Android with qq micromsg
    'Mozilla/5.0 (Linux; Android 10; YAL-AL00 Build/HUAWEIYAL-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2581 MMWEBSDK/200801 Mobile Safari/537.36 MMWEBID/3027 MicroMessenger/7.0.18.1740(0x27001235) Process/toolsmp WeChat/arm64 NetType/WIFI Language/zh_CN ABI/arm64',
    'Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; BKK-AL10 Build/HONORBKK-AL10) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/10.6 Mobile Safari/537.36',
    // macOS 10.15.6  Firefox / Chrome / Safari
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:80.0) Gecko/20100101 Firefox/80.0',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.30 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15',
    // Windows 10 Firefox / Chrome / Edge
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.30 Safari/537.36',
30 31 32 33 34
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/13.10586'
  ]
  let index = 0
  if (typeof ua == 'undefined')
    index = Math.floor(Math.random() * userAgentList.length)
L
lizhenyuls 已提交
35 36
  else if (ua === 'mobile') index = Math.floor(Math.random() * 7)
  else if (ua === 'pc') index = Math.floor(Math.random() * 5) + 8
37 38
  else return ua
  return userAgentList[index]
N
Nzix 已提交
39 40
}

N
Nzix 已提交
41
const createRequest = (method, url, data, options) => {
42 43
  return new Promise((resolve, reject) => {
    let headers = { 'User-Agent': chooseUserAgent(options.ua) }
L
lizhenyuls 已提交
44
    if (method.toUpperCase() === 'POST')
45 46
      headers['Content-Type'] = 'application/x-www-form-urlencoded'
    if (url.includes('music.163.com'))
47
      headers['Referer'] = 'https://music.163.com'
A
a632079 已提交
48 49
    if (options.realIP)
      headers['X-Real-IP'] = options.realIP
50 51 52 53 54 55 56 57 58 59 60
    // headers['X-Real-IP'] = '118.88.88.88'
    if (typeof options.cookie === 'object')
      headers['Cookie'] = Object.keys(options.cookie)
        .map(
          key =>
            encodeURIComponent(key) +
            '=' +
            encodeURIComponent(options.cookie[key])
        )
        .join('; ')
    else if (options.cookie) headers['Cookie'] = options.cookie
H
huggy 已提交
61

62 63 64
    if (!headers['Cookie']) {
      headers['Cookie'] = options.token || ''
    }
L
lizhenyuls 已提交
65
    if (options.crypto === 'weapi') {
66 67 68 69
      let csrfToken = (headers['Cookie'] || '').match(/_csrf=([^(;|$)]+)/)
      data.csrf_token = csrfToken ? csrfToken[1] : ''
      data = encrypt.weapi(data)
      url = url.replace(/\w*api/, 'weapi')
L
lizhenyuls 已提交
70
    } else if (options.crypto === 'linuxapi') {
71 72 73 74 75 76
      data = encrypt.linuxapi({
        method: method,
        url: url.replace(/\w*api/, 'api'),
        params: data
      })
      headers['User-Agent'] =
H
huggy 已提交
77
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'
78
      url = 'https://music.163.com/api/linux/forward'
L
lizhenyuls 已提交
79 80 81 82
    } else if (options.crypto === 'eapi') {
      const cookie = options.cookie || {};
      const csrfToken = cookie['__csrf'] || ''
      const header = {
B
binaryify 已提交
83 84 85 86 87 88 89 90 91 92 93
        'osver': cookie.osver, //系统版本
        'deviceId': cookie.deviceId, //encrypt.base64.encode(imei + '\t02:00:00:00:00:00\t5106025eb79a5247\t70ffbaac7')
        'appver': cookie.appver || '6.1.1', // app版本
        'versioncode': cookie.versioncode || '140', //版本号
        'mobilename': cookie.mobilename, //设备model
        'buildver': cookie.buildver || Date.now().toString().substr(0, 10),
        'resolution': cookie.resolution || '1920x1080', //设备分辨率
        '__csrf': csrfToken,
        'os': cookie.os || 'android',
        'channel': cookie.channel,
        'requestId': `${Date.now()}_${Math.floor(Math.random() * 1000).toString().padStart(4, '0')}`
L
lizhenyuls 已提交
94
      }
B
binaryify 已提交
95 96
      if (cookie.MUSIC_U) header['MUSIC_U'] = cookie.MUSIC_U
      if (cookie.MUSIC_A) header['MUSIC_A'] = cookie.MUSIC_A
L
lizhenyuls 已提交
97 98 99 100 101 102 103 104 105 106
      headers['Cookie'] = Object.keys(header)
        .map(
          key =>
            encodeURIComponent(key) +
            '=' +
            encodeURIComponent(header[key])
        )
        .join('; ')
      data.header = header
      data = encrypt.eapi(options.url, data)
B
binaryify 已提交
107
      url = url.replace(/\w*api/, 'eapi')
108
    }
N
Nzix 已提交
109

110
    const answer = { status: 500, body: {}, cookie: [] }
T
trazyn 已提交
111 112 113 114 115 116 117
    const settings = {
      method: method,
      url: url,
      headers: headers,
      body: queryString.stringify(data)
    }

L
lizhenyuls 已提交
118 119
    if (options.crypto === 'eapi') settings.encoding = null

T
trazyn 已提交
120 121 122 123 124 125
    if (/\.pac$/i.test(options.proxy)) {
      settings.agent = new PacProxyAgent(options.proxy)
    } else {
      settings.proxy = options.proxy
    }

126
    request(
T
trazyn 已提交
127
      settings,
128 129 130 131 132 133 134 135 136 137
      (err, res, body) => {
        if (err) {
          answer.status = 502
          answer.body = { code: 502, msg: err.stack }
          reject(answer)
        } else {
          answer.cookie = (res.headers['set-cookie'] || []).map(x =>
            x.replace(/\s*Domain=[^(;|$)]+;*/, '')
          )
          try {
L
lizhenyuls 已提交
138 139 140 141 142
            if (options.crypto === 'eapi') {

              zlib.unzip(body, function (err, buffer) {
                const _buffer = err ? body : buffer
                try {
H
huggy 已提交
143
                  try {
L
lizhenyuls 已提交
144 145
                    answer.body = JSON.parse(encrypt.decrypt(_buffer).toString())
                    answer.status = answer.body.code || res.statusCode
H
huggy 已提交
146
                  } catch (e) {
L
lizhenyuls 已提交
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
                    answer.body = JSON.parse(_buffer.toString())
                    answer.status = res.statusCode
                  }
                } catch (e) {
                  answer.body = _buffer.toString()
                  answer.status = res.statusCode
                }
                answer.status =
                  100 < answer.status && answer.status < 600 ? answer.status : 400
                if (answer.status === 200) resolve(answer)
                else reject(answer)
              });
              return false

            } else {

              answer.body = JSON.parse(body)
              answer.status = answer.body.code || res.statusCode
H
huggy 已提交
165
              if (answer.body.code === 502) {
166 167
                answer.status = 200
              }
L
lizhenyuls 已提交
168 169
            }

170 171 172 173
          } catch (e) {
            answer.body = body
            answer.status = res.statusCode
          }
L
lizhenyuls 已提交
174

175 176 177 178
          answer.status =
            100 < answer.status && answer.status < 600 ? answer.status : 400
          if (answer.status == 200) resolve(answer)
          else reject(answer)
N
Nzix 已提交
179
        }
180 181 182
      }
    )
  })
N
Nzix 已提交
183 184 185
}

module.exports = createRequest