From 5c98a9a1eaf30a219d2c779bd4668609bc17405d Mon Sep 17 00:00:00 2001 From: cXp1r <2510037056@qq.com> Date: Mon, 24 Aug 2026 16:26:12 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3NMTID=E6=9D=A5?= =?UTF-8?q?=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/request.js | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/util/request.js b/util/request.js index 1d2f505..204392f 100644 --- a/util/request.js +++ b/util/request.js @@ -68,6 +68,8 @@ const WNMCID = (function () { return `${randomString}.${now().toString()}.01.0` })() +let NMTID = '' + // 预先定义osMap const osMap = { pc: { @@ -155,8 +157,8 @@ const processCookieObject = (cookie, uri) => { appver: cookie.appver || os.appver, } - if (uri.indexOf('login') === -1) { - processedCookie['NMTID'] = CryptoJS.lib.WordArray.random(16).toString() + if (NMTID) { + processedCookie['NMTID'] = NMTID } if (!processedCookie.MUSIC_U) { @@ -420,9 +422,22 @@ const createRequest = async (uri, data, options) => { axios(settings) .then((res) => { const body = res.data - answer.cookie = (res.headers['set-cookie'] || []).map((x) => - x.replace(/\s*Domain=[^(;|$)]+;*/, ''), - ) + const setCookies = res.headers['set-cookie'] || [] + + const cleanCookie = (x) => x.replace(/\s*Domain=[^(;|$)]+;*/, '') + + if (crypto == 'eapi' && !NMTID) { + answer.cookie = setCookies.map((x) => { + const cleaned = cleanCookie(x) + const match = x.match(/NMTID=([^;]+)/) + if (match) { + NMTID = match[1] + } + return cleaned + }) + } else { + answer.cookie = setCookies.map(cleanCookie) + } // debug: 统一注释块,需要时取消注释查看请求/返回的原始密文 From 8376699f5e187e5d5324b7e73bc387ec941b075c Mon Sep 17 00:00:00 2001 From: cXp1r <2510037056@qq.com> Date: Mon, 24 Aug 2026 17:46:19 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9NMTID=E9=87=87?= =?UTF-8?q?=E5=8F=96=E9=80=BB=E8=BE=91=E5=92=8C=E5=8C=B9=E9=85=8D=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/request.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/util/request.js b/util/request.js index 204392f..7e4fcef 100644 --- a/util/request.js +++ b/util/request.js @@ -157,9 +157,10 @@ const processCookieObject = (cookie, uri) => { appver: cookie.appver || os.appver, } - if (NMTID) { - processedCookie['NMTID'] = NMTID - } + processedCookie['NMTID'] = + cookie.NMTID || + NMTID || + '00O' + CryptoJS.lib.WordArray.random(38).toString() if (!processedCookie.MUSIC_U) { processedCookie.MUSIC_A = processedCookie.MUSIC_A || anonymous_token @@ -426,10 +427,10 @@ const createRequest = async (uri, data, options) => { const cleanCookie = (x) => x.replace(/\s*Domain=[^(;|$)]+;*/, '') - if (crypto == 'eapi' && !NMTID) { + if (crypto === 'eapi' && !NMTID) { answer.cookie = setCookies.map((x) => { const cleaned = cleanCookie(x) - const match = x.match(/NMTID=([^;]+)/) + const match = x.match(/(?:^|;\s*)NMTID=([^;]+)/) if (match) { NMTID = match[1] } From 22003c2c322387aba696232abf74a0163aebf723 Mon Sep 17 00:00:00 2001 From: cXp1r <2510037056@qq.com> Date: Tue, 25 Aug 2026 00:51:47 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DNMTID=E4=BF=9D?= =?UTF-8?q?=E5=BA=95=E6=9C=89=E9=9A=8F=E6=9C=BA=E7=94=9F=E6=88=90=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E6=9C=8D=E5=8A=A1=E5=99=A8=E6=B0=B8=E8=BF=9C=E4=B8=8D?= =?UTF-8?q?=E4=BC=9A=E4=B8=8B=E6=94=BE,=20=E8=87=B4=E4=BD=BF=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E8=BF=9B=E5=85=A5=E5=88=86=E6=94=AF=E6=B5=AA=E8=B4=B9?= =?UTF-8?q?=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/request.js | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/util/request.js b/util/request.js index 7e4fcef..55b6d2b 100644 --- a/util/request.js +++ b/util/request.js @@ -69,6 +69,7 @@ const WNMCID = (function () { })() let NMTID = '' +let NMTID_RETRIES_LEFT = 3 // 预先定义osMap const osMap = { @@ -138,7 +139,7 @@ const chooseUserAgent = (crypto, uaType = 'pc') => { } // cookie处理 -const processCookieObject = (cookie, uri) => { +const processCookieObject = (cookie, crypto) => { const _ntes_nuid = CryptoJS.lib.WordArray.random(32).toString() const os = osMap[cookie.os] || osMap['pc'] @@ -157,10 +158,15 @@ const processCookieObject = (cookie, uri) => { appver: cookie.appver || os.appver, } - processedCookie['NMTID'] = - cookie.NMTID || - NMTID || - '00O' + CryptoJS.lib.WordArray.random(38).toString() + // 服务端下发条件为不带NMTID请求任意eapi加密方式接口 + if (cookie.NMTID) { + processedCookie['NMTID'] = cookie.NMTID + } else if (NMTID) { + processedCookie['NMTID'] = NMTID + } else if (NMTID_RETRIES_LEFT <= 0 || crypto !== 'eapi') { + processedCookie['NMTID'] = + '00O' + CryptoJS.lib.WordArray.random(19).toString() + } if (!processedCookie.MUSIC_U) { processedCookie.MUSIC_A = processedCookie.MUSIC_A || anonymous_token @@ -208,6 +214,12 @@ const createRequest = async (uri, data, options) => { const headers = options.headers ? { ...options.headers } : {} const ip = options.realIP || options.ip || '' + // 加密方式选择 + let crypto = options.crypto + if (crypto === '') { + crypto = APP_CONF.encrypt ? 'eapi' : 'api' + } + // IP头设置 if (ip) { headers['X-Real-IP'] = ip @@ -220,19 +232,13 @@ const createRequest = async (uri, data, options) => { } if (typeof cookie === 'object') { - cookie = processCookieObject(cookie, uri) + cookie = processCookieObject(cookie, crypto) headers['Cookie'] = cookieObjToString(cookie) } let url = '' let encryptData = '' - let crypto = options.crypto const csrfToken = cookie['__csrf'] || '' - // 加密方式选择 - if (crypto === '') { - crypto = APP_CONF.encrypt ? 'eapi' : 'api' - } - const answer = { status: 500, body: {}, cookie: [] } data.e_r = toBoolean( @@ -335,9 +341,8 @@ const createRequest = async (uri, data, options) => { if (cookie.MUSIC_U) header['MUSIC_U'] = cookie.MUSIC_U if (cookie.MUSIC_A) header['MUSIC_A'] = cookie.MUSIC_A - if (options.checkToken) { - header['X-antiCheatToken'] = token - } + if (options.checkToken) header['X-antiCheatToken'] = token + if (crypto === 'eapi' && cookie.NMTID) header['NMTID'] = cookie.NMTID headers['Cookie'] = createHeaderCookie(header) headers['User-Agent'] = @@ -427,11 +432,19 @@ const createRequest = async (uri, data, options) => { const cleanCookie = (x) => x.replace(/\s*Domain=[^(;|$)]+;*/, '') - if (crypto === 'eapi' && !NMTID) { + // 仅对真正未携带 NMTID 的探测请求采集并消耗重试次数 + if ( + crypto === 'eapi' && + !NMTID && + NMTID_RETRIES_LEFT > 0 && + !cookie.NMTID + ) { + NMTID_RETRIES_LEFT-- answer.cookie = setCookies.map((x) => { const cleaned = cleanCookie(x) const match = x.match(/(?:^|;\s*)NMTID=([^;]+)/) if (match) { + //不需要处理竞争, 官方客户端真实操作 NMTID = match[1] } return cleaned