diff --git a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts index 6905047..fb1d757 100644 --- a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts +++ b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts @@ -168,31 +168,26 @@ export default function initIpc() { }) // console.log(subProcessOfPuppeteer) return new Promise((resolve, reject) => { - // subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => { - // const data = raw - // switch (data.type) { - // case 'AUTO_START_CHAT_DAEMON_PROCESS_STARTUP': { - // subProcessOfPuppeteer!.stdio[3]!.write( - // JSON.stringify({ - // type: 'GEEK_AUTO_START_CHAT_CAN_BE_RUN' - // }) - // ) - // break - // } - // case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': { - // resolve(data) - // break - // } - // case 'LOGIN_STATUS_INVALID': { - // await sleep(500) - // mainWindow?.webContents.send('check-boss-zhipin-cookie-file') - // return - // } - // default: { - // return - // } - // } - // }) + subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => { + const data = raw + switch (data.type) { + case 'LOGIN_STATUS_INVALID': { + await sleep(500) + mainWindow?.webContents.send('check-boss-zhipin-cookie-file') + return + } + case 'ERR_INTERNET_DISCONNECTED': { + mainWindow?.webContents.send('toast-message', { + type: 'error', + message: '联网失败,请检查网络连接' + }) + return + } + default: { + return + } + } + }) subProcessOfPuppeteer!.once('exit', (exitCode) => { subProcessOfPuppeteer = null @@ -204,7 +199,7 @@ export default function initIpc() { } }) - resolve(undefined) + resolve(true) }) // TODO: }) diff --git a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/bootstrap.ts b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/bootstrap.ts index 5036b40..2eead61 100644 --- a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/bootstrap.ts +++ b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/bootstrap.ts @@ -33,7 +33,14 @@ export async function launchBoss(browser: Browser) { await page.setCookie(bossCookies[i]) } await setDomainLocalStorage(browser, localStoragePageUrl, bossLocalStorage) - await Promise.all([page.goto(bossChatUiUrl, { timeout: 0 }), page.waitForNavigation()]) + try { + await Promise.all([page.goto(bossChatUiUrl, { timeout: 0 }), page.waitForNavigation()]) + } catch (error) { + if (error?.message?.startsWith('net::ERR_INTERNET_DISCONNECTED')) { + throw new Error('ERR_INTERNET_DISCONNECTED') + } + throw error + } pageMapByName['boss'] = page page.once('close', () => { pageMapByName['boss'] = null diff --git a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/index.ts b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/index.ts index d925a34..b2cc8f2 100644 --- a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/index.ts +++ b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/index.ts @@ -9,6 +9,9 @@ import { initDb } from '@geekgeekrun/sqlite-plugin' import { getPublicDbFilePath } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' import { ChatMessageRecord } from '@geekgeekrun/sqlite-plugin/dist/entity/ChatMessageRecord' import { saveChatMessageRecord } from '@geekgeekrun/sqlite-plugin/dist/handlers' +import { writeStorageFile } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' +import * as fs from 'fs' +import { pipeWriteRegardlessError } from '../utils/pipe' const dbInitPromise = initDb(getPublicDbFilePath()) @@ -29,7 +32,7 @@ async function saveCurrentChatRecord(page) { 'document.querySelector(".message-content .chat-record").__vue__.records$' ) )?.filter((msg) => ['received', 'sent'].includes(msg.style)) ?? [] - const chatRecordList = rawChatRecordList.map(it => { + const chatRecordList = rawChatRecordList.map((it) => { const mappedItem = {} as InstanceType mappedItem.mid = it.mid mappedItem.encryptFromUserId = @@ -86,6 +89,42 @@ const mainLoop = async () => { pageMapByName.boss!.bringToFront() await sleep(2000) + const currentPageUrl = pageMapByName.boss!.url() ?? '' + // #region + if (currentPageUrl.startsWith('https://www.zhipin.com/web/user/')) { + writeStorageFile('boss-cookies.json', []) + throw new Error('LOGIN_STATUS_INVALID') + } + if ( + currentPageUrl.startsWith('https://www.zhipin.com/web/common/403.html') || + currentPageUrl.startsWith('https://www.zhipin.com/web/common/error.html') + ) { + throw new Error('ACCESS_IS_DENIED') + } + if (currentPageUrl.startsWith('https://www.zhipin.com/web/user/safe/verify-slider')) { + const validateRes: any = await pageMapByName + .boss!.waitForResponse( + (response) => { + if ( + response.url().startsWith('https://www.zhipin.com/wapi/zpAntispam/v2/geetest/validate') + ) { + return true + } + return false + }, + { + timeout: 0 + } + ) + .then((res) => { + return res.json() + }) + if (validateRes.code === 0) { + await storeStorage(pageMapByName.boss) + throw new Error('CAPTCHA_PASSED_AND_NEED_RESTART') + } + } + // #endregion // check set security question tip modal let setSecurityQuestionTipModelProxy = await pageMapByName.boss!.$( '.dialog-wrap.dialog-account-safe' @@ -230,6 +269,13 @@ const rerunInterval = (() => { return v })() + +let pipe +try { + pipe = fs.createWriteStream(null, { fd: 3 }) +} catch { + console.warn('pipe is not available') +} export async function runEntry() { process.on('disconnect', () => { app.exit() @@ -246,6 +292,21 @@ export async function runEntry() { } catch { // } + // handle error + if ( + err instanceof Error && + ['LOGIN_STATUS_INVALID', 'ACCESS_IS_DENIED', 'ERR_INTERNET_DISCONNECTED'].includes( + err.message + ) + ) { + pipeWriteRegardlessError( + pipe, + JSON.stringify({ + type: err.message + }) + '\r\n' + ) + process.exit(1) + } } finally { pageMapByName['boss'] = null await sleep(rerunInterval) @@ -265,3 +326,18 @@ process.once('unhandledRejection', (error) => { console.log('unhandledRejection', error) process.exit(1) }) + +async function storeStorage(page) { + const [cookies, localStorage] = await Promise.all([ + page.cookies(), + page + .evaluate(() => { + return JSON.stringify(window.localStorage) + }) + .then((res) => JSON.parse(res)) + ]) + return Promise.all([ + writeStorageFile('boss-cookies.json', cookies), + writeStorageFile('boss-local-storage.json', localStorage) + ]) +} diff --git a/packages/ui/src/renderer/src/main.ts b/packages/ui/src/renderer/src/main.ts index 0a42f36..464baf0 100644 --- a/packages/ui/src/renderer/src/main.ts +++ b/packages/ui/src/renderer/src/main.ts @@ -1,5 +1,5 @@ import { createApp } from 'vue' -import ElementPlus from 'element-plus' +import ElementPlus, { ElMessage } from 'element-plus' import App from './App.vue' import router from './router' import 'normalize.css' @@ -8,7 +8,7 @@ import 'element-plus/dist/index.css' import 'virtual:uno.css' import 'animate.css' -createApp(App) - .use(router) - .use(ElementPlus) - .mount('#app') +createApp(App).use(router).use(ElementPlus).mount('#app') +electron.ipcRenderer.on('toast-message', (_, payload) => { + ElMessage(payload) +})