From 49d36516c160e9a00bb3fadd6f0c26169c42beb2 Mon Sep 17 00:00:00 2001 From: yema <1304119519@qq.com> Date: Sun, 4 Jun 2023 18:09:47 +0800 Subject: [PATCH 1/9] init --- electron/main/gpt/getLink.ts | 41 +++++ electron/main/gpt/index.ts | 45 +++++ electron/main/gpt/login.ts | 100 +++++++++++ electron/main/gpt/validate.ts | 27 +++ electron/main/index.ts | 6 +- electron/main/poe/getLink.js | 52 ++++++ electron/main/poe/hao.txt | 0 electron/main/poe/index.js | 62 +++++++ electron/main/poe/login.js | 89 +++++++++ electron/main/poe/openBrowser.js | 8 + electron/main/poe/validate.js | 39 ++++ electron/main/tools.js | 5 + package.json | 20 ++- src/App.vue | 299 ++++++++++++++++++++++++++----- src/auto-imports.d.ts | 178 ++++++++++++++++++ src/components.d.ts | 17 ++ src/main.ts | 3 + src/style.css | 13 +- unocss.config.ts | 35 ++++ vite.config.ts | 26 +++ 20 files changed, 1016 insertions(+), 49 deletions(-) create mode 100644 electron/main/gpt/getLink.ts create mode 100644 electron/main/gpt/index.ts create mode 100644 electron/main/gpt/login.ts create mode 100644 electron/main/gpt/validate.ts create mode 100644 electron/main/poe/getLink.js create mode 100644 electron/main/poe/hao.txt create mode 100644 electron/main/poe/index.js create mode 100644 electron/main/poe/login.js create mode 100644 electron/main/poe/openBrowser.js create mode 100644 electron/main/poe/validate.js create mode 100644 electron/main/tools.js create mode 100644 src/auto-imports.d.ts create mode 100644 src/components.d.ts create mode 100644 unocss.config.ts diff --git a/electron/main/gpt/getLink.ts b/electron/main/gpt/getLink.ts new file mode 100644 index 0000000..c2185e4 --- /dev/null +++ b/electron/main/gpt/getLink.ts @@ -0,0 +1,41 @@ +import { clog } from "../poe/login"; +import { login } from "./login"; + +export async function getLink(options) { + const log = clog(options) + log('开始', { ident: 'gpt-link' }) + const page = await login(options) + + // await page.waitForTimeout(500) + + await page.waitForSelector('body > div.absolute.inset-0') + await page.evaluate(() => { + const $mark = document.querySelector("body > div.absolute.inset-0") + if ($mark) $mark.hidden = true + document.body.style.pointerEvents = 'all' + }) + + log('隐藏欢迎页面') + + await page.waitForSelector('.gold-new-button', { visible: true }) + log('等待升级plus按钮出现') + await page.waitForTimeout(500) + + log('开始点击升级plus按钮') + await page.click('.gold-new-button') + + const [response] = await Promise.all([ + page.waitForNavigation({ waitUntil: 'domcontentloaded' }), + page.evaluate((selector, searchText) => { + const elements = Array.from(document.querySelectorAll(selector)); + const target = elements.find(el => el.textContent.trim() === searchText); + target && target.click() + }, 'button', 'Upgrade plan') + ]) + + if (response.ok()) { + const url = response._request._frame._url + log('获取链接成功', { result: url, type: 'success' }) + return url + } +} diff --git a/electron/main/gpt/index.ts b/electron/main/gpt/index.ts new file mode 100644 index 0000000..a844cba --- /dev/null +++ b/electron/main/gpt/index.ts @@ -0,0 +1,45 @@ +import { ipcMain } from 'electron' +import { getLink } from './getLink' +import { validate } from './validate' +import { browser } from './login' + +const parseAccount = text => text.split('\n').filter(Boolean).map(v => { + v = v.split(/(——|-)+/).filter(v => !['-', '——'].includes(v)) + return v +}) + +ipcMain.handle('gpt-link', async (event, arg) => { + const { text } = arg + const accounts = parseAccount(text) + + const links = [] + for(let i = 0; i < accounts.length; i++) { + const [user, pass] = accounts[i] + const link = await getLink({ user, pass, index: i, id: user }) + links.push({ + i, + user, + link + }) + console.log('process', i, user, link) + } + browser && browser.close() +}) + +ipcMain.handle('gpt-result', async (event, arg) => { + const { text } = arg + const accounts = parseAccount(text) + + const links = [] + for(let i = 0; i < accounts.length; i++) { + const [user, pass] = accounts[i] + const link = await validate({ user, pass, index: i, id: user }) + links.push({ + i, + user, + link + }) + console.log('process', i, user, link) + } + // browser && browser.close() +}) diff --git a/electron/main/gpt/login.ts b/electron/main/gpt/login.ts new file mode 100644 index 0000000..facbbe3 --- /dev/null +++ b/electron/main/gpt/login.ts @@ -0,0 +1,100 @@ +import type { Browser, Page } from 'puppeteer' +import puppeteer from 'puppeteer-extra' +import StealthPlugin from 'puppeteer-extra-plugin-stealth' +import { randomNum } from '../tools' +import { win } from '../index' +import { clog } from '../poe/login' +puppeteer.use(StealthPlugin()) + +let id +export let browser: Browser | undefined +/** + * 登录google + */ +export async function login(options, tryCount = 1): Promise { + let resolve, reject + const log = clog(options) + const p = new Promise((res, rej) => { + resolve = res + reject = rej + }) + id = options.id + const env = { + GUSER: options.user, + GPASS: options.pass + } + + if (browser) await browser.close() + + browser = await puppeteer.launch({ headless: false }) + const page = await browser.newPage() + await page.setExtraHTTPHeaders({ + 'accept-language': 'en-US,en;q=0.9,hy;q=0.8' + }) + + log('开始访问 gpt') + await page.goto('https://chat.openai.com/auth/login') + await page.waitForSelector('button') + + // log('准备进入 google 登录页') + const [response] = await Promise.all([ + page.waitForNavigation(() => location.href.startsWith('https://auth0.openai.com/u/login/identifier')), + page.click('button') + ]) + // log('已进入 google 登录页') + + if (!response.ok()) return log('进入 google 登录页失败') + + log('准备输入账号') + await page.type('#username', env.GUSER) + await Promise.all([ + page.waitForNavigation(), + page.keyboard.press('Enter') + ]) + + log('已输入账号,准备输入密码') + await page.waitForSelector('#password', { visible: true }) + await page.type('#password', env.GPASS) + log('已输入密码,开始登录') + + await Promise.all([ + page.waitForNavigation(() => location.href === 'https://chat.openai.com/'), + page.keyboard.press('Enter') + ]) + log('登录成功') + resolve(page) + + // if (response.ok()) { + // await page.waitForSelector('input[type="email"]') + // log('准备输入账号') + // await page.type('input[type="email"]', env.GUSER) + // await Promise.all([ + // page.waitForNavigation(), + // await page.keyboard.press('Enter') + // ]) + // log('已输入账号,准备输入密码') + // await page.waitForSelector('input[type="password"]', { visible: true }) + // await page.type('input[type="password"]', env.GPASS) + // log('已输入密码,开始登录') + // await Promise.all([ + // page.waitForFunction(() => location.href === 'https://poe.com/'), + // await page.keyboard.press('Enter') + // ]) + + // log('登录成功,准备进入 poe') + + // return page + // } + + // if (tryCount < 4) { + // log(`google 登录失败,准备 ${tryCount} 次重试`) + // await page.close() + // return await loginGoogle(options, tryCount + 1) + // } else { + // log('google 登录失败,重试次数已达上限') + // reject('google 登录失败') + // } + + return p + // return Promise.reject('google 登录失败') +} diff --git a/electron/main/gpt/validate.ts b/electron/main/gpt/validate.ts new file mode 100644 index 0000000..922b63a --- /dev/null +++ b/electron/main/gpt/validate.ts @@ -0,0 +1,27 @@ +import { clog } from "../poe/login"; +import { login } from "./login"; + +export async function validate(options) { + const log = clog(options) + log('开始', { ident: 'gpt-validate' }) + const page = await login(options) + + await page.waitForSelector('body > div.absolute.inset-0') + await page.evaluate(() => { + const $mark = document.querySelector("body > div.absolute.inset-0") + if ($mark) $mark.hidden = true + document.body.style.pointerEvents = 'all' + }) + log('隐藏欢迎页面,开始检测') + + await page.waitForTimeout(2000) + + const isSuccess = await page.evaluate((selector, searchText) => { + const elements = Array.from(document.querySelectorAll(selector)); + const target = elements.find(el => el.textContent.trim() === searchText); + return !!target + }, 'button', 'GPT-4') + log('获取链接成功', { result: isSuccess ? '充值成功😘' : '充值失败😭', type: isSuccess ? 'success' : 'fail' }) + + console.log(isSuccess) +} diff --git a/electron/main/index.ts b/electron/main/index.ts index a1bed6c..bf868dd 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -1,6 +1,8 @@ import { app, BrowserWindow, shell, ipcMain } from 'electron' import { release } from 'node:os' import { join } from 'node:path' +import './poe/index' +import './gpt/index' // The built directory structure // @@ -34,7 +36,7 @@ if (!app.requestSingleInstanceLock()) { // Read more on https://www.electronjs.org/docs/latest/tutorial/security // process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true' -let win: BrowserWindow | null = null +export let win: BrowserWindow | null = null // Here, you can also use other preload const preload = join(__dirname, '../preload/index.js') const url = process.env.VITE_DEV_SERVER_URL @@ -43,6 +45,8 @@ const indexHtml = join(process.env.DIST, 'index.html') async function createWindow() { win = new BrowserWindow({ title: 'Main window', + width: 1000, + height: 800, icon: join(process.env.PUBLIC, 'favicon.ico'), webPreferences: { preload, diff --git a/electron/main/poe/getLink.js b/electron/main/poe/getLink.js new file mode 100644 index 0000000..37d7201 --- /dev/null +++ b/electron/main/poe/getLink.js @@ -0,0 +1,52 @@ +import { clog, loginGoogle } from './login' +import { readFileSync, writeFileSync } from 'fs' +import path from 'path' +import { EOL } from 'os' + +export async function getLink(options) { + const log = clog(options) + log('开始', { ident: 'poe-link' }) + const page = await loginGoogle(options) + + await Promise.all([ + page.waitForNavigation(), + page.goto('https://poe.com/settings') + ]) + + log('已进入设置页面, 检查中') + + // page.waitForTimeout(1000) + await page.waitForSelector('[class*=SettingsSubscriptionSection_subscribeButton]') + log('1, 开始点击显示订阅套餐按钮') + await page.click('[class*=SettingsSubscriptionSection_subscribeButton]') + log('2, 开始点击显示更多套餐') + await page.waitForSelector('[class*=WebSubscriptionFreeTrial_viewAllPlansButton]') + await page.click('[class*=WebSubscriptionFreeTrial_viewAllPlansButton]') + log('3, 开始点击最后一个套餐') + await page.waitForSelector('[class*=WebSubscriptionPaywall_plans]') + await page.click('[class*=WebSubscriptionPaywall_plans] > button:last-child') + + // 点击订阅 + log('4, 开始点击订阅') + page.click('[class*=WebSubscriptionPaywall_button]') + const [response] = await Promise.all([ + page.waitForNavigation({ waitUntil: 'domcontentloaded' }), + ]) + + if (response.ok()) { + const url = response._request._frame._url + log('获取链接成功', { result: url, type: 'success' }) + return url + + // if (options.index === 0) { + // writeFileSync(resolve('./hao.txt'), '', 'utf8') + // } + // const fileContent = readFileSync(resolve('./hao.txt'), 'utf8') + // writeFileSync(resolve('./hao.txt'), fileContent + `${EOL}${options.index + 1} ${options.user}${EOL}${url}`, 'utf8') + } +} + + +function resolve(url) { + return path.resolve(__dirname, '../src/poe/', url) +} diff --git a/electron/main/poe/hao.txt b/electron/main/poe/hao.txt new file mode 100644 index 0000000..e69de29 diff --git a/electron/main/poe/index.js b/electron/main/poe/index.js new file mode 100644 index 0000000..aa645b2 --- /dev/null +++ b/electron/main/poe/index.js @@ -0,0 +1,62 @@ +import { getLink } from './getLink' +import { validate } from './validate' +import { ipcMain } from 'electron' +import { browser } from './login' + +// import './openBrowser' +// suzzettedeanne2393@gmail.com----zebulonlawayne3013----zebulonlawayne4749@outlook.com +const text = ` +` + +export const parseAccount = text => text.split('\n').filter(Boolean).map(v => { + v = v.split(/(——|-)+/).filter(v => !['-', '——'].includes(v)) + return v +}) + +ipcMain.handle('getLink', async (event, arg) => { + const { text } = arg + const accounts = parseAccount(text) + + const links = [] + 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 => { + // console.log('error ->', err) + // }) + links.push({ + i, + user, + link + }) + console.log('process', i, user, link) + } + browser && browser.close() + return links +}) + +ipcMain.handle('poe-result', async (event, arg) => { + const { text } = arg + const accounts = parseAccount(text) + + const links = [] + 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 => { + // console.log('error ->', err) + // }) + links.push({ + i, + user, + link + }) + console.log('process', i, user, link) + } + browser && browser.close() + return links +}) +ipcMain.handle('stop', async (event, arg) => { + browser && browser.close() + return true +}) diff --git a/electron/main/poe/login.js b/electron/main/poe/login.js new file mode 100644 index 0000000..7693990 --- /dev/null +++ b/electron/main/poe/login.js @@ -0,0 +1,89 @@ +import puppeteer from 'puppeteer-extra' +import StealthPlugin from 'puppeteer-extra-plugin-stealth' +import { randomNum } from '../tools' +import { win } from '../index' +puppeteer.use(StealthPlugin()) + + + +let id +export let browser +/** + * 登录google + */ +export async function loginGoogle(options, tryCount = 1) { + let resolve, reject + const log = clog(options) + const p = new Promise((res, rej) => { + resolve = res + reject = rej + }) + id = options.id + const env = { + GUSER: options.user, + GPASS: options.pass + } + + if (browser) await browser.close() + + browser = await puppeteer.launch({ headless: false }) + const page = await browser.newPage() + await page.setExtraHTTPHeaders({ + 'accept-language': 'en-US,en;q=0.9,hy;q=0.8' + }) + + log('开始访问 poe') + await page.goto('https://poe.com') + log('已进入 poe') + await page.waitForTimeout(randomNum(1000, 2600)) + + log('准备进入 google 登录页') + const [response] = await Promise.all([ + page.waitForNavigation(() => location.href.startsWith('https://accounts.google.com')), + page.click('.ContinueWithGoogleButton_buttonContentWrapper__Mrp0W') + ]) + log('已进入 google 登录页') + + if (response.ok()) { + await page.waitForSelector('input[type="email"]') + log('准备输入账号') + await page.type('input[type="email"]', env.GUSER) + await Promise.all([ + page.waitForNavigation(), + await page.keyboard.press('Enter') + ]) + log('已输入账号,准备输入密码') + await page.waitForSelector('input[type="password"]', { visible: true }) + await page.type('input[type="password"]', env.GPASS) + log('已输入密码,开始登录') + await Promise.all([ + page.waitForFunction(() => location.href === 'https://poe.com/'), + await page.keyboard.press('Enter') + ]) + + log('登录成功,准备进入 poe') + + return page + } + + if (tryCount < 4) { + log(`google 登录失败,准备 ${tryCount} 次重试`) + await page.close() + return await loginGoogle(options, tryCount + 1) + } else { + log('google 登录失败,重试次数已达上限') + reject('google 登录失败') + } + + return p + // return Promise.reject('google 登录失败') +} + + +export function clog(options) { + return (info, data = {}) => { + if (win) { + win.webContents.send('progress', {...options, info, ...data}) + } + } +} diff --git a/electron/main/poe/openBrowser.js b/electron/main/poe/openBrowser.js new file mode 100644 index 0000000..2ea0089 --- /dev/null +++ b/electron/main/poe/openBrowser.js @@ -0,0 +1,8 @@ +import puppeteer from 'puppeteer-extra' +import StealthPlugin from 'puppeteer-extra-plugin-stealth' +puppeteer.use(StealthPlugin()) + +;(async () => { + const browser = await puppeteer.launch({ headless: false }) + browser.newPage() +})() diff --git a/electron/main/poe/validate.js b/electron/main/poe/validate.js new file mode 100644 index 0000000..8061e71 --- /dev/null +++ b/electron/main/poe/validate.js @@ -0,0 +1,39 @@ +import { clog, loginGoogle } from './login' +import { readFileSync, writeFileSync } from 'fs' +import path from 'path' +import { EOL } from 'os' + +export async function validate (options) { + const log = clog(options) + log('开始', { ident: 'poe-validate' }) + const page = await loginGoogle(options) + + await Promise.all([ + page.waitForNavigation(), + page.goto('https://poe.com/settings') + ]) + + log('已进入设置页面, 检查中', { ident: 'poe-validate' }) + + const length = await page.$$eval('.SettingsSubscriptionSection_botLimitSection__j4mSO > div:first-child > div', (doms) => doms.length) + // page.close() + + // if (options.index === 0) { + // writeFileSync(resolve('./validate.txt'), '', 'utf8') + // } + // const fileContent = readFileSync(resolve('./validate.txt'), 'utf8') + const resultTxt = length === 1 ? '失败😭' : '成功😘' + // writeFileSync(resolve('./validate.txt'), fileContent + `${options.index + 1} ${options.user}----${resultTxt}${EOL}`, 'utf8') + + log(resultTxt, { type: length === 1 ? 'fail' : 'success', result: length === 1 ? '失败😭' : '成功😘' }) + // // 不成功 + // if (length === 1) { + + // } else { + // log('充值成功😘') + // } +} + +function resolve (url) { + return path.resolve(__dirname, '../src/poe/', url) +} diff --git a/electron/main/tools.js b/electron/main/tools.js new file mode 100644 index 0000000..10ddf5c --- /dev/null +++ b/electron/main/tools.js @@ -0,0 +1,5 @@ + +//生成从minNum到maxNum的随机数 +export function randomNum (min, max) { + return parseInt(Math.random() * (max - min + 1) + min) +} diff --git a/package.json b/package.json index 1209e0c..6ff78c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "electron-vue-vite", - "version": "2.0.0", + "name": "poe_gpt", + "version": "1.0.0", "main": "dist-electron/main/index.js", "description": "Really simple Electron + Vue + Vite boilerplate.", "author": "草鞋没号 <308487730@qq.com>", @@ -20,18 +20,32 @@ }, "scripts": { "dev": "vite", - "build": "vue-tsc --noEmit && vite build && electron-builder", + "build": "vite build && electron-builder", + "build:64": "vite build && electron-builder --win --x64", + "build:32": "vite build && electron-builder --win --x32", "preview": "vite preview" }, "devDependencies": { "@vitejs/plugin-vue": "^4.1.0", + "@vitejs/plugin-vue-jsx": "^3.0.1", "electron": "^25.0.1", "electron-builder": "^23.6.0", "typescript": "^5.0.2", + "unplugin-auto-import": "^0.16.4", + "unplugin-vue-components": "^0.25.0", "vite": "^4.1.4", "vite-plugin-electron": "^0.11.2", "vite-plugin-electron-renderer": "^0.14.1", "vue": "^3.2.47", "vue-tsc": "^1.2.0" + }, + "dependencies": { + "@vueuse/core": "^10.1.2", + "naive-ui": "^2.34.4", + "puppeteer": "^13.3.2", + "puppeteer-extra": "^3.3.6", + "puppeteer-extra-plugin-stealth": "^2.11.2", + "sass": "^1.62.1", + "unocss": "^0.52.7" } } diff --git a/src/App.vue b/src/App.vue index 3210bf6..88a45ff 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,51 +1,268 @@ -