diff --git a/src/coupons/const.js b/src/coupons/const.js index 2705100d..2125f491 100644 --- a/src/coupons/const.js +++ b/src/coupons/const.js @@ -6,15 +6,17 @@ const ECODE = { RUNTIME: 4 } -const mainActConf = [ - { gid: '2KAWnD', name: '外卖红包天天领' }, - { gid: '4luWGh', name: '品质优惠天天领' } +const mainActConf = { gid: '2KAWnD', name: '外卖红包天天领' } + +const gundamActConfs = [ + { gid: '4luWGh', name: '品质优惠天天领' }, + { gid: '4JZIgf', name: '冬日美食季' } ] -const wxfwhActConf = [ +const wxfwhActConfs = [ { gid: '1C0wLz', name: '天天神券服务号专属福利' }, { gid: '1HgnjG', name: '365元祝福请收下' }, { gid: '1I9uL6', name: '美团外卖社群专属福利' } ] -export { ECODE, mainActConf, wxfwhActConf } +export { ECODE, gundamActConfs, mainActConf, wxfwhActConfs } diff --git a/src/coupons/gundamGrab.js b/src/coupons/gundam.js similarity index 70% rename from src/coupons/gundamGrab.js rename to src/coupons/gundam.js index 4ae011ee..38ac6198 100644 --- a/src/coupons/gundamGrab.js +++ b/src/coupons/gundam.js @@ -3,32 +3,47 @@ import { dateFormat } from '../util/index.js' import { getTemplateData, getRenderList, matchMoudleData } from '../template.js' import { ECODE } from './const.js' -async function getPayload(gundamId, appJs, guard) { - const renderList = await getRenderList(gundamId, guard) - const jsText = await fetch(appJs).then((res) => res.text()) - let data = null - +function resolveRedMod(text, renderList) { try { for (const instanceId of renderList) { - data = matchMoudleData( - jsText, - `gdc-fx-v2-netunion-red-envelope-${instanceId}`, - 'isStopTJCoupon' - ) + const data = + matchMoudleData( + text, + `gdc-fx-v2-netunion-red-envelope-${instanceId}`, + 'isStopTJCoupon' + ) ?? + matchMoudleData( + text, + `gdc-fx-new-netunion-red-envelope-${instanceId}`, + 'isStopTJCoupon' + ) if (data) { data.instanceID = instanceId data.isStopTJCoupon = true - break + return data } } } catch { // ignore } + return null +} + +async function getPayload( + cookie, + { gundamId, gdId, appJs, renderList }, + guard +) { + const jsText = await fetch(appJs).then((res) => res.text()) + const data = + resolveRedMod(jsText, renderList) ?? + resolveRedMod(jsText, await getRenderList(cookie, gdId, guard)) + if (!data) { - throw new Error('天天神券 Payload 生成失败') + throw new Error(`[${gundamId}] Gundam Payload 生成失败`) } return { @@ -38,7 +53,8 @@ async function getPayload(gundamId, appJs, guard) { platform: 3, couponAllConfigIdOrderString: data.expandCouponIds.keys.join(','), couponConfigIdOrderCommaString: data.priorityCouponIds.keys.join(','), - gundamId: gundamId, + // 这里取 number 类型的 gdId + gundamId: gdId, instanceId: data.instanceID, h5Fingerprint: '', rubikCouponKey: data.cubeToken || '', @@ -77,8 +93,8 @@ function formatCoupons(coupons, actName) { async function grabCoupon(cookie, gundamId, guard) { const actUrl = getActUrl(gundamId) - const { actName, appJs, gdId } = await getTemplateData(cookie, gundamId) - const payload = await getPayload(gdId, appJs, guard) + const tmplData = await getTemplateData(cookie, gundamId) + const payload = await getPayload(cookie, tmplData, guard) const res = await fetch.post( 'https://mediacps.meituan.com/gundam/gundamGrabV4', payload, @@ -93,12 +109,12 @@ async function grabCoupon(cookie, gundamId, guard) { ) if (res.code == 0) { - return formatCoupons(res.data.coupons, actName) + return formatCoupons(res.data.coupons, tmplData.actName) } const apiInfo = { api: 'gundamGrabV4', - name: actName, + name: tmplData.actName, msg: res.msg || res.message } diff --git a/src/coupons/index.js b/src/coupons/index.js index fc365182..4fb13d36 100644 --- a/src/coupons/index.js +++ b/src/coupons/index.js @@ -1,39 +1,36 @@ import fetch from '../fetch.js' import ShadowGuard from '../shadow/index.js' import { createMTCookie, getUserInfo } from '../user.js' -import { mainActConf, wxfwhActConf, ECODE } from './const.js' -import mainAct from './gundamGrab.js' -import wxfwhAct from './wxfwh.js' +import { mainActConf, gundamActConfs, wxfwhActConfs, ECODE } from './const.js' +import gundam from './gundam.js' +import wxfwh from './wxfwh.js' async function runTask(cookie, guard) { try { // 优先检测登录状态 const userInfo = await getUserInfo(cookie) - const allResults = [] - for (const conf of mainActConf) { - // 主活动,失败时向外抛出异常 - const result = await mainAct.grabCoupon(cookie, conf.gid, guard) + // 主活动,失败时向外抛出异常 + const results = await gundam.grabCoupon(cookie, mainActConf.gid, guard) - allResults.push(...result) - } - - for (const conf of wxfwhActConf) { - try { - // 微信服务号活动,失败时忽略 - const wxResult = await wxfwhAct.grabCoupon(cookie, conf.gid, guard) + // 次要活动,并行执行提升效率 + const asyncResults = await Promise.all([ + ...gundamActConfs.map((conf) => + gundam.grabCoupon(cookie, conf.gid, guard).catch(() => []) + ), + // 微信服务号活动 + ...wxfwhActConfs.map((conf) => + wxfwh.grabCoupon(cookie, conf.gid, guard).catch(() => []) + ) + ]) - allResults.push(...wxResult) - } catch (e) { - // ignore - } - } + results.push(...asyncResults.flat()) return { code: ECODE.SUCC, data: { userInfo, - coupons: allResults + coupons: results }, msg: '成功' } @@ -88,9 +85,7 @@ async function getCoupons(token, { maxRetry = 0, httpProxy }) { const cookieJar = createMTCookie(token) // 复用 guard - const guard = await new ShadowGuard().init( - mainAct.getActUrl(mainActConf[0].gid) - ) + const guard = await new ShadowGuard().init(gundam.getActUrl(mainActConf.gid)) async function main(retryTimes = 0) { const result = await runTask(cookieJar, guard) diff --git a/src/coupons/wxfwh.js b/src/coupons/wxfwh.js index a3c2c203..25f279cf 100644 --- a/src/coupons/wxfwh.js +++ b/src/coupons/wxfwh.js @@ -63,7 +63,8 @@ async function getPayloadTabs(cookie, viewId) { async function getPayload( cookie, - { gdId, pageId, renderList, appJs, fingerprint } + { gundamId, gdId, pageId, renderList, appJs }, + guard ) { const jsText = await fetch(appJs).then((res) => res.text()) let data = null @@ -90,7 +91,7 @@ async function getPayload( } if (!data) { - throw new Error('服务号 Payload 生成失败') + throw new Error(`[${gundamId}] wxfwh Payload 生成失败`) } const tabs = await getPayloadTabs(cookie, data.viewId) @@ -105,23 +106,14 @@ async function getPayload( gdId: gdId, pageId: pageId, instanceId: data.instanceId, - mtFingerprint: fingerprint + mtFingerprint: guard.fingerprint } } async function grabCoupon(cookie, gundamId, guard) { const actUrl = getActUrl(gundamId) - const { actName, gdId, pageId, renderList, appJs } = await getTemplateData( - cookie, - gundamId - ) - const payload = await getPayload(cookie, { - gdId, - pageId, - renderList, - appJs, - fingerprint: guard.fingerprint - }) + const tmplData = await getTemplateData(cookie, gundamId) + const payload = await getPayload(cookie, tmplData, guard) if (!payload.tabs.length) { return [] @@ -149,12 +141,12 @@ async function grabCoupon(cookie, gundamId, guard) { ) if (res.code == 0) { - return formatCoupons(res.data.couponList, actName) + return formatCoupons(res.data.couponList, tmplData.actName) } const apiInfo = { api: 'generalcoupon/fetch', - name: actName, + name: tmplData.actName, msg: res.msg || res.message } diff --git a/src/template.js b/src/template.js index 5da94b26..a829d82b 100644 --- a/src/template.js +++ b/src/template.js @@ -19,6 +19,7 @@ async function getTemplateData(cookie, gundamId) { const globalData = JSON.parse(matchGlobal[1]) return { + gundamId, gdId: globalData.gdId, actName: globalData.pageInfo.title, appJs: appJs, @@ -45,7 +46,7 @@ function formatRendeInfo(renderInfo) { } // 通过接口获取真实的渲染列表 -async function getRenderList(gdNumId, guard) { +async function getRenderList(cookie, gdNumId, guard) { let data try { @@ -58,6 +59,7 @@ async function getRenderList(gdNumId, guard) { gdId: gdNumId, tenant: 'gundam' }, + cookie, guard } ) diff --git a/test/coupons.js b/test/coupons.js index 68c2860e..582ea1d6 100644 --- a/test/coupons.js +++ b/test/coupons.js @@ -4,8 +4,10 @@ import { createMTCookie, parseToken } from '../src/user.js' import { getCoupons, ECODE } from '../src/coupons/index.js' import wxfwhGrab from '../src/coupons/wxfwh.js' +const tokens = parseToken(process.env.TOKEN) +const cookie = createMTCookie(tokens[0].token) + test('Test Coupons', async () => { - const tokens = parseToken(process.env.TOKEN) const res = await getCoupons(tokens[0].token, { // proxy: 'http://127.0.0.1:8887' }) @@ -22,8 +24,6 @@ test('Test Token Error', async () => { }) test('Test Result Format', async () => { - const tokens = parseToken(process.env.TOKEN) - const cookie = createMTCookie(tokens[0].token) const res = await wxfwhGrab.getCouponList(cookie, 'I5r2SYd5kTN1l1AkMhwCNA') expect(res).toBeTruthy() diff --git a/test/payload.js b/test/payload.js index 295dd01e..3376c760 100644 --- a/test/payload.js +++ b/test/payload.js @@ -1,17 +1,19 @@ import { getTemplateData } from '../src/template.js' import ShadowGuard from '../src/shadow/index.js' -import mainAct from '../src/coupons/gundamGrab.js' +import mainAct from '../src/coupons/gundam.js' import wxfwhAct from '../src/coupons/wxfwh.js' -import { mainActConf, wxfwhActConf } from '../src/coupons/const.js' +import { mainActConf, wxfwhActConfs } from '../src/coupons/const.js' import { createMTCookie, parseToken } from '../src/user.js' const guard = new ShadowGuard() +const tokens = parseToken(process.env.TOKEN) +const cookie = createMTCookie(tokens[0].token) -beforeAll(() => guard.init(mainAct.getActUrl(mainActConf[0].gid))) +beforeAll(() => guard.init(mainAct.getActUrl(mainActConf.gid))) test('Test Main Payload', async () => { - const { gdId, appJs } = await getTemplateData(null, mainActConf[0].gid) - const payload = await mainAct.getPayload(gdId, appJs, guard) + const tmplData = await getTemplateData(null, mainActConf.gid) + const payload = await mainAct.getPayload(cookie, tmplData, guard) return expect(payload).toMatchObject({ actualLatitude: 0, @@ -20,7 +22,7 @@ test('Test Main Payload', async () => { platform: 3, couponConfigIdOrderCommaString: expect.any(String), couponAllConfigIdOrderString: expect.any(String), - gundamId: gdId, + gundamId: tmplData.gdId, needTj: expect.any(Boolean), instanceId: expect.any(String), h5Fingerprint: '', @@ -29,27 +31,16 @@ test('Test Main Payload', async () => { }) test('Test Wxfwh Payload', async () => { - const tokens = parseToken(process.env.TOKEN) - const cookie = createMTCookie(tokens[0].token) - const { gdId, pageId, renderList, appJs } = await getTemplateData( - null, - wxfwhActConf[1].gid - ) - const payload = await wxfwhAct.getPayload(cookie, { - gdId, - pageId, - renderList, - appJs, - fingerprint: guard.fingerprint - }) + const tmplData = await getTemplateData(null, wxfwhActConfs[1].gid) + const payload = await wxfwhAct.getPayload(cookie, tmplData, guard) return expect(payload).toMatchObject({ ctype: 'wm_wxapp', fpPlatform: 13, wxOpenId: '', appVersion: '', - gdId: gdId, - pageId: pageId, + gdId: tmplData.gdId, + pageId: tmplData.pageId, tabs: expect.any(Array), activityViewId: expect.any(String), instanceId: expect.any(String), @@ -58,9 +49,7 @@ test('Test Wxfwh Payload', async () => { }) test('Test Wxfwh grab', async () => { - const tokens = parseToken(process.env.TOKEN) - const cookie = createMTCookie(tokens[0].token) - const res = await wxfwhAct.grabCoupon(cookie, wxfwhActConf[1].gid, guard) + const res = await wxfwhAct.grabCoupon(cookie, wxfwhActConfs[1].gid, guard) return expect(res).toBeTruthy() }) diff --git a/test/shadow.js b/test/shadow.js index 6ac07837..44f9c02a 100644 --- a/test/shadow.js +++ b/test/shadow.js @@ -1,12 +1,12 @@ import ShadowGuard from '../src/shadow/index.js' -import grab from '../src/coupons/gundamGrab.js' +import mainGrab from '../src/coupons/gundam.js' import { mainActConf } from '../src/coupons/const.js' const guard = new ShadowGuard({ dfpId: '8v0111yz74185w7deu38vz71222u80w981zvylws4779123469xu4399' }) -beforeAll(() => guard.init(grab.getActUrl(mainActConf[0].gid))) +beforeAll(() => guard.init(mainGrab.getActUrl(mainActConf.gid))) test('Test Generate Session', () => expect(guard.meta.sessionId).toHaveLength(32)) diff --git a/test/template.js b/test/template.js index 1d139bce..4c9930bc 100644 --- a/test/template.js +++ b/test/template.js @@ -1,14 +1,17 @@ import { getTemplateData, getRenderList } from '../src/template.js' import ShadowGuard from '../src/shadow/index.js' -import grab from '../src/coupons/gundamGrab.js' -import { wxfwhActConf } from '../src/coupons/const.js' +import mainGrab from '../src/coupons/gundam.js' +import { createMTCookie, parseToken } from '../src/user.js' +import { wxfwhActConfs } from '../src/coupons/const.js' const guard = new ShadowGuard() +const tokens = parseToken(process.env.TOKEN) +const cookie = createMTCookie(tokens[0].token) -beforeAll(() => guard.init(grab.getActUrl(wxfwhActConf[0].gid))) +beforeAll(() => guard.init(mainGrab.getActUrl(wxfwhActConfs[0].gid))) test('Test getTemplateData', async () => { - const res = await getTemplateData(null, wxfwhActConf[0].gid) + const res = await getTemplateData(null, wxfwhActConfs[0].gid) return expect(res).toMatchObject({ pageId: expect.any(Number), @@ -19,7 +22,7 @@ test('Test getTemplateData', async () => { }) test('Test getRenderList', async () => { - const renderList = await getRenderList(422308, guard) + const renderList = await getRenderList(cookie, 422308, guard) return expect(renderList).toEqual(expect.any(Array)) }) diff --git a/test/user.js b/test/user.js index 90d73d48..90188ad8 100644 --- a/test/user.js +++ b/test/user.js @@ -1,12 +1,12 @@ import tough from 'tough-cookie' import ShadowGuard from '../src/shadow/index.js' -import grab from '../src/coupons/gundamGrab.js' +import mainGrab from '../src/coupons/gundam.js' import { createMTCookie, getUserInfo, parseToken } from '../src/user.js' import { mainActConf } from '../src/coupons/const.js' const guard = new ShadowGuard() -beforeAll(() => guard.init(grab.getActUrl(mainActConf[0].gid))) +beforeAll(() => guard.init(mainGrab.getActUrl(mainActConf.gid))) test('Test Token Undefined', () => { expect(() => parseToken()).toThrow('请配置 TOKEN')