diff --git a/electron/main/gpt/getLink.ts b/electron/main/gpt/getLink.ts index 2d14f80..57ef783 100644 --- a/electron/main/gpt/getLink.ts +++ b/electron/main/gpt/getLink.ts @@ -4,11 +4,11 @@ import login from "../login"; export async function getLink(options) { const log = clog(options) log('开始', { ident: 'gpt-link' }) - const [page, browser] = await login.chatgpt(options) + const [page, browser] = await login.chatgpt({ ...options, changeUS: false }) // await page.waitForTimeout(500) - await page.waitForSelector('body > div.absolute.inset-0') + await page.waitForSelector('body > div.absolute.inset-0', { timeout: 0 }) await page.evaluate(() => { const $mark = document.querySelector("body > div.absolute.inset-0") if ($mark) $mark.hidden = true diff --git a/electron/main/index.ts b/electron/main/index.ts index c8228cf..161275a 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -3,7 +3,22 @@ import { release } from 'node:os' import { join } from 'node:path' import './poe/index' import './gpt/index' -import { browsers } from './tools' +import { browsers, test1 } from './tools' + +import puppeteer from 'puppeteer-extra' +import StealthPlugin from 'puppeteer-extra-plugin-stealth' +puppeteer.use(StealthPlugin()) + + +// test1() +// puppeteer.launch({ +// headless: false, +// args: [ +// '--no-sandbox', +// '--disable-setuid-sandbox', +// '--proxy-server=socks5://127.0.0.1:40000' +// ] +// }) // The built directory structure // @@ -64,7 +79,7 @@ async function createWindow() { console.log('process.env.VITE_DEV_SERVER_URL', process.env.VITE_DEV_SERVER_URL); // Open devTool if the app is not packaged - win.webContents.openDevTools() + // win.webContents.openDevTools() } else { win.loadFile(indexHtml) } @@ -127,32 +142,3 @@ ipcMain.handle('stop', async (event, arg) => { browsers.forEach(browser => browser.close()) return true }) - - -fetch("https://poe.com/api/gql_POST", { - "headers": { - "accept": "*/*", - "accept-language": "zh-CN,zh;q=0.9", - "content-type": "application/json", - "poe-formkey": "520a133912dc68714f36a5bcf4848e59", - "poe-tag-id": "0bc8018cd51c5229e87987cf31f8f89c", - "poe-tchannel": "poe-chan49-8888-qcbwsgypbumznmwlcfwi", - "sec-ch-ua": "\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"", - "sec-ch-ua-mobile": "?0", - "sec-ch-ua-platform": "\"macOS\"", - "Cookie": "p-b=l9xRB8cUvzqnE5Wu0JoLCQ%3D%3D", - "sec-fetch-dest": "empty", - "sec-fetch-mode": "cors", - "sec-fetch-site": "same-origin" - }, - "referrer": "https://poe.com/zhenjie", - "referrerPolicy": "strict-origin-when-cross-origin", - "body": "{\"queryName\":\"chatHelpers_sendMessageMutation_Mutation\",\"variables\":{\"chatId\":15454343,\"bot\":\"zhenjie\",\"query\":\"hi\",\"source\":null,\"withChatBreak\":false,\"clientNonce\":\"eBAHfmO3h41BlXK0\",\"sdid\":\"36988d7a-8ed4-4eaa-bbf8-24782e5b5461\"},\"query\":\"mutation chatHelpers_sendMessageMutation_Mutation(\\n $chatId: BigInt!\\n $bot: String!\\n $query: String!\\n $source: MessageSource\\n $withChatBreak: Boolean!\\n $clientNonce: String\\n $sdid: String\\n) {\\n messageEdgeCreate(chatId: $chatId, bot: $bot, query: $query, source: $source, withChatBreak: $withChatBreak, clientNonce: $clientNonce, sdid: $sdid) {\\n chatBreak {\\n cursor\\n node {\\n id\\n messageId\\n text\\n author\\n suggestedReplies\\n creationTime\\n state\\n }\\n id\\n }\\n message {\\n cursor\\n node {\\n id\\n messageId\\n text\\n author\\n suggestedReplies\\n creationTime\\n state\\n clientNonce\\n contentType\\n chat {\\n shouldShowDisclaimer\\n id\\n }\\n }\\n id\\n }\\n bot {\\n id\\n messageLimit {\\n dailySent\\n }\\n }\\n status\\n }\\n}\\n\"}", - "method": "POST", - "mode": "cors", - "credentials": "include" -}).then(res => { - console.log('ok', res) -}).catch(err=> { - console.log('err', err) -}) diff --git a/electron/main/login.ts b/electron/main/login.ts index 1ef651e..e3b373b 100644 --- a/electron/main/login.ts +++ b/electron/main/login.ts @@ -1,16 +1,21 @@ -import { Page } from 'puppeteer' -import { browsers, clog, elCheck } from './tools' +import type { Page, Browser } from 'puppeteer' +import { browsers, clog, statusCheck } from './tools' import { awaitWrap, browserAndPage, randomNum } from './tools' -import { Browser } from 'puppeteer' const login = { // poe 邮箱登录 - async poe_email(options, getCodeFn: Function): Promise<[Page, Browser]> { + async poe_email(options, getCodeFn: Function, tryCount = 1): Promise<[Page, Browser]> { const log = clog(options) + if (tryCount > 2) { + log('重试次数已达上限') + throw '重试次数已达上限' + return + } + log('启动浏览器') - const { browser, page } = await browserAndPage(options) + const { browser, page } = await browserAndPage({ ...options, proxy: true }) log('正在进入登录页面') await page.goto('https://poe.com/login') @@ -30,11 +35,37 @@ const login = { await page.waitForSelector('input[type="email"]') await page.type('input[type="email"]', options.user) await page.waitForTimeout(1000) - // elCheck() - await page.keyboard.press('Enter') + await statusCheck( + async () => await page.keyboard.press('Enter'), + async () => await page.$('.LoadingDots_wrapper__lXyQd'), // LoadingDots_wrapper__lXyQd + ) + + // 检查是否有错误 + const isOk = await Promise.race([ + page.waitForSelector('.InfoText_error__OQwmg').then(() => false), + page.waitForSelector('input[class^="VerificationCodeInput_verificationCodeInput"]').then(() => true) + ]) + + console.log('isOk', isOk) + if (!isOk) { + const reason = await page.$eval('.InfoText_error__OQwmg', (el: HTMLElement) => el.textContent.trim()) + if (reason.startsWith('Something')) { + await page.waitForTimeout(3482) + await statusCheck( + async () => await page.keyboard.press('Enter'), + async () => await page.$('.LoadingDots_wrapper__lXyQd'), // LoadingDots_wrapper__lXyQd + ) + } else { + log('', { result: `登录失败: ${reason}` }) + browser.close() + throw '登录失败' + } + // return login.poe_email(options, getCodeFn, tryCount + 1) + } + + // await page.keyboard.press('Enter') log('开始输入密码') - await page.waitForSelector('input[class^="VerificationCodeInput_verificationCodeInput"]') const code = await getCodeFn(options, { page, browser }) await page.type('input[class^=VerificationCodeInput_verificationCodeInput]', code) @@ -185,52 +216,85 @@ const login = { await page.keyboard.press('Enter') log('开始登录') + /** + * + * @param reload 是否点击刷新验证码按钮 + */ async function validateCode() { log('开始获取code') let $iframe = await page.$('#thirdPartyFrame_home') let frame = await $iframe?.contentFrame() if (!frame) { + log('未找到页面,刷新重试中...') await page.reload() return await validateCode() } + const [err] = await awaitWrap(frame.waitForSelector('ul.inbox-container li', { timeout: 4000 })) + if (err) { + console.log(err) + console.log('有报错') + await frame.waitForSelector('.ico.sync') + const sync = await page.$('.ico.sync') + if (!sync) { + console.log('未找到刷新按钮') + log('未找到刷新按钮') + return '' + } + await frame.click('.ico.sync') + await frame.waitForTimeout(4000) + return await validate() + } + + return await validate() + + + // console.log('type', type) + // if (type === 'list') { + // return await validate() + // } + + await frame.waitForSelector('.ico.sync') await frame.click('.ico.sync') await frame.waitForTimeout(1000) await frame.waitForSelector('ul.inbox-container li') log('查找邮箱') - const $li = await frame.evaluate((emailText) => { - const $li: any = Array.from(document.querySelectorAll('ul.inbox-container li')).find($li => { - let sender = $li.querySelector('.sender')?.textContent || '' - return sender.includes(emailText) - }) - if ($li) $li.click() - return $li - }, emailText) + async function validate() { + const $li = await frame.evaluate((emailText) => { + const $li: any = Array.from(document.querySelectorAll('ul.inbox-container li')).find($li => { + let sender = $li.querySelector('.sender')?.textContent || '' + return sender.includes(emailText) + }) - if (!$li) { - log('未找到邮箱') - return '' - } else { - log('等待出现验证码 iframe') - await page.waitForSelector('#thirdPartyFrame_mail') - log('出现了验证码 iframe,寻找他的 iframe') - $iframe = await page.$('#thirdPartyFrame_mail') - frame = await $iframe?.contentFrame() + if ($li) $li.click() + return $li + }, emailText) - await frame.waitForSelector('iframe#mail-detail') - log('出现验证码 iframe') + if (!$li) { + log('未找到邮箱') + return '' + } else { + log('等待出现验证码 iframe') + await page.waitForSelector('#thirdPartyFrame_mail') + log('出现了验证码 iframe,寻找他的 iframe') + $iframe = await page.$('#thirdPartyFrame_mail') + frame = await $iframe?.contentFrame() - $iframe = await frame.$('iframe#mail-detail') - frame = await $iframe?.contentFrame() + await frame.waitForSelector('iframe#mail-detail') + log('出现验证码 iframe') - log('等待验证码') - await frame.waitForSelector('table table table ') - const code = (await frame.$eval('table table table tr:nth-of-type(5)', el => el.textContent)) || '' - return code.trim() + $iframe = await frame.$('iframe#mail-detail') + frame = await $iframe?.contentFrame() + + log('等待验证码') + await frame.waitForSelector('table table table ') + const code = (await frame.$eval('table table table tr:nth-of-type(5)', el => el.textContent)) || '' + return code.trim() + } } } @@ -286,7 +350,7 @@ const login = { log('已输入密码,开始登录') await Promise.all([ - page.waitForNavigation({ timeout: 10000 }), + page.waitForNavigation({ timeout: 10000, waitUntil: 'domcontentloaded' }), page.keyboard.press('Enter') ]) log('登录成功') diff --git a/electron/main/poe/index.js b/electron/main/poe/index.js index 34d383b..957f307 100644 --- a/electron/main/poe/index.js +++ b/electron/main/poe/index.js @@ -2,11 +2,7 @@ import { getLink } from './getLink' import { validate } from './validate' import { ipcMain } from 'electron' import { link_7day } from './link_7day' - -// import './openBrowser' -// suzzettedeanne2393@gmail.com----zebulonlawayne3013----zebulonlawayne4749@outlook.com -const text = ` -` +import { browserAndPage } from '../tools' export const parseAccount = text => text.split('\n').filter(Boolean).map(v => { v = v.split(/(——|-)+/).filter(v => !['-', '——'].includes(v)) @@ -18,7 +14,7 @@ ipcMain.handle('getLink', async (event, arg) => { const accounts = parseAccount(text) const links = [] - for(let i = 0; i < accounts.length; i++) { + for (let i = 0; i < accounts.length; i++) { const [user, pass, auxiliary] = accounts[i] const link = await getLink({ user, pass, auxiliary, index: i, id: user }) // .catch(err => { @@ -35,13 +31,13 @@ ipcMain.handle('getLink', async (event, arg) => { }) ipcMain.handle('get-poe-link-7day', async (event, arg) => { - const { text } = arg + const { text, liao } = arg const accounts = parseAccount(text) const links = [] - for(let i = 0; i < accounts.length; i++) { + for (let i = 0; i < accounts.length; i++) { const [user, pass, auxiliary] = accounts[i] - const link = await link_7day({ user, pass, auxiliary, index: i, id: user }) + const link = await link_7day({ user, pass, auxiliary, index: i, id: user, liao }) // .catch(err => { // console.log('error ->', err) // }) @@ -61,7 +57,7 @@ ipcMain.handle('poe-result', async (event, arg) => { const accounts = parseAccount(text) const links = [] - for(let i = 0; i < accounts.length; i++) { + for (let i = 0; i < accounts.length; i++) { const [user, pass, auxiliary] = accounts[i] const link = await validate({ user, pass, auxiliary, index: i, id: user }) // .catch(err => { @@ -76,3 +72,7 @@ ipcMain.handle('poe-result', async (event, arg) => { } return links }) + +ipcMain.handle('start-one-chrom', async (event, arg) => { + browserAndPage({ proxy: true }) +}) diff --git a/electron/main/poe/link_7day.ts b/electron/main/poe/link_7day.ts index 138f6bb..8c62a81 100644 --- a/electron/main/poe/link_7day.ts +++ b/electron/main/poe/link_7day.ts @@ -1,40 +1,31 @@ import type { Browser, Page } from 'puppeteer' import puppeteer from 'puppeteer-extra' import StealthPlugin from 'puppeteer-extra-plugin-stealth' -import { browserAndPage, clog, createPromise } from "../tools" +import { browserAndPage, browsers, clog, createPromise, statusCheck } from "../tools" import login from '../login' puppeteer.use(StealthPlugin()) export async function link_7day(options) { + console.log('options', options); const log = clog(options) log('开始', { ident: 'link_7day' }) - let { p, resolve, reject } = createPromise() - login.mail_get_code(options).then(([page, browser, options]) => { - if (options.code) { - resolve(options.code) - browser.close() - } else { - log('未获取验证码,重试一次', { ident: 'link_7day' }) - setTimeout(async () => { - const code = await options.validateCode() - if (code) { - browser.close() - resolve(code) - }else { - setTimeout(async () => { - const code = await options.validateCode() - if (code) { - browser.close() - resolve(code) - }else { - resolve('') - } - }, 3000); - } - }, 3000); - } + let { p, resolve, reject } = createPromise() + + login.mail_get_code({ ...options, changeUS: false }).then(async ([page, browser, options]) => { + const isOk = await statusCheck( + () => options.code, + async () => { + log('未获取验证码,重试一次', { ident: 'link_7day' }) + options.code = await options.validateCode() + return options.code + }, + { interval: 4000 } + ) + resolve(options.code) + browser.close() }) + const [page, browser] = await login.poe_email(options, async () => { const code = await p console.log('获取验证码结果', code) @@ -45,16 +36,102 @@ export async function link_7day(options) { } return code - }) + }).catch(() => '' as any) - await getLink(options, [page, browser]) + // 登录失败了 + if (!page) { + console.log('登录失败了') + browsers.map(b => b.close()) + return + } - browser.close() + const url = await getLink(options, [page, browser]) + + if (url && options.liao) { + await recharge({ ...options, page, browser }) + } + + // browser.close() // await page.waitForTimeout(2000) // browser.close() // const { page } = await login.poe_email(options) } +async function test() { + const url = 'https://checkout.stripe.com/c/pay/cs_live_a1SgJas9blPTFsRxVwdTA6Ox1mQxnfj4uDoF2yKUrO6ZjAnY7dXbo9qVsp#fidkdWxOYHwnPyd1blppbHNgWjxITDJsdEROY3Y1NjZpNTc8Q1RMU3ZTNicpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl' + const liao = { + "bank": "5445446852620225", + "cvc": "233", + "date": "07/25", + "name": "Miguel", + "address": "5615 E 127th Ave Apt c", + "city": "Tampa", + "postalCode": "33613", + "nation": "US" + } + const user = 'neletegcongder@mail.com' + + const { page, browser } = await browserAndPage() + await page.goto(url) + recharge({ browser, page, user, liao }) +} + +// test() + +async function recharge(options: { + browser: Browser, + page: Page, + user: string, + liao: any, +}) { + const { browser, page, liao, ...args } = options + const log = clog(args) + log('开始充值') + await page.waitForSelector('#cardNumber') + + await page.evaluate(() => { + const btn: HTMLElement = document.querySelector('.AddressAutocomplete-manual-entry .Link') + if (btn) btn.click() + }) + + await page.evaluate((email: string) => { + const el: HTMLInputElement = document.querySelector('#email') + if (el) el.value = email + }, options.user) + + await page.type('#cardNumber', liao.bank) + await page.type('#cardExpiry', liao.date) + await page.type('#cardCvc', liao.cvc) + await page.type('#billingName', liao.name) + await page.select('#billingCountry', liao.nation) + await page.type('#billingAddressLine1', liao.address) + await page.type('#billingLocality', liao.city) + await page.type('#billingPostalCode', liao.postalCode) + await page.waitForTimeout(1000) + await page.click('.SubmitButton-IconContainer') + + // await page.waitForTimeout(9000) + + // await page.waitForSelector('iframe') + // let $frame = await page.$('iframe') + // let frame = await $frame.contentFrame() + + // console.log('$frame', $frame) + // // console.log('frame', frame) + // await $frame.waitForSelector('iframe') + // $frame = await frame.$('iframe') + // frame = await $frame.contentFrame() + // await frame.waitForSelector('iframe') + // $frame = await frame.$('iframe') + // frame = await $frame.contentFrame() + + // await frame.waitForSelector('#checkbox', { timeout: 0 }) + // await frame.click('#checkbox') + // await page.waitForNavigation() + console.log('充值成功') + log('充值成功') +} + function existDialog(page: Page) { return page.evaluate((selector, searchText) => { const elements = Array.from(document.querySelectorAll(selector)); @@ -90,11 +167,29 @@ export async function getLink(options, [page, browser]: [Page, Browser]) { log('已经订阅') return } - await page.waitForSelector('[class*=SettingsSubscriptionSection_subscribeButton]') + await page.waitForSelector('[class*=SettingsSubscriptionSection_subscribeButton]', { timeout: 0 }) page.waitForTimeout(500) log('点击显示订阅套餐按钮') - await page.click('[class*=SettingsSubscriptionSection_subscribeButton]') + // await page.click('[class*=SettingsSubscriptionSection_subscribeButton]') + + const disabled = await page.$eval('[class*=SettingsSubscriptionSection_subscribeButton]', (el: HTMLButtonElement) => el.disabled) + if (disabled) { + log('订阅按钮不可用,地区不可用') + return + } + + await statusCheck( + async () => { + return page.evaluate(() => { + const $el = document.querySelector("[class*=SettingsSubscriptionSection_subscribeButton]") + console.log('$el', $el) + $el.click(); + }) + }, + // async () => page.click('[class*=SettingsSubscriptionSection_subscribeButton]'), + async () => page.$('.Modal_modal__SxITf'), + ) } // log('显示更多套餐') @@ -106,7 +201,7 @@ export async function getLink(options, [page, browser]: [Page, Browser]) { // 点击订阅 log('4, 开始点击订阅') - await page.waitForSelector('[class*=WebSubscriptionPaywall_button]') + await page.waitForSelector('[class*=WebSubscriptionPaywall_button]', { timeout: 0 }) page.click('[class*=WebSubscriptionPaywall_button]') const [response] = await Promise.all([ page.waitForNavigation({ waitUntil: 'domcontentloaded' }), diff --git a/electron/main/tools.ts b/electron/main/tools.ts index 32aaa70..3d8cf7c 100644 --- a/electron/main/tools.ts +++ b/electron/main/tools.ts @@ -1,9 +1,64 @@ import type { Page } from "puppeteer" import puppeteer from 'puppeteer-extra' import StealthPlugin from 'puppeteer-extra-plugin-stealth' +import RecaptchaPlugin from 'puppeteer-extra-plugin-recaptcha' import chromeLauncher from 'chrome-launcher' import { win } from './index' +import fakeUa from 'fake-useragent' +import axios from "axios" puppeteer.use(StealthPlugin()) +puppeteer.use(RecaptchaPlugin({ + provider: { + id: '2captcha', + token: '25bd4a3638f3836b0d119007cbc21954' + }, + visualFeedback: true +})) + + +export function test1() { + // puppeteer-extra is a drop-in replacement for puppeteer, + // it augments the installed puppeteer with plugin functionality + const puppeteer = require('puppeteer-extra') + + // add recaptcha plugin and provide it your 2captcha token (= their apiKey) + // 2captcha is the builtin solution provider but others would work as well. + // Please note: You need to add funds to your 2captcha account for this to work + const RecaptchaPlugin = require('puppeteer-extra-plugin-recaptcha') + puppeteer.use( + RecaptchaPlugin({ + provider: { + id: '2captcha', + token: '25bd4a3638f3836b0d119007cbc21954' // REPLACE THIS WITH YOUR OWN 2CAPTCHA API KEY ⚡ + }, + visualFeedback: true // colorize reCAPTCHAs (violet = detected, green = solved) + }) + ) + + // puppeteer usage as normal + puppeteer.launch({ headless: false }).then(async browser => { + const page = await browser.newPage() + await page.goto('https://www.google.com/recaptcha/api2/demo') + + // That's it, a single line of code to solve reCAPTCHAs 🎉 + const { + captchas, + filtered, + solutions, + solved, + error + } = await page.solveRecaptchas() + + console.log({ captchas, filtered, solutions, solved, error }) + + await Promise.all([ + page.waitForNavigation(), + page.click(`#recaptcha-demo-submit`) + ]) + await page.screenshot({ path: 'response.png', fullPage: true }) + await browser.close() + }) +} //生成从minNum到maxNum的随机数 export function randomNum (min, max) { @@ -31,16 +86,32 @@ export function pageRequest (page: Page) { export const browsers = [] -export async function browserAndPage (options = {}) { - const { request } = options +export async function browserAndPage (options: any = {}) { + const { request, changeUS = true, proxy = false } = options + + async function proxyCommand () { + // const proxy = (await axios.get('http://127.0.0.1:10101/api/get_ip_list?num=1&country=US&state=all&city=all&zip=all&isp=all&t=1&port=40000&ip_time=1')).data + console.log('proxy', proxy); + + // return proxy ? + return `--proxy-server=socks5://127.0.0.1:40000` + } + + const args = [ + '--no-sandbox', + '--disable-setuid-sandbox', + ] + + // proxy ? args.push(await proxyCommand()) : null + console.log(args, proxy); + + // proxy ? args.push(await proxyCommand()) : '' + const browser = await puppeteer.launch({ headless: false, - args: [ - '--no-sandbox', - '--disable-setuid-sandbox', - // `--proxy-server=http:// - ] + args }) + browsers.push(browser) const close = browser.close browser.close = async function () { @@ -50,6 +121,9 @@ export async function browserAndPage (options = {}) { } const page = await browser.newPage() + console.log('fakeUa', fakeUa()); + + changeUS && page.setUserAgent(fakeUa()) await page.setExtraHTTPHeaders({ 'accept-language': 'en-US,en;q=0.9,hy;q=0.8' }) @@ -59,13 +133,26 @@ export async function browserAndPage (options = {}) { return { browser, page } } +function getProxy () { + return axios({ + url: 'http://api.tianqiip.com/getip?secret=loy0r7fpmnlshm8l&num=1&type=json&port=3&time=5&mr=1&sign=5f73ab58ad7ab40346311014bef59b79', + method: 'get', + }).then(res => { + console.log('proxy', res.data.data[0]) + return res.data.data[0] + }).catch(err => { + console.log(err) + }) +} + + /** * 记录日志 */ export function clog(options) { return (info, data = {}) => { if (win) { - win.webContents.send('progress', { ...options, info, ...data }) + win?.webContents?.send?.('progress', { ...options, info, ...data }) } } } @@ -94,15 +181,25 @@ async function findElement (page: Page, selector: string, searchText: string) { /** * 元素检查,被点击或按下按键后,检查是否成功,不成功测重试或其他操作 */ -export async function elCheck(operationsFn: Function, checkFn: Function, tryCount = 1) { +export async function statusCheck( + operationsFn: Function, + checkFn: Function, + options: {interval?: number, tryCount?: number} = {} +) { + options.interval = options.interval ?? 1000 + options.tryCount = options.tryCount ?? 1 + let { interval, tryCount } = options const { p, resolve, reject } = createPromise() await operationsFn() const pass = await checkFn() + console.log('检查状态', !!pass) if (pass) { resolve(true) } else { - if (tryCount > 1) { - return await elCheck(operationsFn, checkFn, tryCount - 1) + if (tryCount <= 5) { + await sleep(interval) + options.tryCount++ + return await statusCheck(operationsFn, checkFn, options) } else { resolve(false) } @@ -110,3 +207,28 @@ export async function elCheck(operationsFn: Function, checkFn: Function, tryCoun return p } + +export function sleep (time = 1000) { + return new Promise((resolve) => { + setTimeout(resolve, time) + }) +} + +/** + * 将方法重试n次 + */ +export function retry(fn: Function, tryCount = 1) { + return async function (...args) { + try { + return await fn(...args) + } catch (error) { + if (tryCount <= 5) { + await sleep(1000) + tryCount++ + return await retry(fn, tryCount)(...args) + } else { + throw error + } + } + } +} diff --git a/package.json b/package.json index 2bb48a9..5024fa0 100644 --- a/package.json +++ b/package.json @@ -43,11 +43,13 @@ "@vueuse/core": "^10.1.2", "axios": "^1.4.0", "chrome-launcher": "^0.15.2", + "fake-useragent": "^1.0.1", "mockjs": "^1.1.0", "naive-ui": "^2.34.4", "proxy-chain": "^2.3.0", "puppeteer": "^13.3.2", "puppeteer-extra": "^3.3.6", + "puppeteer-extra-plugin-recaptcha": "^3.6.8", "puppeteer-extra-plugin-stealth": "^2.11.2", "sass": "^1.62.1", "socks-proxy-agent": "^8.0.1", diff --git a/response.png b/response.png new file mode 100644 index 0000000..b7f193d Binary files /dev/null and b/response.png differ diff --git a/src/App.vue b/src/App.vue index 1537a05..c68f387 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,103 +1,31 @@