diff --git a/README.md b/README.md index a482684..6926880 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ conf/kyapp_qinglong.conf # 快音 CK → 青龙 KYAPP 自动更新重写 conf/pingme.conf # PingMe → NiuPanel pingme_multi.js 抓包重写订阅 js/qdreader_cookie.js # 起点读书 QX Rewrite 脚本入口 js/kyapp_qinglong_update.js # 快音 CK 抓取并更新青龙 KYAPP -js/pingme_capture.js # PingMe 抓取 pingme_multi.js 所需账号 JSON +js/pingme_capture.js # PingMe 抓取 pingme_multi.js 当前 CK 同款 url+headers JSON docs/qx-rewrite-lessons.md # 本次制作经验 source/qdreader.upstream.js # 上游 QDReader 脚本备份 ``` diff --git a/conf/pingme.conf b/conf/pingme.conf index 0514c6c..7e917cf 100644 --- a/conf/pingme.conf +++ b/conf/pingme.conf @@ -1,5 +1,6 @@ hostname = api.pingmeapp.net # PingMe:抓取 NiuPanel pingme_multi.js 所需账号配置 +# 现有正确 CK 格式只包含 {"url":"...","headers":{...}},不额外输出 paramsRaw # 使用说明见 docs/pingme-capture.md -^https?:\/\/api\.pingmeapp\.net\/app\/(?:queryBalanceAndBonus|checkIn|videoBonus)(?:\?|$) url script-request-header https://gitea.chickliu.fun/Hermes/qx/raw/branch/main/js/pingme_capture.js +^https?:\/\/api\.pingmeapp\.net\/app\/queryBalanceAndBonus(?:\?|$) url script-request-header https://gitea.chickliu.fun/Hermes/qx/raw/branch/main/js/pingme_capture.js diff --git a/docs/pingme-capture.md b/docs/pingme-capture.md index cbb9b08..b8749ad 100644 --- a/docs/pingme-capture.md +++ b/docs/pingme-capture.md @@ -8,20 +8,22 @@ https://gitea.chickliu.fun/Hermes/qx/raw/branch/main/conf/pingme.conf ## 功能 -这个 QX 重写监听 PingMe 官方接口: +这个 QX 重写监听 PingMe 官方余额接口: ```text api.pingmeapp.net/app/queryBalanceAndBonus -api.pingmeapp.net/app/checkIn -api.pingmeapp.net/app/videoBonus ``` -抓到后生成 NiuPanel 任务 `pingme_multi.js` 所需的账号 JSON 对象: +只抓这个接口是为了对齐现有可用 `pingme_ck.json` 的来源格式。 + +抓到后生成 NiuPanel 任务 `pingme_multi.js` 当前正确 CK 同款账号 JSON 对象: ```json -{"url":"...","paramsRaw":{"...":"..."},"headers":{"User-Agent":"..."}} +{"url":"https://api.pingmeapp.net/app/queryBalanceAndBonus?...","headers":{"Host":"api.pingmeapp.net","Connection":"keep-alive","Accept":"*/*","User-Agent":"...","Accept-Language":"...","Accept-Encoding":"..."}} ``` +注意:当前正确 CK **不包含** `paramsRaw`。`pingme_multi.js` 会从 `url` 里的查询字符串自行解析参数并重算 `sign`。 + NiuPanel 当前任务读取位置: ```text @@ -49,7 +51,7 @@ NiuPanel 当前任务读取位置: api.pingmeapp.net ``` -4. 打开 PingMe App,触发余额、签到或视频奖励接口。 +4. 打开 PingMe App,触发余额接口 `queryBalanceAndBonus`。 5. QX 弹窗标题显示 `CK 获取成功`,正文是完整 JSON 对象。 6. 将 JSON 对象追加到 NiuPanel 的 `pingme_ck.json`。 @@ -69,4 +71,4 @@ NiuPanel 当前任务读取位置: - 仓库不提交任何真实 CK、token、设备 ID 或 headers 明文。 - 脚本不上传数据,不请求第三方,只在 QX 本地保存最近一次抓取结果 `pingme_ck_last` 并弹窗展示。 -- 重写范围只包含 `api.pingmeapp.net` 的三个任务相关接口。 +- 重写范围只包含 `api.pingmeapp.net` 的 `queryBalanceAndBonus` 接口。 diff --git a/js/pingme_capture.js b/js/pingme_capture.js index 86980d5..63e032f 100644 --- a/js/pingme_capture.js +++ b/js/pingme_capture.js @@ -4,11 +4,10 @@ * 订阅地址: * https://gitea.chickliu.fun/Hermes/qx/raw/branch/main/conf/pingme.conf * - * 功能: - * - 监听 api.pingmeapp.net/app/queryBalanceAndBonus、checkIn、videoBonus - * - 抓取 pingme_multi.js 需要的 url / paramsRaw / headers - * - 弹窗输出可直接追加到 NiuPanel /app/data/scripts/pingme_ck.json 的 JSON 对象 + * 输出格式严格对齐当前 NiuPanel 正确 CK: + * {"url":"https://api.pingmeapp.net/app/queryBalanceAndBonus?...","headers":{...}} * + * 注意:pingme_multi.js 会从 url 自行解析查询参数并重算 sign,正确 CK 不需要 paramsRaw。 * 安全:不上传 CK,不请求第三方;仅在 QX 本地保存最近一次抓取结果。 */ @@ -34,72 +33,30 @@ function getHeader(headers, name) { return '' } -function parseRawQuery(url) { - const raw = String(url || '') - const qIndex = raw.indexOf('?') - if (qIndex < 0) return {} - const hashIndex = raw.indexOf('#', qIndex + 1) - const query = raw.slice(qIndex + 1, hashIndex >= 0 ? hashIndex : undefined) - const out = {} - query.split('&').forEach(pair => { - if (!pair) return - const idx = pair.indexOf('=') - if (idx < 0) return - const k = pair.slice(0, idx) - const v = pair.slice(idx + 1) - if (k) out[k] = v - }) - return out +function hasQuery(url) { + return String(url || '').indexOf('?') >= 0 && String(url || '').split('?')[1].length > 0 } -function pickHeaders(headers) { - const names = [ - 'User-Agent', - 'Accept', - 'Accept-Language', - 'Authorization', - 'Cookie', - 'X-Requested-With', - 'Content-Type', - 'Origin', - 'Referer' - ] +function buildHeaders(headers) { + // 严格按现有正确 pingme_ck.json 的 header 形状输出。 + // 保留 Host/Connection/Accept-Encoding,因为当前正确 CK 就是这个集合; + // pingme_multi.js 后续会覆盖 Host 与 Accept-Encoding,不会影响执行。 + const ordered = ['Host', 'Connection', 'Accept', 'User-Agent', 'Accept-Language', 'Accept-Encoding'] const out = {} - names.forEach(name => { + ordered.forEach(name => { const v = getHeader(headers, name) if (v !== undefined && v !== null && String(v) !== '') out[name] = String(v) }) - - // 保留 PingMe/客户端自定义头,避免后续接口校验客户端参数。 - Object.keys(headers || {}).forEach(k => { - const lk = String(k).toLowerCase() - if ( - lk.startsWith('x-') || - lk.indexOf('device') >= 0 || - lk.indexOf('token') >= 0 || - lk.indexOf('client') >= 0 || - lk.indexOf('app') >= 0 - ) { - if (!/^content-length$/i.test(k) && !/^host$/i.test(k)) out[k] = String(headers[k]) - } - }) + if (!out.Host) out.Host = 'api.pingmeapp.net' + if (!out.Accept) out.Accept = '*/*' return out } function buildRecord(req) { - const url = String(req.url || '') - const paramsRaw = parseRawQuery(url) - const headers = pickHeaders(req.headers || {}) - return { url, paramsRaw, headers } -} - -function hasRequiredParams(record) { - const p = record && record.paramsRaw || {} - return Object.keys(p).length > 0 -} - -function formatRecord(record) { - return JSON.stringify(record) + return { + url: String(req.url || ''), + headers: buildHeaders(req.headers || {}) + } } function main() { @@ -109,13 +66,18 @@ function main() { return done() } - const record = buildRecord(req) - if (!hasRequiredParams(record)) { - notify('抓取失败', '当前请求缺少 URL 查询参数,请打开 PingMe 触发余额/签到/视频接口') + const url = String(req.url || '') + if (!/^https?:\/\/api\.pingmeapp\.net\/app\/queryBalanceAndBonus(?:\?|$)/.test(url)) { + notify('等待正确接口', '请打开 PingMe 触发 queryBalanceAndBonus 接口') + return done() + } + if (!hasQuery(url)) { + notify('抓取失败', 'queryBalanceAndBonus 请求缺少查询参数') return done() } - const text = formatRecord(record) + const record = buildRecord(req) + const text = JSON.stringify(record) setPref('pingme_ck_last', text) notify('CK 获取成功', text) done()