diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index f68af62..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,57 +0,0 @@ -module.exports = { - root: true, - - ignorePatterns: ['public/'], - parserOptions: { - parser: 'babel-eslint', - ecmaVersion: 2018, - sourceType: 'module', - }, - plugins: ['html'], - extends: ['plugin:prettier/recommended'], - env: { - browser: true, - node: true, - }, - - rules: { - 'prettier/prettier': [ - 'error', - { - endOfLine: 'auto', - }, - ], - indent: ['error', 2, { SwitchCase: 1 }], - 'space-infix-ops': ['error', { int32Hint: false }], - 'key-spacing': [ - 2, - { - beforeColon: false, - afterColon: true, - }, - ], - 'no-octal': 2, - 'no-redeclare': 2, - 'comma-spacing': 2, - 'no-new-object': 2, - 'arrow-spacing': 2, - quotes: [ - 2, - 'single', - { - avoidEscape: true, - allowTemplateLiterals: true, - }, - ], - }, - overrides: [ - { - files: ['**/*.ts'], - parser: '@typescript-eslint/parser', - extends: [ - 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin - // 'prettier/@typescript-eslint', - ], - }, - ], -} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..7e1d03c --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,91 @@ +const { defineConfig, globalIgnores } = require('eslint/config') + +const html = require('eslint-plugin-html') +const globals = require('globals') +const tsParser = require('@typescript-eslint/parser') +const js = require('@eslint/js') + +const { FlatCompat } = require('@eslint/eslintrc') + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}) + +module.exports = defineConfig([ + { + languageOptions: { + ecmaVersion: 2018, + sourceType: 'module', + parserOptions: { + parser: 'babel-eslint', + }, + globals: { + ...globals.browser, + ...globals.node, + }, + }, + + plugins: { + html, + }, + + extends: compat.extends('plugin:prettier/recommended'), + + rules: { + 'prettier/prettier': [ + 'error', + { + endOfLine: 'auto', + }, + ], + + indent: [ + 'error', + 2, + { + SwitchCase: 1, + }, + ], + + 'space-infix-ops': [ + 'error', + { + int32Hint: false, + }, + ], + + 'key-spacing': [ + 2, + { + beforeColon: false, + afterColon: true, + }, + ], + + 'no-octal': 2, + 'no-redeclare': 2, + 'comma-spacing': 2, + 'no-new-object': 2, + 'arrow-spacing': 2, + + quotes: [ + 2, + 'single', + { + avoidEscape: true, + allowTemplateLiterals: true, + }, + ], + }, + }, + globalIgnores(['**/public/']), + { + files: ['**/*.ts'], + languageOptions: { + parser: tsParser, + }, + extends: compat.extends('plugin:@typescript-eslint/recommended'), + }, +]) diff --git a/module/song_url_match.js b/module/song_url_match.js index b339136..791f6fd 100644 --- a/module/song_url_match.js +++ b/module/song_url_match.js @@ -5,31 +5,34 @@ const createOption = require('../util/option.js') const logger = require('../util/logger.js') module.exports = async (query, request) => { - try { - const match = require("@unblockneteasemusic/server") - const source = query.source - ? query.source.split(',') : ['pyncmd', 'bodian','kuwo', 'qq', 'migu', 'kugou'] - const server = query.server ? query.server.split(',') : query.server - const result = await match(query.id, !server? source : server) - const proxy = process.env.PROXY_URL; - logger.info("开始解灰", query.id, result) - const useProxy = process.env.ENABLE_PROXY || "false" - if (result.url.includes('kuwo')) { result.proxyUrl = useProxy === 'true' ? proxy + result.url : result.url } - return { - status: 200, - body: { - code: 200, - data: result, - }, - } - } catch (e) { - return { - status: 500, - body: { - code: 500, - msg: e.message || 'unblock error', - data: [], - }, - } + try { + const match = require('@unblockneteasemusic/server') + const source = query.source + ? query.source.split(',') + : ['pyncmd', 'bodian', 'kuwo', 'qq', 'migu', 'kugou'] + const server = query.server ? query.server.split(',') : query.server + const result = await match(query.id, !server ? source : server) + const proxy = process.env.PROXY_URL + logger.info('开始解灰', query.id, result) + const useProxy = process.env.ENABLE_PROXY || 'false' + if (result.url.includes('kuwo')) { + result.proxyUrl = useProxy === 'true' ? proxy + result.url : result.url } -} \ No newline at end of file + return { + status: 200, + body: { + code: 200, + data: result, + }, + } + } catch (e) { + return { + status: 500, + body: { + code: 500, + msg: e.message || 'unblock error', + data: [], + }, + } + } +} diff --git a/module/song_url_ncmget.js b/module/song_url_ncmget.js index 4fd9d22..a2c5852 100644 --- a/module/song_url_ncmget.js +++ b/module/song_url_ncmget.js @@ -5,71 +5,73 @@ const createOption = require('../util/option.js') module.exports = async (query, request) => { - try { - const { id, br = "320" } = query; - if (!id) { - return { - status: 400, - body: { - code: 400, - message: "缺少必要参数 id", - data: [], - }, - }; - } - const validBR = ["128", "192", "320", "740", "999"]; - // const covertBR = ["128000", "192000", "320000","740000", "999000"]; - if (!validBR.includes(br)) { - return { - status: 400, - body: { - code: 400, - message: "无效音质参数", - allowed_values: validBR, - data: [], - }, - }; - } - - const apiUrl = new URL("https://music-api.gdstudio.xyz/api.php"); - apiUrl.searchParams.append("types", "url"); - apiUrl.searchParams.append("id", id); - apiUrl.searchParams.append("br", br); - - const response = await fetch(apiUrl.toString()); - if (!response.ok) throw new Error(`API 响应状态: ${response.status}`); - const result = await response.json(); - - // 代理逻辑 - const useProxy = process.env.ENABLE_PROXY || false; - const proxy = process.env.PROXY_URL; - if (useProxy && result.url && result.url.includes("kuwo")) { - result.proxyUrl = proxy + result.url.replace(/^http:\/\//, "http/"); - } - - return { - status: 200, - body: { - code: 200, - message: "请求成功", - data: { - id, - br, - url: result.url, - ...(proxy && result.proxyUrl ? { proxyUrl: result.proxyUrl } : {}) - } - } - }; - } catch (error) { - console.error("Error in song_url_ncmget:", error); - return { - status: 500, - body: { - code: 500, - message: "服务器处理请求失败", - ...(process.env.NODE_ENV === "development" ? { error: error.message } : {}), - data: [], - }, - }; + try { + const { id, br = '320' } = query + if (!id) { + return { + status: 400, + body: { + code: 400, + message: '缺少必要参数 id', + data: [], + }, + } } + const validBR = ['128', '192', '320', '740', '999'] + // const covertBR = ['128000', '192000', '320000','740000', '999000'] + if (!validBR.includes(br)) { + return { + status: 400, + body: { + code: 400, + message: '无效音质参数', + allowed_values: validBR, + data: [], + }, + } + } + + const apiUrl = new URL('https://music-api.gdstudio.xyz/api.php') + apiUrl.searchParams.append('types', 'url') + apiUrl.searchParams.append('id', id) + apiUrl.searchParams.append('br', br) + + const response = await fetch(apiUrl.toString()) + if (!response.ok) throw new Error(`API 响应状态: ${response.status}`) + const result = await response.json() + + // 代理逻辑 + const useProxy = process.env.ENABLE_PROXY || false + const proxy = process.env.PROXY_URL + if (useProxy && result.url && result.url.includes('kuwo')) { + result.proxyUrl = proxy + result.url.replace(/^http:\/\//, 'http/') + } + + return { + status: 200, + body: { + code: 200, + message: '请求成功', + data: { + id, + br, + url: result.url, + ...(proxy && result.proxyUrl ? { proxyUrl: result.proxyUrl } : {}), + }, + }, + } + } catch (error) { + console.error('Error in song_url_ncmget:', error) + return { + status: 500, + body: { + code: 500, + message: '服务器处理请求失败', + ...(process.env.NODE_ENV === 'development' + ? { error: error.message } + : {}), + data: [], + }, + } + } } diff --git a/module/song_url_unblock.js b/module/song_url_unblock.js index f55af60..c1e47a0 100644 --- a/module/song_url_unblock.js +++ b/module/song_url_unblock.js @@ -5,31 +5,34 @@ const createOption = require('../util/option.js') const logger = require('../util/logger.js') module.exports = async (query, request) => { - try { - const match = require("@unblockneteasemusic/server") - const source = query.source - ? query.source.split(',') : ['pyncmd', 'bodian', 'kuwo', 'qq', 'migu', 'kugou'] - const server = query.server ? query.server.split(',') : query.server - const result = await match(query.id, !server? source : server) - const proxy = process.env.PROXY_URL; - logger.info("开始解灰", query.id, result) - const useProxy = process.env.ENABLE_PROXY || "false" - if (result.url.includes('kuwo') && useProxy === "true") { result.proxyUrl = proxy + result.url } - return { - status: 200, - body: { - code: 200, - data: result, - }, - } - } catch (e) { - return { - status: 500, - body: { - code: 500, - msg: e.message || 'unblock error', - data: [], - }, - } + try { + const match = require('@unblockneteasemusic/server') + const source = query.source + ? query.source.split(',') + : ['pyncmd', 'bodian', 'kuwo', 'qq', 'migu', 'kugou'] + const server = query.server ? query.server.split(',') : query.server + const result = await match(query.id, !server ? source : server) + const proxy = process.env.PROXY_URL + logger.info('开始解灰', query.id, result) + const useProxy = process.env.ENABLE_PROXY || 'false' + if (result.url.includes('kuwo')) { + result.proxyUrl = useProxy === 'true' ? proxy + result.url : result.url } -} \ No newline at end of file + return { + status: 200, + body: { + code: 200, + data: result, + }, + } + } catch (e) { + return { + status: 500, + body: { + code: 500, + msg: e.message || 'unblock error', + data: [], + }, + } + } +} diff --git a/module/song_url_v1.js b/module/song_url_v1.js index 97903b6..fae1989 100644 --- a/module/song_url_v1.js +++ b/module/song_url_v1.js @@ -18,12 +18,24 @@ module.exports = async (query, request) => { try { const result = await match(query.id, source) logger.info('开始解灰', query.id, result) - if (result.url.includes('kuwo')) { - const useProxy = process.env.ENABLE_PROXY || 'false' - var proxyUrl = useProxy === 'true' ? process.env.PROXY_URL + result.url : result.url + // avoid optional chaining for compatibility + let url + if (Array.isArray(result)) { + url = result[0] && result[0].url ? result[0].url : result[0] + } else { + url = result && result.url ? result.url : result } - let url = Array.isArray(result) ? (result[0]?.url || result[0]) : (result.url || result) + // decide proxyUrl after we resolved the actual url value + let proxyUrl = '' if (url) { + if (url.includes('kuwo')) { + const useProxy = process.env.ENABLE_PROXY || 'false' + if (useProxy === 'true' && process.env.PROXY_URL) { + proxyUrl = process.env.PROXY_URL + url + } else { + proxyUrl = url + } + } return { status: 200, body: { diff --git a/package.json b/package.json index 315b52c..c256833 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@neteasecloudmusicapienhanced/api", - "version": "4.29.12", + "version": "4.29.13", "description": "为停更的网易云音乐 NodeJs API 提供持续的维护!", "scripts": { "dev": "nodemon app.js", @@ -83,6 +83,8 @@ "yargs": "^18.0.0" }, "devDependencies": { + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.39.0", "@types/express": "^5.0.5", "@types/express-fileupload": "^1.5.1", "@types/mocha": "^10.0.10", @@ -93,6 +95,7 @@ "eslint-config-prettier": "10.1.8", "eslint-plugin-html": "8.1.3", "eslint-plugin-prettier": "5.5.4", + "globals": "^16.4.0", "husky": "9.1.7", "intelli-espower-loader": "1.1.0", "lint-staged": "16.2.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 93fba20..24c0e24 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,6 +54,12 @@ importers: specifier: ^18.0.0 version: 18.0.0 devDependencies: + '@eslint/eslintrc': + specifier: ^3.3.1 + version: 3.3.1 + '@eslint/js': + specifier: ^9.39.0 + version: 9.39.0 '@types/express': specifier: ^5.0.5 version: 5.0.5 @@ -84,6 +90,9 @@ importers: eslint-plugin-prettier: specifier: 5.5.4 version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.0))(eslint@9.39.0)(prettier@3.6.2) + globals: + specifier: ^16.4.0 + version: 16.4.0 husky: specifier: 9.1.7 version: 9.1.7 @@ -1193,6 +1202,10 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -3841,6 +3854,8 @@ snapshots: globals@14.0.0: {} + globals@16.4.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 diff --git a/server.js b/server.js index b51491e..704da1d 100644 --- a/server.js +++ b/server.js @@ -1,4 +1,4 @@ -require("dotenv").config(); +require('dotenv').config() const fs = require('fs') const path = require('path') const express = require('express') @@ -248,20 +248,28 @@ async function consturctServer(moduleDefs) { (req.baseUrl === '/song/url/v1' || req.baseUrl === '/song/url') && process.env.ENABLE_GENERAL_UNBLOCK === 'true' ) { - const song = moduleResponse['body']['data'][0] - if (song.freeTrialInfo !== null || !song.url || [1, 4].includes(song.fee)) { - const match = require('@unblockneteasemusic/server') - const source = process.env.UNBLOCK_SOURCE ? process.env.UNBLOCK_SOURCE.split(',') : ['pyncmd', 'bodian', 'kuwo', 'qq', 'migu', 'kugou'] - logger.info("开始解灰", source) - const { url } = await match(req.query.id, source) - song.url = url - song.freeTrialInfo = 'null' - logger.info("解灰成功!") + const song = moduleResponse.body.data[0] + if ( + song.freeTrialInfo !== null || + !song.url || + [1, 4].includes(song.fee) + ) { + const match = require('@unblockneteasemusic/server') + const source = process.env.UNBLOCK_SOURCE + ? process.env.UNBLOCK_SOURCE.split(',') + : ['pyncmd', 'bodian', 'kuwo', 'qq', 'migu', 'kugou'] + logger.info('开始解灰', source) + const { url } = await match(req.query.id, source) + song.url = url + song.freeTrialInfo = 'null' + logger.info('解灰成功!') } - if (song.url.includes('kuwo')) { - const proxy = process.env.PROXY_URL; + if (song.url && song.url.includes('kuwo')) { + const proxy = process.env.PROXY_URL const useProxy = process.env.ENABLE_PROXY || 'false' - if (useProxy === 'true' && proxy) {song.proxyUrl = proxy + song.url} + if (useProxy === 'true' && proxy) { + song.proxyUrl = proxy + song.url + } } } diff --git a/util/apicache.js b/util/apicache.js index 98cc22d..bf6ea13 100644 --- a/util/apicache.js +++ b/util/apicache.js @@ -155,9 +155,12 @@ function ApiCache() { } // add automatic cache clearing from duration, includes max limit on setTimeout - timers[key] = setTimeout(function () { - instance.clear(key, true) - }, Math.min(duration, 2147483647)) + timers[key] = setTimeout( + function () { + instance.clear(key, true) + }, + Math.min(duration, 2147483647), + ) } function accumulateContent(res, content) { diff --git a/util/client-sign.js b/util/client-sign.js index a55f2b5..43a30ff 100644 --- a/util/client-sign.js +++ b/util/client-sign.js @@ -1,5 +1,5 @@ -const crypto = require("crypto"); -const os = require("os"); +const crypto = require('crypto') +const os = require('os') class AdvancedClientSignGenerator { /** @@ -7,25 +7,25 @@ class AdvancedClientSignGenerator { */ static getRealMacAddress() { try { - const interfaces = os.networkInterfaces(); + const interfaces = os.networkInterfaces() for (let interfaceName in interfaces) { - const interface = interfaces[interfaceName]; - for (let i = 0; i < interface.length; i++) { - const alias = interface[i]; + const networkInterface = interfaces[interfaceName] + for (let i = 0; i < networkInterface.length; i++) { + const alias = networkInterface[i] // 排除内部地址和无效地址 if ( alias.mac && - alias.mac !== "00:00:00:00:00:00" && + alias.mac !== '00:00:00:00:00:00' && !alias.internal ) { - return alias.mac.toUpperCase(); + return alias.mac.toUpperCase() } } } - return null; + return null } catch (error) { - console.warn("获取MAC地址失败:", error.message); - return null; + console.warn('获取MAC地址失败:', error.message) + return null } } @@ -33,108 +33,108 @@ class AdvancedClientSignGenerator { * 生成随机MAC地址 */ static generateRandomMac() { - const chars = "0123456789ABCDEF"; - let mac = ""; + const chars = '0123456789ABCDEF' + let mac = '' for (let i = 0; i < 6; i++) { - if (i > 0) mac += ":"; + if (i > 0) mac += ':' mac += chars[Math.floor(Math.random() * 16)] + - chars[Math.floor(Math.random() * 16)]; + chars[Math.floor(Math.random() * 16)] } // 确保第一个字节是单播地址(最低位为0) - const firstByte = parseInt(mac.substring(0, 2), 16); + const firstByte = parseInt(mac.substring(0, 2), 16) const unicastFirstByte = (firstByte & 0xfe) .toString(16) - .padStart(2, "0") - .toUpperCase(); - return unicastFirstByte + mac.substring(2); + .padStart(2, '0') + .toUpperCase() + return unicastFirstByte + mac.substring(2) } /** * 获取MAC地址(优先真实,否则随机) */ static getMacAddress() { - const realMac = this.getRealMacAddress(); + const realMac = this.getRealMacAddress() if (realMac) { - return realMac; + return realMac } - console.warn("无法获取真实MAC地址,使用随机生成"); - return this.generateRandomMac(); + console.warn('无法获取真实MAC地址,使用随机生成') + return this.generateRandomMac() } /** * 字符串转HEX编码 */ static stringToHex(str) { - return Buffer.from(str, "utf8").toString("hex").toUpperCase(); + return Buffer.from(str, 'utf8').toString('hex').toUpperCase() } /** * SHA-256哈希 */ static sha256(data) { - return crypto.createHash("sha256").update(data, "utf8").digest("hex"); + return crypto.createHash('sha256').update(data, 'utf8').digest('hex') } /** * 生成随机设备ID */ static generateRandomDeviceId() { - const partLengths = [4, 4, 4, 4, 4, 4, 4, 5]; // 各部分长度 - const chars = "0123456789ABCDEF"; + const partLengths = [4, 4, 4, 4, 4, 4, 4, 5] // 各部分长度 + const chars = '0123456789ABCDEF' const parts = partLengths.map((length) => { - let part = ""; + let part = '' for (let i = 0; i < length; i++) { - part += chars[Math.floor(Math.random() * 16)]; + part += chars[Math.floor(Math.random() * 16)] } - return part; - }); + return part + }) - return parts.join("_"); + return parts.join('_') } /** * 生成随机clientSign(优先使用真实MAC,否则随机) */ - static generateRandomClientSign(secretKey = "") { + static generateRandomClientSign(secretKey = '') { // 获取MAC地址(优先真实,否则随机) - const macAddress = this.getMacAddress(); + const macAddress = this.getMacAddress() // 生成随机设备ID - const deviceId = this.generateRandomDeviceId(); + const deviceId = this.generateRandomDeviceId() // 转换设备ID为HEX - const hexDeviceId = this.stringToHex(deviceId); + const hexDeviceId = this.stringToHex(deviceId) // 构造签名字符串 - const signString = `${macAddress}@@@${hexDeviceId}`; + const signString = `${macAddress}@@@${hexDeviceId}` // 生成哈希 - const hash = this.sha256(signString + secretKey); + const hash = this.sha256(signString + secretKey) - return `${signString}@@@@@@${hash}`; + return `${signString}@@@@@@${hash}` } /** * 批量生成多个随机签名 */ - static generateMultipleRandomSigns(count, secretKey = "") { - const signs = []; + static generateMultipleRandomSigns(count, secretKey = '') { + const signs = [] for (let i = 0; i < count; i++) { - signs.push(this.generateRandomClientSign(secretKey)); + signs.push(this.generateRandomClientSign(secretKey)) } - return signs; + return signs } /** * 使用指定参数生成签名 */ - static generateWithCustomDeviceId(macAddress, deviceId, secretKey = "") { - const hexDeviceId = this.stringToHex(deviceId); - const signString = `${macAddress}@@@${hexDeviceId}`; - const hash = this.sha256(signString + secretKey); - return `${signString}@@@@@@${hash}`; + static generateWithCustomDeviceId(macAddress, deviceId, secretKey = '') { + const hexDeviceId = this.stringToHex(deviceId) + const signString = `${macAddress}@@@${hexDeviceId}` + const hash = this.sha256(signString + secretKey) + return `${signString}@@@@@@${hash}` } /** @@ -142,28 +142,28 @@ class AdvancedClientSignGenerator { */ static validateClientSign(clientSign) { try { - const parts = clientSign.split("@@@@@@"); - if (parts.length !== 2) return false; + const parts = clientSign.split('@@@@@@') + if (parts.length !== 2) return false - const [infoPart, hash] = parts; - const infoParts = infoPart.split("@@@"); - if (infoParts.length !== 2) return false; + const [infoPart, hash] = parts + const infoParts = infoPart.split('@@@') + if (infoParts.length !== 2) return false - const [mac, hexDeviceId] = infoParts; + const [mac, hexDeviceId] = infoParts // 验证MAC地址格式 - const macRegex = /^([0-9A-F]{2}:){5}[0-9A-F]{2}$/; - if (!macRegex.test(mac)) return false; + const macRegex = /^([0-9A-F]{2}:){5}[0-9A-F]{2}$/ + if (!macRegex.test(mac)) return false // 验证哈希格式 - const hashRegex = /^[0-9a-f]{64}$/; - if (!hashRegex.test(hash)) return false; + const hashRegex = /^[0-9a-f]{64}$/ + if (!hashRegex.test(hash)) return false - return true; + return true } catch (error) { - return false; + return false } } } -module.exports = AdvancedClientSignGenerator; \ No newline at end of file +module.exports = AdvancedClientSignGenerator diff --git a/util/logger.js b/util/logger.js index bd4041b..8fe8295 100644 --- a/util/logger.js +++ b/util/logger.js @@ -1,28 +1,42 @@ // ANSI 颜色代码 const colors = { - reset: '\x1b[0m', - bright: '\x1b[1m', - dim: '\x1b[2m', - black: '\x1b[30m', - red: '\x1b[31m', - green: '\x1b[32m', - yellow: '\x1b[33m', - blue: '\x1b[34m', - magenta: '\x1b[35m', - cyan: '\x1b[36m', - white: '\x1b[37m', - bgRed: '\x1b[41m', - bgGreen: '\x1b[42m', - bgYellow: '\x1b[43m' -}; + reset: '\x1b[0m', + bright: '\x1b[1m', + dim: '\x1b[2m', + black: '\x1b[30m', + red: '\x1b[31m', + green: '\x1b[32m', + yellow: '\x1b[33m', + blue: '\x1b[34m', + magenta: '\x1b[35m', + cyan: '\x1b[36m', + white: '\x1b[37m', + bgRed: '\x1b[41m', + bgGreen: '\x1b[42m', + bgYellow: '\x1b[43m', +} const logger = { - debug: (msg, ...args) => console.info(`${colors.cyan}[DEBUG]${colors.reset}`, msg, ...args), - info: (msg, ...args) => console.info(`${colors.green}[INFO]${colors.reset}`, msg, ...args), - warn: (msg, ...args) => console.info(`${colors.yellow}[WARN]${colors.reset}`, msg, ...args), - error: (msg, ...args) => console.error(`${colors.red}[ERROR]${colors.reset}`, msg, ...args), - success: (msg, ...args) => console.log(`${colors.bright}${colors.green}[SUCCESS]${colors.reset}`, msg, ...args), - critical: (msg, ...args) => console.error(`${colors.bright}${colors.bgRed}[CRITICAL]${colors.reset}`, msg, ...args) -}; + debug: (msg, ...args) => + console.info(`${colors.cyan}[DEBUG]${colors.reset}`, msg, ...args), + info: (msg, ...args) => + console.info(`${colors.green}[INFO]${colors.reset}`, msg, ...args), + warn: (msg, ...args) => + console.info(`${colors.yellow}[WARN]${colors.reset}`, msg, ...args), + error: (msg, ...args) => + console.error(`${colors.red}[ERROR]${colors.reset}`, msg, ...args), + success: (msg, ...args) => + console.log( + `${colors.bright}${colors.green}[SUCCESS]${colors.reset}`, + msg, + ...args, + ), + critical: (msg, ...args) => + console.error( + `${colors.bright}${colors.bgRed}[CRITICAL]${colors.reset}`, + msg, + ...args, + ), +} -module.exports = logger; \ No newline at end of file +module.exports = logger diff --git a/util/request.js b/util/request.js index 4cbb497..27b2024 100644 --- a/util/request.js +++ b/util/request.js @@ -101,7 +101,7 @@ const SPECIAL_STATUS_CODES = new Set([201, 302, 400, 502, 800, 801, 802, 803]) // chooseUserAgent函数 const chooseUserAgent = (crypto, uaType = 'pc') => { - return userAgentMap[crypto]?.[uaType] || '' + return (userAgentMap[crypto] && userAgentMap[crypto][uaType]) || '' } // cookie处理 @@ -153,15 +153,17 @@ const createHeaderCookie = (header) => { const generateRequestId = () => { return `${now()}_${floor(random() * 1000) .toString() - .padStart(4, "0")}`; - + .padStart(4, '0')}` } const createRequest = (uri, data, options) => { return new Promise((resolve, reject) => { // 变量声明和初始化 const headers = options.headers ? { ...options.headers } : {} - const ip = options.realIP || options.ip || (options.randomCNIP ? generateRandomChineseIP() : '') + const ip = + options.realIP || + options.ip || + (options.randomCNIP ? generateRandomChineseIP() : '') // IP头设置 if (ip) { headers['X-Real-IP'] = ip @@ -243,8 +245,8 @@ const createRequest = (uri, data, options) => { options.e_r !== undefined ? options.e_r : data.e_r !== undefined - ? data.e_r - : ENCRYPT_RESPONSE, + ? data.e_r + : ENCRYPT_RESPONSE, ) encryptData = encrypt.eapi(uri, data) url = API_DOMAIN + '/eapi/' + uri.substr(5)