mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-07 00:17:17 +08:00
Merge branch 'feat/login-with-edit-this-cookie' into feature/ui
This commit is contained in:
@@ -1,3 +1,2 @@
|
|||||||
{
|
{
|
||||||
"cookies": []
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -8,12 +8,16 @@ import os from 'node:os'
|
|||||||
import { get__dirname } from '@geekgeekrun/utils/legacy-path.mjs';
|
import { get__dirname } from '@geekgeekrun/utils/legacy-path.mjs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import JSON5 from 'json5'
|
import JSON5 from 'json5'
|
||||||
|
import { EventEmitter } from 'node:events'
|
||||||
|
import { setDomainLocalStorage } from '@geekgeekrun/utils/puppeteer/local-storage.mjs'
|
||||||
|
|
||||||
import { readConfigFile, ensureConfigFileExist } from './runtime-file-utils.mjs'
|
import { readConfigFile, writeStorageFile, ensureConfigFileExist, readStorageFile, ensureStorageFileExist } from './runtime-file-utils.mjs'
|
||||||
ensureConfigFileExist()
|
ensureConfigFileExist()
|
||||||
|
ensureStorageFileExist()
|
||||||
|
|
||||||
const isRunFromUi = Boolean(process.env.MAIN_BOSSGEEKGO_UI_RUN_MODE)
|
const isRunFromUi = Boolean(process.env.MAIN_BOSSGEEKGO_UI_RUN_MODE)
|
||||||
const isUiDev = process.env.NODE_ENV === 'development'
|
const isUiDev = process.env.NODE_ENV === 'development'
|
||||||
|
export const autoStartChatEventBus = new EventEmitter()
|
||||||
|
|
||||||
let puppeteer, StealthPlugin
|
let puppeteer, StealthPlugin
|
||||||
export async function initPuppeteer () {
|
export async function initPuppeteer () {
|
||||||
@@ -43,12 +47,19 @@ export async function initPuppeteer () {
|
|||||||
StealthPlugin = importResult[1].default
|
StealthPlugin = importResult[1].default
|
||||||
}
|
}
|
||||||
puppeteer.use(StealthPlugin())
|
puppeteer.use(StealthPlugin())
|
||||||
|
|
||||||
|
return {
|
||||||
|
puppeteer,
|
||||||
|
StealthPlugin
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { cookies: bossCookies } = readConfigFile('boss.json')
|
const bossCookies = readStorageFile('boss-cookies.json')
|
||||||
|
const bossLocalStorage = readStorageFile('boss-local-storage.json')
|
||||||
|
|
||||||
const targetCompanyList = readConfigFile('target-company-list.json')
|
const targetCompanyList = readConfigFile('target-company-list.json')
|
||||||
|
|
||||||
|
const localStoragePageUrl = `https://www.zhipin.com/desktop/`
|
||||||
const recommendJobPageUrl = `https://www.zhipin.com/web/geek/job-recommend`
|
const recommendJobPageUrl = `https://www.zhipin.com/web/geek/job-recommend`
|
||||||
|
|
||||||
const expectCompanySet = new Set(targetCompanyList)
|
const expectCompanySet = new Set(targetCompanyList)
|
||||||
@@ -79,18 +90,39 @@ export async function mainLoop (hooks) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
//set cookies
|
//set cookies
|
||||||
const copiedBossCookies = JSON.parse(JSON.stringify(bossCookies))
|
hooks.cookieWillSet?.call(bossCookies)
|
||||||
|
for(let i = 0; i < bossCookies.length; i++){
|
||||||
hooks.cookieWillSet?.call(copiedBossCookies)
|
await page.setCookie(bossCookies[i]);
|
||||||
for(let i = 0; i < copiedBossCookies.length; i++){
|
|
||||||
await page.setCookie(copiedBossCookies[i]);
|
|
||||||
}
|
}
|
||||||
|
await setDomainLocalStorage(browser, localStoragePageUrl, bossLocalStorage)
|
||||||
|
|
||||||
|
let userInfoResponse
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
page.goto(recommendJobPageUrl, { timeout: 0 }),
|
page.goto(recommendJobPageUrl, { timeout: 0 }),
|
||||||
|
page.waitForResponse((response) => {
|
||||||
|
if (response.url().startsWith('https://www.zhipin.com/wapi/zpuser/wap/getUserInfo.json')) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}).then((res) => {
|
||||||
|
return res.json()
|
||||||
|
}).then((res) => {
|
||||||
|
userInfoResponse = res
|
||||||
|
}),
|
||||||
page.waitForNavigation(),
|
page.waitForNavigation(),
|
||||||
])
|
])
|
||||||
hooks.pageLoaded?.call()
|
hooks.pageLoaded?.call()
|
||||||
|
hooks.userInfoResponse?.call(userInfoResponse)
|
||||||
|
|
||||||
|
if (userInfoResponse.code !== 0) {
|
||||||
|
autoStartChatEventBus.emit('LOGIN_STATUS_INVALID', {
|
||||||
|
userInfoResponse
|
||||||
|
})
|
||||||
|
writeStorageFile('boss-cookies.json', [])
|
||||||
|
throw new Error("LOGIN_STATUS_INVALID")
|
||||||
|
} else {
|
||||||
|
await storeStorage(page).catch(() => void 0)
|
||||||
|
}
|
||||||
|
|
||||||
const INIT_START_EXCEPT_JOB_INDEX = 1
|
const INIT_START_EXCEPT_JOB_INDEX = 1
|
||||||
let currentExceptJobIndex = INIT_START_EXCEPT_JOB_INDEX
|
let currentExceptJobIndex = INIT_START_EXCEPT_JOB_INDEX
|
||||||
@@ -123,6 +155,7 @@ export async function mainLoop (hooks) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
await storeStorage(page).catch(() => void 0)
|
||||||
await sleepWithRandomDelay(2000)
|
await sleepWithRandomDelay(2000)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +275,7 @@ export async function mainLoop (hooks) {
|
|||||||
if (res.code !== 0) {
|
if (res.code !== 0) {
|
||||||
// startup chat error, may the chance of today has used out
|
// startup chat error, may the chance of today has used out
|
||||||
if (res.zpData.bizCode === 1 && res.zpData.bizData?.chatRemindDialog?.blockLevel === 0 && res.zpData.bizData?.chatRemindDialog?.content === `今日沟通人数已达上限,请明天再试`) {
|
if (res.zpData.bizCode === 1 && res.zpData.bizData?.chatRemindDialog?.blockLevel === 0 && res.zpData.bizData?.chatRemindDialog?.content === `今日沟通人数已达上限,请明天再试`) {
|
||||||
|
await storeStorage(page).catch(() => void 0)
|
||||||
throw new Error('STARTUP_CHAT_ERROR_DUE_TO_TODAY_CHANCE_HAS_USED_OUT')
|
throw new Error('STARTUP_CHAT_ERROR_DUE_TO_TODAY_CHANCE_HAS_USED_OUT')
|
||||||
} else {
|
} else {
|
||||||
console.error(res)
|
console.error(res)
|
||||||
@@ -251,6 +285,7 @@ export async function mainLoop (hooks) {
|
|||||||
hooks.newChatStartup?.call(jobData)
|
hooks.newChatStartup?.call(jobData)
|
||||||
blockBossNotNewChat.add(jobData.jobInfo.encryptUserId)
|
blockBossNotNewChat.add(jobData.jobInfo.encryptUserId)
|
||||||
|
|
||||||
|
await storeStorage(page).catch(() => void 0)
|
||||||
await sleepWithRandomDelay(750)
|
await sleepWithRandomDelay(750)
|
||||||
const closeDialogButtonProxy = await page.$('.greet-boss-dialog .greet-boss-footer .cancel-btn')
|
const closeDialogButtonProxy = await page.$('.greet-boss-dialog .greet-boss-footer .cancel-btn')
|
||||||
await closeDialogButtonProxy.click()
|
await closeDialogButtonProxy.click()
|
||||||
@@ -317,6 +352,23 @@ export async function mainLoop (hooks) {
|
|||||||
|
|
||||||
export async function closeBrowserWindow () {
|
export async function closeBrowserWindow () {
|
||||||
browser?.close()
|
browser?.close()
|
||||||
browse = null
|
browser = null
|
||||||
page = null
|
page = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import defaultDingtalkConf from './default-config-file/dingtalk.json' assert {ty
|
|||||||
import defaultBossConf from './default-config-file/boss.json' assert {type: 'json'}
|
import defaultBossConf from './default-config-file/boss.json' assert {type: 'json'}
|
||||||
import defaultTargetCompanyListConf from './default-config-file/target-company-list.json' assert {type: 'json'}
|
import defaultTargetCompanyListConf from './default-config-file/target-company-list.json' assert {type: 'json'}
|
||||||
|
|
||||||
|
import defaultBossCookieStorage from './default-storage-file/boss-cookies.json' assert { type: 'json' }
|
||||||
|
import defaultBossLocalStorageStorage from './default-storage-file/boss-local-storage.json' assert { type: 'json' }
|
||||||
export const configFileNameList = ['boss.json', 'dingtalk.json', 'target-company-list.json']
|
export const configFileNameList = ['boss.json', 'dingtalk.json', 'target-company-list.json']
|
||||||
|
|
||||||
const defaultConfigFileContentMap = {
|
const defaultConfigFileContentMap = {
|
||||||
@@ -20,7 +22,7 @@ const ensureRuntimeFolderPathExist = () => {
|
|||||||
if (!fs.existsSync(runtimeFolderPath)) {
|
if (!fs.existsSync(runtimeFolderPath)) {
|
||||||
fs.mkdirSync(runtimeFolderPath)
|
fs.mkdirSync(runtimeFolderPath)
|
||||||
}
|
}
|
||||||
;['config'].forEach(dirPath => {
|
;['config', 'storage'].forEach(dirPath => {
|
||||||
if (!fs.existsSync(
|
if (!fs.existsSync(
|
||||||
path.join(runtimeFolderPath, dirPath)
|
path.join(runtimeFolderPath, dirPath)
|
||||||
)) {
|
)) {
|
||||||
@@ -52,8 +54,9 @@ export const ensureConfigFileExist = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const readConfigFile = (fileName) => {
|
export const readConfigFile = (fileName) => {
|
||||||
|
const joinedPath = path.join(configFolderPath, fileName)
|
||||||
if (!fs.existsSync(
|
if (!fs.existsSync(
|
||||||
path.join(configFolderPath, fileName)
|
joinedPath
|
||||||
)) {
|
)) {
|
||||||
ensureConfigFileExist()
|
ensureConfigFileExist()
|
||||||
}
|
}
|
||||||
@@ -61,10 +64,10 @@ export const readConfigFile = (fileName) => {
|
|||||||
let o
|
let o
|
||||||
try {
|
try {
|
||||||
o = JSON.parse(
|
o = JSON.parse(
|
||||||
fs.readFileSync(path.join(configFolderPath, fileName))
|
fs.readFileSync(joinedPath)
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
fs.unlinkSync(fs.readFileSync(path.join(configFolderPath, fileName)))
|
fs.existsSync(joinedPath) && fs.unlinkSync(joinedPath)
|
||||||
ensureConfigFileExist()
|
ensureConfigFileExist()
|
||||||
o = JSON.parse(defaultConfigFileContentMap[fileName])
|
o = JSON.parse(defaultConfigFileContentMap[fileName])
|
||||||
}
|
}
|
||||||
@@ -81,3 +84,60 @@ export const writeConfigFile = async (fileName, content) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const storageFilePath = path.join(
|
||||||
|
runtimeFolderPath,
|
||||||
|
'storage'
|
||||||
|
)
|
||||||
|
export const storageFileNameList = ['boss-cookies.json', 'boss-local-storage.json']
|
||||||
|
|
||||||
|
const defaultStorageFileContentMap = {
|
||||||
|
'boss-cookies.json': JSON.stringify(defaultBossCookieStorage),
|
||||||
|
'boss-local-storage.json': JSON.stringify(defaultBossLocalStorageStorage)
|
||||||
|
}
|
||||||
|
export const ensureStorageFileExist = () => {
|
||||||
|
ensureRuntimeFolderPathExist()
|
||||||
|
;storageFileNameList.forEach(
|
||||||
|
fileName => {
|
||||||
|
if (!fs.existsSync(
|
||||||
|
path.join(storageFilePath, fileName)
|
||||||
|
)) {
|
||||||
|
fs.writeFileSync(
|
||||||
|
path.join(storageFilePath, fileName),
|
||||||
|
defaultStorageFileContentMap[fileName]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const readStorageFile = (fileName) => {
|
||||||
|
const joinedPath = path.join(storageFilePath, fileName)
|
||||||
|
|
||||||
|
if (!fs.existsSync(
|
||||||
|
joinedPath
|
||||||
|
)) {
|
||||||
|
ensureStorageFileExist()
|
||||||
|
}
|
||||||
|
|
||||||
|
let o
|
||||||
|
try {
|
||||||
|
o = JSON.parse(
|
||||||
|
fs.readFileSync(joinedPath)
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
fs.existsSync(joinedPath) && fs.unlinkSync(joinedPath)
|
||||||
|
ensureStorageFileExist()
|
||||||
|
o = JSON.parse(defaultStorageFileContentMap[fileName])
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
export const writeStorageFile = async (fileName, content) => {
|
||||||
|
const filePath = path.join(storageFilePath, fileName)
|
||||||
|
const fileContent = JSON.stringify(content)
|
||||||
|
return fsPromise.writeFile(
|
||||||
|
filePath,
|
||||||
|
fileContent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -0,0 +1,162 @@
|
|||||||
|
|
||||||
|
import {
|
||||||
|
initPuppeteer
|
||||||
|
} from '@geekgeekrun/geek-auto-start-chat-with-boss/index.mjs'
|
||||||
|
import {
|
||||||
|
sleep,
|
||||||
|
sleepWithRandomDelay
|
||||||
|
} from '@geekgeekrun/utils/sleep.mjs'
|
||||||
|
import extractZip from 'extract-zip'
|
||||||
|
import { blockNavigation } from '@geekgeekrun/utils/puppeteer/block-navigation.mjs'
|
||||||
|
import {
|
||||||
|
writeStorageFile
|
||||||
|
} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||||
|
|
||||||
|
import fs from 'node:fs'
|
||||||
|
import os from 'node:os'
|
||||||
|
import path from 'node:path';
|
||||||
|
import JSON5 from 'json5'
|
||||||
|
import url from 'url';
|
||||||
|
import packageJson from './package.json' assert {type: 'json'}
|
||||||
|
|
||||||
|
import { EventEmitter } from 'node:events'
|
||||||
|
|
||||||
|
export const loginEventBus = new EventEmitter()
|
||||||
|
|
||||||
|
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
||||||
|
const isRunFromUi = Boolean(process.env.MAIN_BOSSGEEKGO_UI_RUN_MODE)
|
||||||
|
const isUiDev = process.env.NODE_ENV === 'development'
|
||||||
|
|
||||||
|
const runtimeFolderPath = path.join(os.homedir(), '.geekgeekrun')
|
||||||
|
const extensionDir = path.join(
|
||||||
|
runtimeFolderPath,
|
||||||
|
'chrome-extensions'
|
||||||
|
)
|
||||||
|
if (!fs.existsSync(
|
||||||
|
runtimeFolderPath
|
||||||
|
)) {
|
||||||
|
fs.mkdirSync(runtimeFolderPath)
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(extensionDir)) {
|
||||||
|
fs.mkdirSync(extensionDir)
|
||||||
|
}
|
||||||
|
const editThisCookieExtensionPath = path.join(extensionDir, 'EditThisCookie')
|
||||||
|
|
||||||
|
let editThisCookieZipPath
|
||||||
|
async function getEditThisCookieZipPath () {
|
||||||
|
if (editThisCookieZipPath) {
|
||||||
|
return editThisCookieZipPath
|
||||||
|
}
|
||||||
|
if (isRunFromUi) {
|
||||||
|
const { app } = await import('electron')
|
||||||
|
editThisCookieZipPath = path.join(app.getAppPath(), './node_modules', packageJson.name, 'extensions', 'EditThisCookie.zip')
|
||||||
|
} else {
|
||||||
|
editThisCookieZipPath = path.join(__dirname, 'extensions', 'EditThisCookie.zip')
|
||||||
|
}
|
||||||
|
return editThisCookieZipPath
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function main() {
|
||||||
|
if (!fs.existsSync(
|
||||||
|
path.join(editThisCookieExtensionPath, 'manifest.json')
|
||||||
|
)) {
|
||||||
|
await extractZip(
|
||||||
|
await getEditThisCookieZipPath(),
|
||||||
|
{
|
||||||
|
dir: extensionDir
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { puppeteer } = await initPuppeteer()
|
||||||
|
const browser = await puppeteer.launch({
|
||||||
|
headless: false,
|
||||||
|
args: [
|
||||||
|
`--load-extension=${editThisCookieExtensionPath}`
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const closeAttachedSet = new WeakSet()
|
||||||
|
browser.on('targetcreated', async function closeNewTabs(target) {
|
||||||
|
let targetBrowser = target.browser();
|
||||||
|
const pages = await targetBrowser.pages()
|
||||||
|
console.log(pages)
|
||||||
|
for (let i = 1; i < pages.length; i++) {
|
||||||
|
const page = pages[i]
|
||||||
|
if (!closeAttachedSet.has(page)) {
|
||||||
|
closeAttachedSet.add(page)
|
||||||
|
page.once('domcontentloaded', () => {
|
||||||
|
page.close()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const [page] = await browser.pages();
|
||||||
|
|
||||||
|
page.once('close', async () => {
|
||||||
|
browser.close()
|
||||||
|
if (isRunFromUi) {
|
||||||
|
const electron = await import('electron')
|
||||||
|
electron.app.quit()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { dispose: disposeNavigationLock } = await blockNavigation(page, (req) => !req.url().startsWith('https://www.zhipin.com'))
|
||||||
|
await page.goto('https://www.zhipin.com/web/user/');
|
||||||
|
|
||||||
|
const loginSuccessPromiseList = [
|
||||||
|
page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().startsWith('https://www.zhipin.com/wapi/zppassport/qrcode/loginConfirm'),
|
||||||
|
{
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
|
),
|
||||||
|
page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().startsWith('https://www.zhipin.com/wapi/zppassport/qrcode/dispatcher'),
|
||||||
|
{
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
|
),
|
||||||
|
page.waitForResponse(
|
||||||
|
(response) =>
|
||||||
|
response.url().startsWith('https://www.zhipin.com/wapi/zppassport/login/phoneV2'),
|
||||||
|
{ timeout: 0 }
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
Promise.all([
|
||||||
|
Promise.race(loginSuccessPromiseList),
|
||||||
|
page.waitForNavigation({
|
||||||
|
timeout: 0
|
||||||
|
}),
|
||||||
|
]).then(async () => {
|
||||||
|
await sleep(2000)
|
||||||
|
const headerLogoAnchorHandler = await page.$('.header-home-logo')
|
||||||
|
return Promise.all([
|
||||||
|
headerLogoAnchorHandler ? headerLogoAnchorHandler.click() : page.goto('https://www.zhipin.com/'),
|
||||||
|
page.waitForNavigation({
|
||||||
|
timeout: 0,
|
||||||
|
})
|
||||||
|
])
|
||||||
|
}).then(async () => {
|
||||||
|
if (
|
||||||
|
page.url().startsWith('https://www.zhipin.com/web/common/security-check.html')
|
||||||
|
) {
|
||||||
|
await page.waitForNavigation({
|
||||||
|
timeout: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await sleep(2000)
|
||||||
|
const cookies = await page.cookies()
|
||||||
|
loginEventBus.emit(
|
||||||
|
'cookie-collected',
|
||||||
|
cookies
|
||||||
|
)
|
||||||
|
return writeStorageFile('boss-cookies.json', cookies)
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
+351
@@ -0,0 +1,351 @@
|
|||||||
|
{
|
||||||
|
"name": "@geekgeekrun/launch-browser-with-preload-extension",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "@geekgeekrun/launch-browser-with-preload-extension",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
|
"unzipper": "^0.10.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
|
},
|
||||||
|
"node_modules/big-integer": {
|
||||||
|
"version": "1.6.52",
|
||||||
|
"resolved": "https://registry.npmmirror.com/big-integer/-/big-integer-1.6.52.tgz",
|
||||||
|
"integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/binary": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/binary/-/binary-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffers": "~0.1.1",
|
||||||
|
"chainsaw": "~0.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bluebird": {
|
||||||
|
"version": "3.4.7",
|
||||||
|
"resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.4.7.tgz",
|
||||||
|
"integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA=="
|
||||||
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/buffer-indexof-polyfill": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/buffers": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/buffers/-/buffers-0.1.1.tgz",
|
||||||
|
"integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chainsaw": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/chainsaw/-/chainsaw-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"traverse": ">=0.3.0 <0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||||
|
},
|
||||||
|
"node_modules/core-util-is": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||||
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/duplexer2": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||||
|
"integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fetch-blob": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "^1.0.0",
|
||||||
|
"web-streams-polyfill": "^3.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20 || >= 14.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/formdata-polyfill": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmmirror.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"fetch-blob": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fs.realpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||||
|
},
|
||||||
|
"node_modules/fstream": {
|
||||||
|
"version": "1.0.12",
|
||||||
|
"resolved": "https://registry.npmmirror.com/fstream/-/fstream-1.0.12.tgz",
|
||||||
|
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"inherits": "~2.0.0",
|
||||||
|
"mkdirp": ">=0.5 0",
|
||||||
|
"rimraf": "2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/glob": {
|
||||||
|
"version": "7.2.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
|
||||||
|
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.1.1",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/graceful-fs": {
|
||||||
|
"version": "4.2.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||||
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||||
|
},
|
||||||
|
"node_modules/inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
|
},
|
||||||
|
"node_modules/isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
|
||||||
|
},
|
||||||
|
"node_modules/listenercount": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/listenercount/-/listenercount-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ=="
|
||||||
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
|
||||||
|
},
|
||||||
|
"node_modules/mkdirp": {
|
||||||
|
"version": "0.5.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||||
|
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.6"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"mkdirp": "bin/cmd.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||||
|
"dependencies": {
|
||||||
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/path-is-absolute": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/process-nextick-args": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "2.3.8",
|
||||||
|
"resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||||
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.3",
|
||||||
|
"isarray": "~1.0.0",
|
||||||
|
"process-nextick-args": "~2.0.0",
|
||||||
|
"safe-buffer": "~5.1.1",
|
||||||
|
"string_decoder": "~1.1.1",
|
||||||
|
"util-deprecate": "~1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rimraf": {
|
||||||
|
"version": "2.7.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-2.7.1.tgz",
|
||||||
|
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||||
|
"dependencies": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"rimraf": "bin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
},
|
||||||
|
"node_modules/setimmediate": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
|
||||||
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/traverse": {
|
||||||
|
"version": "0.3.9",
|
||||||
|
"resolved": "https://registry.npmmirror.com/traverse/-/traverse-0.3.9.tgz",
|
||||||
|
"integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/unzipper": {
|
||||||
|
"version": "0.10.14",
|
||||||
|
"resolved": "https://registry.npmmirror.com/unzipper/-/unzipper-0.10.14.tgz",
|
||||||
|
"integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==",
|
||||||
|
"dependencies": {
|
||||||
|
"big-integer": "^1.6.17",
|
||||||
|
"binary": "~0.3.0",
|
||||||
|
"bluebird": "~3.4.1",
|
||||||
|
"buffer-indexof-polyfill": "~1.0.0",
|
||||||
|
"duplexer2": "~0.1.4",
|
||||||
|
"fstream": "^1.0.12",
|
||||||
|
"graceful-fs": "^4.2.2",
|
||||||
|
"listenercount": "~1.0.1",
|
||||||
|
"readable-stream": "~2.3.6",
|
||||||
|
"setimmediate": "~1.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||||
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "3.3.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||||
|
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "launch-bosszhipin-login-page-with-preload-extension",
|
||||||
|
"module": "./index.mjs",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {},
|
||||||
|
"author": "geekgeekrun",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@geekgeekrun/geek-auto-start-chat-with-boss": "workspace:*",
|
||||||
|
"@geekgeekrun/utils": "workspace:*",
|
||||||
|
"extract-zip": "^2.0.1",
|
||||||
|
"node-fetch": "^3.3.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,8 @@ import fs from 'node:fs'
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { get__dirname } from '@geekgeekrun/utils/legacy-path.mjs';
|
import { get__dirname } from '@geekgeekrun/utils/legacy-path.mjs';
|
||||||
import JSON5 from 'json5'
|
import JSON5 from 'json5'
|
||||||
import { readConfigFile } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
import { readConfigFile, readStorageFile } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||||
const { cookies: bossCookies } = readConfigFile('boss.json')
|
const bossCookies = readStorageFile('boss-cookies.json')
|
||||||
const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk.json')
|
const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk.json')
|
||||||
|
|
||||||
const initPlugins = (hooks) => {
|
const initPlugins = (hooks) => {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ files:
|
|||||||
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
|
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
|
||||||
- '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}'
|
- '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}'
|
||||||
asarUnpack:
|
asarUnpack:
|
||||||
- resources/**
|
- 'resources/**'
|
||||||
|
- 'node_modules/@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension/**'
|
||||||
extraResources:
|
extraResources:
|
||||||
- external-node-runtime-dependencies/**
|
- external-node-runtime-dependencies/**
|
||||||
win:
|
win:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
externalizeDepsPlugin({
|
externalizeDepsPlugin({
|
||||||
exclude: ['@geekgeekrun/geek-auto-start-chat-with-boss', '@geekgeekrun/dingtalk-plugin', '@geekgeekrun/utils', 'find-chrome-bin']
|
exclude: ['@geekgeekrun/geek-auto-start-chat-with-boss', '@geekgeekrun/dingtalk-plugin', '@geekgeekrun/utils', 'find-chrome-bin', '@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension']
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"dev": "electron-vite dev",
|
"dev": "electron-vite dev",
|
||||||
"dev:geek-auto-start-chat-with-boss-only": "cross-env MAIN_BOSSGEEKGO_UI_RUN_MODE=geekAutoStartWithBoss electron-vite dev",
|
"dev:geek-auto-start-chat-with-boss-only": "cross-env MAIN_BOSSGEEKGO_UI_RUN_MODE=geekAutoStartWithBoss electron-vite dev",
|
||||||
"dev:check-and-download-dependencies-for-init-only": "cross-env MAIN_BOSSGEEKGO_UI_RUN_MODE=checkAndDownloadDependenciesForInit electron-vite dev",
|
"dev:check-and-download-dependencies-for-init-only": "cross-env MAIN_BOSSGEEKGO_UI_RUN_MODE=checkAndDownloadDependenciesForInit electron-vite dev",
|
||||||
|
"dev:launch-bosszhipin-login-page-with-preload-extension-only": "cross-env MAIN_BOSSGEEKGO_UI_RUN_MODE=launchBossZhipinLoginPageWithPreloadExtension electron-vite dev",
|
||||||
"build": "electron-vite build",
|
"build": "electron-vite build",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix",
|
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix",
|
||||||
@@ -19,13 +20,15 @@
|
|||||||
"build:unpack": "npm run build && electron-builder --dir",
|
"build:unpack": "npm run build && electron-builder --dir",
|
||||||
"build:win": "npm run build && electron-builder --win",
|
"build:win": "npm run build && electron-builder --win",
|
||||||
"build:mac": "npm run build && electron-builder --mac",
|
"build:mac": "npm run build && electron-builder --mac",
|
||||||
"build:linux": "npm run build && electron-builder --linux"
|
"build:linux": "npm run build && electron-builder --linux",
|
||||||
|
"install": "cd ./external-node-runtime-dependencies && cross-env PUPPETEER_SKIP_DOWNLOAD=geekAutoStartWithBoss npm install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron-toolkit/preload": "^3.0.0",
|
"@electron-toolkit/preload": "^3.0.0",
|
||||||
"@electron-toolkit/utils": "^3.0.0",
|
"@electron-toolkit/utils": "^3.0.0",
|
||||||
"@geekgeekrun/dingtalk-plugin": "workspace:*",
|
"@geekgeekrun/dingtalk-plugin": "workspace:*",
|
||||||
"@geekgeekrun/geek-auto-start-chat-with-boss": "workspace:*",
|
"@geekgeekrun/geek-auto-start-chat-with-boss": "workspace:*",
|
||||||
|
"@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension": "workspace:*",
|
||||||
"@geekgeekrun/utils": "workspace:*",
|
"@geekgeekrun/utils": "workspace:*",
|
||||||
"@puppeteer/browsers": "^2.0.0",
|
"@puppeteer/browsers": "^2.0.0",
|
||||||
"JSONStream": "^1.3.5",
|
"JSONStream": "^1.3.5",
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
export const checkCookieListFormat = (cookies: Array<Record<string, string>>) => {
|
||||||
|
const allExpectKeySet = new Set([
|
||||||
|
'name',
|
||||||
|
'value',
|
||||||
|
'domain',
|
||||||
|
'path',
|
||||||
|
'secure',
|
||||||
|
'session',
|
||||||
|
'httpOnly'
|
||||||
|
])
|
||||||
|
return Array.isArray(cookies) &&
|
||||||
|
cookies.length &&
|
||||||
|
cookies.every((it) => {
|
||||||
|
const currentOwnedKeySet = new Set(Object.keys(it))
|
||||||
|
if (currentOwnedKeySet.size < allExpectKeySet.size) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const allExpectKeyArr = [...allExpectKeySet]
|
||||||
|
for (let i = 0; i < allExpectKeyArr.length; i++) {
|
||||||
|
if (!currentOwnedKeySet.has(allExpectKeyArr[i])) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ const initPlugins = (hooks) => {
|
|||||||
let isParentProcessDisconnect = false
|
let isParentProcessDisconnect = false
|
||||||
|
|
||||||
export const runAutoChat = async () => {
|
export const runAutoChat = async () => {
|
||||||
const { initPuppeteer, mainLoop, closeBrowserWindow } = await import(
|
const { initPuppeteer, mainLoop, closeBrowserWindow, autoStartChatEventBus } = await import(
|
||||||
'@geekgeekrun/geek-auto-start-chat-with-boss/index.mjs'
|
'@geekgeekrun/geek-auto-start-chat-with-boss/index.mjs'
|
||||||
)
|
)
|
||||||
process.on('disconnect', () => {
|
process.on('disconnect', () => {
|
||||||
@@ -73,16 +73,27 @@ export const runAutoChat = async () => {
|
|||||||
type: 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED' //geek-auto-start-chat-with-boss-started
|
type: 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED' //geek-auto-start-chat-with-boss-started
|
||||||
}) + '\r\n'
|
}) + '\r\n'
|
||||||
)
|
)
|
||||||
while (!([isParentProcessDisconnect].includes(true))) {
|
|
||||||
|
autoStartChatEventBus.once('LOGIN_STATUS_INVALID', () => {
|
||||||
|
pipeWriteRegardlessError(
|
||||||
|
pipe,
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'LOGIN_STATUS_INVALID' //geek-auto-start-chat-with-boss-started
|
||||||
|
}) + '\r\n'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
while (![isParentProcessDisconnect].includes(true)) {
|
||||||
try {
|
try {
|
||||||
await mainLoop(hooks)
|
await mainLoop(hooks)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
// if(err instanceof Error && err.message.includes('ERR_MODULE_NOT_FOUND')) {
|
if (err instanceof Error && err.message.includes('LOGIN_STATUS_INVALID')) {
|
||||||
// throw err
|
process.exit(2)
|
||||||
// } else {
|
break
|
||||||
void err
|
} else {
|
||||||
// }
|
throw err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closeBrowserWindow()
|
closeBrowserWindow()
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { app } from 'electron'
|
||||||
|
import { main, loginEventBus } from '@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension'
|
||||||
|
import { pipeWriteRegardlessError } from './utils/pipe'
|
||||||
|
import fs from "node:fs";
|
||||||
|
|
||||||
|
export enum DOWNLOAD_ERROR_EXIT_CODE {
|
||||||
|
NO_ERROR = 0,
|
||||||
|
DOWNLOAD_ERROR = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export const launchBossZhipinLoginPageWithPreloadExtension = async () => {
|
||||||
|
process.on('disconnect', () => app.exit())
|
||||||
|
app.dock?.hide()
|
||||||
|
let pipe: null | fs.WriteStream = null
|
||||||
|
try {
|
||||||
|
pipe = fs.createWriteStream(null, { fd: 3 })
|
||||||
|
} catch {
|
||||||
|
console.warn('pipe is not available')
|
||||||
|
}
|
||||||
|
pipeWriteRegardlessError(
|
||||||
|
pipe,
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'INITIALIZE_PUPPETEER'
|
||||||
|
}) + '\r\n'
|
||||||
|
)
|
||||||
|
const { initPuppeteer } = await import('@geekgeekrun/geek-auto-start-chat-with-boss/index.mjs')
|
||||||
|
try {
|
||||||
|
await initPuppeteer()
|
||||||
|
pipeWriteRegardlessError(
|
||||||
|
pipe,
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'PUPPETEER_INITIALIZE_SUCCESSFULLY'
|
||||||
|
}) + '\r\n'
|
||||||
|
)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
app.exit(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loginEventBus.once('cookie-collected', (cookies) => {
|
||||||
|
pipeWriteRegardlessError(
|
||||||
|
pipe,
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'BOSS_ZHIPIN_COOKIE_COLLECTED',
|
||||||
|
cookies
|
||||||
|
}) + '\r\n'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
main()
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { runAutoChat } from './flow/GEEK_AUTO_START_CHAT_WITH_BOSS'
|
import { runAutoChat } from './flow/GEEK_AUTO_START_CHAT_WITH_BOSS'
|
||||||
import { openSettingWindow } from './flow/OPEN_SETTING_WINDOW'
|
import { openSettingWindow } from './flow/OPEN_SETTING_WINDOW'
|
||||||
import { checkAndDownloadDependenciesForInit } from './flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/index';
|
import { checkAndDownloadDependenciesForInit } from './flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/index'
|
||||||
|
import { launchBossZhipinLoginPageWithPreloadExtension } from './flow/LAUNCH_BOSS_ZHIPIN_LOGIN_PAGE_WITH_PRELOAD_EXTENSION'
|
||||||
|
|
||||||
const runMode = process.env.MAIN_BOSSGEEKGO_UI_RUN_MODE
|
const runMode = process.env.MAIN_BOSSGEEKGO_UI_RUN_MODE
|
||||||
switch (runMode) {
|
switch (runMode) {
|
||||||
@@ -12,6 +13,10 @@ switch (runMode) {
|
|||||||
checkAndDownloadDependenciesForInit()
|
checkAndDownloadDependenciesForInit()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case 'launchBossZhipinLoginPageWithPreloadExtension': {
|
||||||
|
launchBossZhipinLoginPageWithPreloadExtension()
|
||||||
|
break
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
openSettingWindow()
|
openSettingWindow()
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -3,17 +3,23 @@ import path from 'path'
|
|||||||
import * as childProcess from 'node:child_process'
|
import * as childProcess from 'node:child_process'
|
||||||
import { is } from '@electron-toolkit/utils'
|
import { is } from '@electron-toolkit/utils'
|
||||||
import {
|
import {
|
||||||
readConfigFile,
|
|
||||||
configFileNameList,
|
|
||||||
ensureConfigFileExist,
|
ensureConfigFileExist,
|
||||||
writeConfigFile
|
ensureStorageFileExist,
|
||||||
|
|
||||||
|
configFileNameList,
|
||||||
|
readConfigFile,
|
||||||
|
writeConfigFile,
|
||||||
|
readStorageFile,
|
||||||
|
writeStorageFile
|
||||||
} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||||
import { ChildProcess } from 'child_process'
|
import { ChildProcess } from 'child_process'
|
||||||
import * as JSONStream from 'JSONStream'
|
import * as JSONStream from 'JSONStream'
|
||||||
|
import { checkCookieListFormat } from '../../common/utils/cookie'
|
||||||
import {
|
import {
|
||||||
DOWNLOAD_ERROR_EXIT_CODE,
|
DOWNLOAD_ERROR_EXIT_CODE,
|
||||||
getAnyAvailablePuppeteerExecutable
|
getAnyAvailablePuppeteerExecutable
|
||||||
} from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES'
|
} from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES'
|
||||||
|
import { sleep } from '@geekgeekrun/utils/sleep.mjs'
|
||||||
let mainWindow: BrowserWindow | null = null
|
let mainWindow: BrowserWindow | null = null
|
||||||
|
|
||||||
export function createMainWindow(): void {
|
export function createMainWindow(): void {
|
||||||
@@ -25,8 +31,8 @@ export function createMainWindow(): void {
|
|||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
...(process.platform === 'linux'
|
...(process.platform === 'linux'
|
||||||
? {
|
? {
|
||||||
/* icon */
|
/* icon */
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: path.join(__dirname, '../preload/index.js'),
|
preload: path.join(__dirname, '../preload/index.js'),
|
||||||
@@ -53,15 +59,24 @@ export function createMainWindow(): void {
|
|||||||
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'))
|
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipcMain.on('open-external-link', (_, link) => {
|
||||||
|
shell.openExternal(link, {
|
||||||
|
activate: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
ipcMain.handle('fetch-config-file-content', async () => {
|
ipcMain.handle('fetch-config-file-content', async () => {
|
||||||
const fileContentList = configFileNameList.map((fileName) => {
|
const configFileContentList = configFileNameList.map((fileName) => {
|
||||||
return readConfigFile(fileName)
|
return readConfigFile(fileName)
|
||||||
})
|
})
|
||||||
const result = {}
|
const result = {
|
||||||
|
config: {},
|
||||||
|
}
|
||||||
|
|
||||||
configFileNameList.forEach((fileName, index) => {
|
configFileNameList.forEach((fileName, index) => {
|
||||||
result[fileName] = fileContentList[index]
|
result.config[fileName] = configFileContentList[index]
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -72,16 +87,23 @@ export function createMainWindow(): void {
|
|||||||
const dingtalkConfig = readConfigFile('dingtalk.json')
|
const dingtalkConfig = readConfigFile('dingtalk.json')
|
||||||
dingtalkConfig.groupRobotAccessToken = payload.dingtalkRobotAccessToken
|
dingtalkConfig.groupRobotAccessToken = payload.dingtalkRobotAccessToken
|
||||||
|
|
||||||
const bossZhipinConfig = readConfigFile('boss.json')
|
|
||||||
bossZhipinConfig.cookies = JSON.parse(payload.bossZhipinCookies)
|
|
||||||
|
|
||||||
return await Promise.all([
|
return await Promise.all([
|
||||||
writeConfigFile('boss.json', bossZhipinConfig),
|
|
||||||
writeConfigFile('dingtalk.json', dingtalkConfig),
|
writeConfigFile('dingtalk.json', dingtalkConfig),
|
||||||
writeConfigFile('target-company-list.json', payload.expectCompanies.split(','))
|
writeConfigFile('target-company-list.json', payload.expectCompanies.split(','))
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('read-storage-file', async (ev, payload) => {
|
||||||
|
ensureStorageFileExist()
|
||||||
|
return await readStorageFile(payload.fileName)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('write-storage-file', async (ev, payload) => {
|
||||||
|
ensureStorageFileExist()
|
||||||
|
|
||||||
|
return await writeStorageFile(payload.fileName, JSON.parse(payload.data))
|
||||||
|
})
|
||||||
|
|
||||||
// const currentExecutablePath = app.getPath('exe')
|
// const currentExecutablePath = app.getPath('exe')
|
||||||
// console.log(currentExecutablePath)
|
// console.log(currentExecutablePath)
|
||||||
|
|
||||||
@@ -102,13 +124,18 @@ export function createMainWindow(): void {
|
|||||||
})
|
})
|
||||||
console.log(subProcessOfPuppeteer)
|
console.log(subProcessOfPuppeteer)
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', (raw) => {
|
subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => {
|
||||||
const data = raw
|
const data = raw
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': {
|
case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': {
|
||||||
resolve(data)
|
resolve(data)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case 'LOGIN_STATUS_INVALID': {
|
||||||
|
await sleep(500)
|
||||||
|
mainWindow?.webContents.send('check-boss-zhipin-cookie-file')
|
||||||
|
return
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -195,11 +222,62 @@ export function createMainWindow(): void {
|
|||||||
mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopping')
|
mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopping')
|
||||||
subProcessOfPuppeteer?.kill('SIGINT')
|
subProcessOfPuppeteer?.kill('SIGINT')
|
||||||
})
|
})
|
||||||
ipcMain.on('open-project-homepage-on-github', () => {
|
|
||||||
shell.openExternal(`https://github.com/geekgeekrun`, {
|
let subProcessOfBossZhipinLoginPageWithPreloadExtension: ChildProcess | null = null
|
||||||
activate: true
|
ipcMain.on('launch-bosszhipin-login-page-with-preload-extension', async () => {
|
||||||
|
try {
|
||||||
|
subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill()
|
||||||
|
} catch {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
const subProcessEnv = {
|
||||||
|
...process.env,
|
||||||
|
MAIN_BOSSGEEKGO_UI_RUN_MODE: 'launchBossZhipinLoginPageWithPreloadExtension',
|
||||||
|
PUPPETEER_EXECUTABLE_PATH: (await getAnyAvailablePuppeteerExecutable())!.executablePath
|
||||||
|
}
|
||||||
|
subProcessOfBossZhipinLoginPageWithPreloadExtension = childProcess.spawn(
|
||||||
|
process.argv[0],
|
||||||
|
process.argv.slice(1),
|
||||||
|
{
|
||||||
|
env: subProcessEnv,
|
||||||
|
stdio: [null, null, null, 'pipe', 'ipc']
|
||||||
|
}
|
||||||
|
)
|
||||||
|
subProcessOfBossZhipinLoginPageWithPreloadExtension!.stdio[3]!.pipe(JSONStream.parse()).on(
|
||||||
|
'data',
|
||||||
|
(raw) => {
|
||||||
|
const data = raw
|
||||||
|
switch (data.type) {
|
||||||
|
case 'BOSS_ZHIPIN_COOKIE_COLLECTED': {
|
||||||
|
mainWindow?.webContents.send(data.type, data)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
subProcessOfBossZhipinLoginPageWithPreloadExtension!.once('exit', () => {
|
||||||
|
mainWindow?.webContents.send('BOSS_ZHIPIN_LOGIN_PAGE_CLOSED')
|
||||||
|
subProcessOfBossZhipinLoginPageWithPreloadExtension = null
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
ipcMain.on('kill-bosszhipin-login-page-with-preload-extension', async () => {
|
||||||
|
try {
|
||||||
|
subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill()
|
||||||
|
} catch {
|
||||||
|
//
|
||||||
|
} finally {
|
||||||
|
subProcessOfBossZhipinLoginPageWithPreloadExtension = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('check-boss-zhipin-cookie-file', () => {
|
||||||
|
const cookies = readStorageFile('boss-cookies.json')
|
||||||
|
return checkCookieListFormat(cookies)
|
||||||
|
})
|
||||||
|
|
||||||
mainWindow!.once('closed', () => {
|
mainWindow!.once('closed', () => {
|
||||||
mainWindow = null
|
mainWindow = null
|
||||||
|
|||||||
+3
-1
@@ -26,7 +26,8 @@ const props = defineProps({
|
|||||||
dependenciesStatus: {
|
dependenciesStatus: {
|
||||||
type: Object as PropType<Record<string, boolean>>,
|
type: Object as PropType<Record<string, boolean>>,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
}
|
},
|
||||||
|
processWaitee: Object
|
||||||
})
|
})
|
||||||
|
|
||||||
// shallow copy
|
// shallow copy
|
||||||
@@ -75,6 +76,7 @@ const processTasks = async () => {
|
|||||||
try {
|
try {
|
||||||
p.then(() => {
|
p.then(() => {
|
||||||
if (!promiseList.length) {
|
if (!promiseList.length) {
|
||||||
|
props.processWaitee?.resolve?.()
|
||||||
props.dispose?.()
|
props.dispose?.()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+3
-2
@@ -2,7 +2,7 @@ import { createApp } from 'vue'
|
|||||||
import ElementPlus from 'element-plus'
|
import ElementPlus from 'element-plus'
|
||||||
import DependenciesSetupProgressIndicatorDialog from './index.vue'
|
import DependenciesSetupProgressIndicatorDialog from './index.vue'
|
||||||
|
|
||||||
export const mountGlobalDialog = (dependenciesStatus: Record<string, boolean>) => {
|
export const mountGlobalDialog = (o: { dependenciesStatus: Record<string, boolean>, processWaitee? }) => {
|
||||||
const containerElId = `elForDependenciesSetupProgressIndicatorDialog`
|
const containerElId = `elForDependenciesSetupProgressIndicatorDialog`
|
||||||
|
|
||||||
if (document.getElementById(containerElId)) {
|
if (document.getElementById(containerElId)) {
|
||||||
@@ -28,7 +28,8 @@ export const mountGlobalDialog = (dependenciesStatus: Record<string, boolean>) =
|
|||||||
dispose()
|
dispose()
|
||||||
},
|
},
|
||||||
dispose,
|
dispose,
|
||||||
dependenciesStatus
|
dependenciesStatus: o?.dependenciesStatus,
|
||||||
|
processWaitee: o?.processWaitee
|
||||||
}).use(ElementPlus)
|
}).use(ElementPlus)
|
||||||
app.mount(containerEl)
|
app.mount(containerEl)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,245 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-bind="$attrs"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="!cookieInvalid"
|
||||||
|
title="Boss直聘 Cookie助手"
|
||||||
|
:width="720"
|
||||||
|
top="20px"
|
||||||
|
lock-scroll
|
||||||
|
:show-close="!cookieInvalid"
|
||||||
|
>
|
||||||
|
<el-alert
|
||||||
|
v-if="cookieInvalid"
|
||||||
|
type="warning"
|
||||||
|
:closable="false"
|
||||||
|
title="需要获取您的Boss直聘Cookie才能继续"
|
||||||
|
>
|
||||||
|
由于您是首次使用本程序,或者您之前使用的Boss直聘账号登录状态失效,因此您需要重新获取登录凭证。
|
||||||
|
</el-alert>
|
||||||
|
<div ml1em mt1em line-height-normal>
|
||||||
|
如果您了解如何获取Cookie、了解有效的Cookie格式,可以直接在下方输入框中进行编辑。<br />
|
||||||
|
手动编辑较为麻烦,建议您打开已登录过Boss直聘的浏览器,使用
|
||||||
|
<a
|
||||||
|
color-blue
|
||||||
|
decoration-none
|
||||||
|
href="javascript:void(0)"
|
||||||
|
@click.prevent="handleEditThisCookieExtensionStoreLinkClick"
|
||||||
|
>EditThisCookie 扩展程序</a
|
||||||
|
>
|
||||||
|
复制Cookie,然后粘贴在下方输入框中。<br />
|
||||||
|
格式为被序列化为JSON的数组,不含两侧引号。
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div ml1em line-height-normal>
|
||||||
|
如果您不了解Cookie相关概念,或者不能访问Chrome扩展程序商店下载EditThisCookie来获取Cookie,请按照以下步骤进行操作:
|
||||||
|
</div>
|
||||||
|
<ol lh-2em mt-0>
|
||||||
|
<li>
|
||||||
|
<el-button size="small" type="primary" font-size-inherit @click="handleClickLaunchLogin"
|
||||||
|
>点击此处</el-button
|
||||||
|
>
|
||||||
|
启动浏览器
|
||||||
|
</li>
|
||||||
|
<li>按照正常流程,通过 <b>短信验证码/二维码/微信小程序</b> 登录您的Boss直聘账号</li>
|
||||||
|
<li>接下来将自动进行一些页面跳转,最终将会停留在首页</li>
|
||||||
|
<li>
|
||||||
|
登录后预计5-10秒内(具体取决于您的网速),您的Cookie将被自动填入下方输入框。
|
||||||
|
<details>
|
||||||
|
<summary color-orange cursor-pointer>我已完成登录,但Cookie一直没出现?</summary>
|
||||||
|
<div ml-2em max-h-200px of-auto>
|
||||||
|
如果您确实已经在打开浏览器中看到您已登录了Boss直聘,请尝试按照如图所示方式复制Cookie:
|
||||||
|
<figure>
|
||||||
|
<figcaption>依次点击浏览器右上角“扩展程序”图标、“EditThisCookie”图标</figcaption>
|
||||||
|
<img block max-w-full src="./resources/copy-cookie-step-1.png" />
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<figcaption>点击“EditThisCookie”弹出框中的“Export”按钮</figcaption>
|
||||||
|
<img block max-w-full src="./resources/copy-cookie-step-2.png" />
|
||||||
|
</figure>
|
||||||
|
<figure>
|
||||||
|
<figcaption>在下方输入框执行粘贴操作。</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
inline-message
|
||||||
|
:model="formContent"
|
||||||
|
label-position="top"
|
||||||
|
:rules="formRules"
|
||||||
|
class="cookie-form"
|
||||||
|
>
|
||||||
|
<el-form-item prop="collectedCookies" mb-0>
|
||||||
|
<el-input
|
||||||
|
v-model="formContent.collectedCookies"
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{
|
||||||
|
minRows: 10,
|
||||||
|
maxRows: 10
|
||||||
|
}"
|
||||||
|
font-size-12px
|
||||||
|
@input="hasUserMutateInput = true"
|
||||||
|
></el-input>
|
||||||
|
<el-alert
|
||||||
|
v-if="loginCookieWaitingStatus === LOGIN_COOKIE_WAITING_STATUS.WAITING_FOR_LOGIN"
|
||||||
|
:closable="false"
|
||||||
|
>正在等待登录……</el-alert
|
||||||
|
>
|
||||||
|
<el-alert
|
||||||
|
v-if="loginCookieWaitingStatus === LOGIN_COOKIE_WAITING_STATUS.COOKIE_COLLECTED"
|
||||||
|
:closable="false"
|
||||||
|
type="success"
|
||||||
|
>已获取到Cookie<template v-if="hasUserMutateInput"
|
||||||
|
>;看起来您似乎正在尝试手动输入Cookie?<el-button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
font-size-inherit
|
||||||
|
@click="fillCollectedCookie"
|
||||||
|
>使用获取到的Cookie</el-button
|
||||||
|
></template
|
||||||
|
></el-alert
|
||||||
|
>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button v-if="!cookieInvalid" @click="dispose">关闭</el-button>
|
||||||
|
<el-button type="primary" @click="handleSubmit">保存Cookie</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ElForm, ElMessage } from 'element-plus'
|
||||||
|
import { ref, onUnmounted, onMounted } from 'vue'
|
||||||
|
import { checkCookieListFormat } from '../../../../common/utils/cookie'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
dispose: Function,
|
||||||
|
processWaitee: Object
|
||||||
|
})
|
||||||
|
|
||||||
|
const cookieInvalid = ref(false)
|
||||||
|
|
||||||
|
enum LOGIN_COOKIE_WAITING_STATUS {
|
||||||
|
INIT,
|
||||||
|
WAITING_FOR_LOGIN,
|
||||||
|
COOKIE_COLLECTED
|
||||||
|
}
|
||||||
|
const loginCookieWaitingStatus = ref(LOGIN_COOKIE_WAITING_STATUS.INIT)
|
||||||
|
|
||||||
|
const formRef = ref<InstanceType<typeof ElForm>>()
|
||||||
|
const formContent = ref({
|
||||||
|
collectedCookies: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRules = {
|
||||||
|
collectedCookies: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入Cookie'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
trigger: 'blur',
|
||||||
|
validator(rule, val, cb) {
|
||||||
|
let arr
|
||||||
|
try {
|
||||||
|
arr = JSON.parse(val)
|
||||||
|
} catch (err) {
|
||||||
|
cb(
|
||||||
|
new Error(
|
||||||
|
`JSON格式无效 - 存在语法错误: ${err.message};建议使用EditThisCookie扩展程序进行复制。`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkCookieListFormat(JSON.parse(formContent.value.collectedCookies))) {
|
||||||
|
cb(new Error(`Cookie格式无效 - 部分字段缺失;建议使用EditThisCookie扩展程序进行复制。`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasUserMutateInput = ref(false)
|
||||||
|
const collectedCookie = ref()
|
||||||
|
const handleCookieCollected = (_, payload) => {
|
||||||
|
loginCookieWaitingStatus.value = LOGIN_COOKIE_WAITING_STATUS.COOKIE_COLLECTED
|
||||||
|
collectedCookie.value = payload.cookies
|
||||||
|
if (!hasUserMutateInput.value) {
|
||||||
|
fillCollectedCookie()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const fillCollectedCookie = () => {
|
||||||
|
if (loginCookieWaitingStatus.value !== LOGIN_COOKIE_WAITING_STATUS.COOKIE_COLLECTED) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formContent.value.collectedCookies = JSON.stringify(collectedCookie.value, null, 2)
|
||||||
|
hasUserMutateInput.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClickLaunchLogin = () => {
|
||||||
|
electron.ipcRenderer.send('launch-bosszhipin-login-page-with-preload-extension')
|
||||||
|
loginCookieWaitingStatus.value = LOGIN_COOKIE_WAITING_STATUS.WAITING_FOR_LOGIN
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEditThisCookieExtensionStoreLinkClick = () => {
|
||||||
|
electron.ipcRenderer.send(
|
||||||
|
'open-external-link',
|
||||||
|
'https://chromewebstore.google.com/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
await formRef.value!.validate()
|
||||||
|
await electron.ipcRenderer.invoke('write-storage-file', {
|
||||||
|
fileName: 'boss-cookies.json',
|
||||||
|
data: formContent.value.collectedCookies
|
||||||
|
})
|
||||||
|
ElMessage.success('Boss直聘 Cookie 保存成功')
|
||||||
|
props.processWaitee?.resolve?.()
|
||||||
|
props.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleBossZhipinLoginPageClosed = () => {
|
||||||
|
if (loginCookieWaitingStatus.value === LOGIN_COOKIE_WAITING_STATUS.WAITING_FOR_LOGIN) {
|
||||||
|
loginCookieWaitingStatus.value = LOGIN_COOKIE_WAITING_STATUS.INIT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
electron.ipcRenderer.once('BOSS_ZHIPIN_COOKIE_COLLECTED', handleCookieCollected)
|
||||||
|
electron.ipcRenderer.on('BOSS_ZHIPIN_LOGIN_PAGE_CLOSED', handleBossZhipinLoginPageClosed)
|
||||||
|
|
||||||
|
const cookieFileContent = await electron.ipcRenderer.invoke('read-storage-file', {
|
||||||
|
fileName: 'boss-cookies.json'
|
||||||
|
})
|
||||||
|
if (checkCookieListFormat(cookieFileContent)) {
|
||||||
|
formContent.value.collectedCookies = JSON.stringify(cookieFileContent, null, 2)
|
||||||
|
} else {
|
||||||
|
cookieInvalid.value = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
electron.ipcRenderer.removeListener('BOSS_ZHIPIN_COOKIE_COLLECTED', handleCookieCollected)
|
||||||
|
electron.ipcRenderer.removeListener(
|
||||||
|
'BOSS_ZHIPIN_LOGIN_PAGE_CLOSED',
|
||||||
|
handleBossZhipinLoginPageClosed
|
||||||
|
)
|
||||||
|
electron.ipcRenderer.send('kill-bosszhipin-login-page-with-preload-extension')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.cookie-form.el-form {
|
||||||
|
.el-form-item__error--inline {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import ElementPlus from 'element-plus'
|
||||||
|
import WaitForLogin from './index.vue'
|
||||||
|
|
||||||
|
export const mountGlobalDialog = (o: { processWaitee? }) => {
|
||||||
|
const containerElId = `elForWaitForLogin`
|
||||||
|
|
||||||
|
if (document.getElementById(containerElId)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let containerEl: null | HTMLElement = (() => {
|
||||||
|
const el = document.createElement('div')
|
||||||
|
el.id = containerElId
|
||||||
|
return el
|
||||||
|
})()
|
||||||
|
document.body.append(containerEl)
|
||||||
|
|
||||||
|
const dispose = () => {
|
||||||
|
app?.unmount()
|
||||||
|
containerEl?.remove()
|
||||||
|
|
||||||
|
app = null
|
||||||
|
containerEl = null
|
||||||
|
}
|
||||||
|
let app: null | ReturnType<typeof createApp> = createApp(WaitForLogin, {
|
||||||
|
modelValue: true,
|
||||||
|
onClosed() {
|
||||||
|
dispose()
|
||||||
|
},
|
||||||
|
dispose,
|
||||||
|
processWaitee: o?.processWaitee
|
||||||
|
}).use(ElementPlus)
|
||||||
|
app.mount(containerEl)
|
||||||
|
|
||||||
|
return {
|
||||||
|
dispose
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
@@ -1,15 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="form-wrap">
|
<div class="form-wrap">
|
||||||
<el-form ref="formRef" :model="formContent" label-position="top" :rules="formRules">
|
<el-form ref="formRef" :model="formContent" label-position="top" :rules="formRules">
|
||||||
<el-form-item
|
<el-form-item label="BOSS直聘 Cookie">
|
||||||
label="BOSS直聘 Cookie (使用EditThisCookie扩展程序,从你已登录过BOSS直聘的浏览器复制)"
|
<el-button size="small" type="primary" font-size-inherit @click="handleClickLaunchLogin"
|
||||||
prop="bossZhipinCookies"
|
>编辑Cookie</el-button
|
||||||
>
|
>
|
||||||
<el-input
|
|
||||||
v-model="formContent.bossZhipinCookies"
|
|
||||||
:autosize="{ minRows: 4 }"
|
|
||||||
type="textarea"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="钉钉机器人 AccessToken" prop="dingtalkRobotAccessToken">
|
<el-form-item label="钉钉机器人 AccessToken" prop="dingtalkRobotAccessToken">
|
||||||
<el-input v-model="formContent.dingtalkRobotAccessToken" />
|
<el-input v-model="formContent.dingtalkRobotAccessToken" />
|
||||||
@@ -32,47 +27,23 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import JSON5 from 'json5'
|
|
||||||
import { ElForm, ElMessage } from 'element-plus'
|
import { ElForm, ElMessage } from 'element-plus'
|
||||||
import router from '../../router/index'
|
import router from '../../router/index'
|
||||||
import { mountGlobalDialog as mountDependenciesSetupProgressIndicatorDialog } from '@renderer/features/DependenciesSetupProgressIndicatorDialog/operations'
|
import { mountGlobalDialog as mountDependenciesSetupProgressIndicatorDialog } from '@renderer/features/DependenciesSetupProgressIndicatorDialog/operations'
|
||||||
|
import { mountGlobalDialog as mountWaitForLoginDialog } from '@renderer/features/WaitForLoginDialog/operations'
|
||||||
|
|
||||||
const formContent = ref({
|
const formContent = ref({
|
||||||
bossZhipinCookies: '',
|
|
||||||
dingtalkRobotAccessToken: '',
|
dingtalkRobotAccessToken: '',
|
||||||
expectCompanies: ''
|
expectCompanies: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
electron.ipcRenderer.invoke('fetch-config-file-content').then((res) => {
|
electron.ipcRenderer.invoke('fetch-config-file-content').then((res) => {
|
||||||
console.log(res)
|
console.log(res)
|
||||||
formContent.value.bossZhipinCookies = JSON.stringify(res['boss.json'].cookies, null, 2)
|
formContent.value.dingtalkRobotAccessToken = res.config['dingtalk.json']['groupRobotAccessToken']
|
||||||
formContent.value.dingtalkRobotAccessToken = res['dingtalk.json']['groupRobotAccessToken']
|
formContent.value.expectCompanies = res.config['target-company-list.json'].join(',')
|
||||||
formContent.value.expectCompanies = res['target-company-list.json'].join(',')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const formRules = {
|
const formRules = {
|
||||||
bossZhipinCookies: [
|
|
||||||
{
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
trigger: 'blur',
|
|
||||||
validator(rule, val, cb) {
|
|
||||||
let arr
|
|
||||||
try {
|
|
||||||
arr = JSON5.parse(val)
|
|
||||||
} catch (err) {
|
|
||||||
cb(new Error(`JSON content is invalid: ${err.message}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!Array.isArray(arr) || !arr.length) {
|
|
||||||
cb(new Error(`Invalid cookies. Please copy with EditThisCookie extension`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const formRef = ref<InstanceType<typeof ElForm>>()
|
const formRef = ref<InstanceType<typeof ElForm>>()
|
||||||
@@ -116,11 +87,15 @@ const handleExpectCompaniesInputBlur = (event) => {
|
|||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(',')
|
.join(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleClickLaunchLogin = () => {
|
||||||
|
mountWaitForLoginDialog()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.form-wrap {
|
.form-wrap {
|
||||||
padding-top: 100px;
|
padding-top: 60px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
.last-form-item {
|
.last-form-item {
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<template><RouterView /></template>
|
<template><RouterView /></template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onUnmounted } from 'vue'
|
import { onMounted, onUnmounted } from 'vue'
|
||||||
import { mountGlobalDialog as mountDependenciesSetupProgressIndicatorDialog } from '@renderer/features/DependenciesSetupProgressIndicatorDialog/operations'
|
import { mountGlobalDialog as mountDependenciesSetupProgressIndicatorDialog } from '@renderer/features/DependenciesSetupProgressIndicatorDialog/operations'
|
||||||
|
import { mountGlobalDialog as mountWaitForLoginDialog } from '@renderer/features/WaitForLoginDialog/operations'
|
||||||
|
|
||||||
const unmountedCbs: Array<InstanceType<typeof Function>> = []
|
const unmountedCbs: Array<InstanceType<typeof Function>> = []
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
@@ -13,10 +14,31 @@ onUnmounted(() => {
|
|||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
onMounted(() => {
|
||||||
|
electron.ipcRenderer.on('check-boss-zhipin-cookie-file', mountWaitForLoginDialog)
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
electron.ipcRenderer.removeListener('check-boss-zhipin-cookie-file', mountWaitForLoginDialog)
|
||||||
|
})
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const checkDependenciesResult = await electron.ipcRenderer.invoke('check-dependencies')
|
const checkDependenciesResult = await electron.ipcRenderer.invoke('check-dependencies')
|
||||||
if (Object.values(checkDependenciesResult).includes(false)) {
|
if (Object.values(checkDependenciesResult).includes(false)) {
|
||||||
mountDependenciesSetupProgressIndicatorDialog(checkDependenciesResult)
|
const processWaitee = Promise.withResolvers()
|
||||||
|
mountDependenciesSetupProgressIndicatorDialog({
|
||||||
|
checkDependenciesResult, processWaitee
|
||||||
|
})
|
||||||
|
|
||||||
|
await processWaitee.promise
|
||||||
|
}
|
||||||
|
|
||||||
|
const isCookieFileValid = await electron.ipcRenderer.invoke('check-boss-zhipin-cookie-file')
|
||||||
|
if (!isCookieFileValid) {
|
||||||
|
const processWaitee = Promise.withResolvers()
|
||||||
|
mountWaitForLoginDialog({
|
||||||
|
processWaitee
|
||||||
|
})
|
||||||
|
|
||||||
|
await processWaitee.promise
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
html, body {
|
html, body {
|
||||||
--monospace-font-family: Monaco, Consolas, Menlo, monospace;
|
--monospace-font-family: Monaco, Consolas, Menlo;
|
||||||
font-family: var(--monospace-font-family);
|
--sans-serif-font-family: 'PingFang SC', 'Microsoft Yahei', Helvetica, Arial;
|
||||||
|
font-family: var(--monospace-font-family), var(--sans-serif-font-family);
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
export async function blockNavigation(page, predictor = (url) => true) {
|
||||||
|
console.log(`block navigation for puppeteer page from url ${page.url()}`)
|
||||||
|
await page.setRequestInterception(true)
|
||||||
|
|
||||||
|
const handler = (req) => {
|
||||||
|
if (req.isNavigationRequest() && req.frame() === page.mainFrame() && predictor(req)) {
|
||||||
|
req.abort('aborted')
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
req.continue()
|
||||||
|
} catch {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
page.on('request', handler)
|
||||||
|
|
||||||
|
return {
|
||||||
|
dispose: async () => {
|
||||||
|
page.off('request', handler)
|
||||||
|
await page.setRequestInterception(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export const setDomainLocalStorage = async (browser, url, kv) => {
|
||||||
|
const page = await browser.newPage();
|
||||||
|
await page.setRequestInterception(true);
|
||||||
|
page.on('request', r => {
|
||||||
|
r.respond({
|
||||||
|
status: 200,
|
||||||
|
contentType: 'text/plain',
|
||||||
|
body: ':)',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await page.goto(url);
|
||||||
|
await page.evaluate(kv => {
|
||||||
|
Object.keys(kv).forEach(k => {
|
||||||
|
localStorage.setItem(k, kv[k]);
|
||||||
|
})
|
||||||
|
}, kv);
|
||||||
|
await page.close();
|
||||||
|
};
|
||||||
Generated
+62
-5
@@ -1,9 +1,5 @@
|
|||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
|
||||||
autoInstallPeers: true
|
|
||||||
excludeLinksFromLockfile: false
|
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
@@ -35,6 +31,21 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../utils
|
version: link:../utils
|
||||||
|
|
||||||
|
packages/launch-bosszhipin-login-page-with-preload-extension:
|
||||||
|
dependencies:
|
||||||
|
'@geekgeekrun/geek-auto-start-chat-with-boss':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../geek-auto-start-chat-with-boss
|
||||||
|
'@geekgeekrun/utils':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../utils
|
||||||
|
extract-zip:
|
||||||
|
specifier: ^2.0.1
|
||||||
|
version: 2.0.1
|
||||||
|
node-fetch:
|
||||||
|
specifier: ^3.3.2
|
||||||
|
version: 3.3.2
|
||||||
|
|
||||||
packages/run-core-of-geek-auto-start-chat-with-boss:
|
packages/run-core-of-geek-auto-start-chat-with-boss:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@geekgeekrun/dingtalk-plugin':
|
'@geekgeekrun/dingtalk-plugin':
|
||||||
@@ -61,6 +72,9 @@ importers:
|
|||||||
'@geekgeekrun/geek-auto-start-chat-with-boss':
|
'@geekgeekrun/geek-auto-start-chat-with-boss':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../geek-auto-start-chat-with-boss
|
version: link:../geek-auto-start-chat-with-boss
|
||||||
|
'@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../launch-bosszhipin-login-page-with-preload-extension
|
||||||
'@geekgeekrun/utils':
|
'@geekgeekrun/utils':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../utils
|
version: link:../utils
|
||||||
@@ -1271,7 +1285,7 @@ packages:
|
|||||||
/@types/fs-extra@9.0.13:
|
/@types/fs-extra@9.0.13:
|
||||||
resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
|
resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 18.19.9
|
'@types/node': 18.19.15
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/http-cache-semantics@4.0.4:
|
/@types/http-cache-semantics@4.0.4:
|
||||||
@@ -2460,6 +2474,11 @@ packages:
|
|||||||
/csstype@3.1.3:
|
/csstype@3.1.3:
|
||||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||||
|
|
||||||
|
/data-uri-to-buffer@4.0.1:
|
||||||
|
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/data-uri-to-buffer@6.0.1:
|
/data-uri-to-buffer@6.0.1:
|
||||||
resolution: {integrity: sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==}
|
resolution: {integrity: sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==}
|
||||||
engines: {node: '>= 14'}
|
engines: {node: '>= 14'}
|
||||||
@@ -3077,6 +3096,14 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pend: 1.2.0
|
pend: 1.2.0
|
||||||
|
|
||||||
|
/fetch-blob@3.2.0:
|
||||||
|
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
|
||||||
|
engines: {node: ^12.20 || >= 14.13}
|
||||||
|
dependencies:
|
||||||
|
node-domexception: 1.0.0
|
||||||
|
web-streams-polyfill: 3.3.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/file-entry-cache@6.0.1:
|
/file-entry-cache@6.0.1:
|
||||||
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
||||||
engines: {node: ^10.12.0 || >=12.0.0}
|
engines: {node: ^10.12.0 || >=12.0.0}
|
||||||
@@ -3161,6 +3188,13 @@ packages:
|
|||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/formdata-polyfill@4.0.10:
|
||||||
|
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
|
||||||
|
engines: {node: '>=12.20.0'}
|
||||||
|
dependencies:
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fs-constants@1.0.0:
|
/fs-constants@1.0.0:
|
||||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -4018,6 +4052,11 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/node-domexception@1.0.0:
|
||||||
|
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||||
|
engines: {node: '>=10.5.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/node-fetch-native@1.6.2:
|
/node-fetch-native@1.6.2:
|
||||||
resolution: {integrity: sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==}
|
resolution: {integrity: sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -4034,6 +4073,15 @@ packages:
|
|||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/node-fetch@3.3.2:
|
||||||
|
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
|
||||||
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
dependencies:
|
||||||
|
data-uri-to-buffer: 4.0.1
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
formdata-polyfill: 4.0.10
|
||||||
|
dev: false
|
||||||
|
|
||||||
/node-releases@2.0.14:
|
/node-releases@2.0.14:
|
||||||
resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
|
resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -5286,6 +5334,11 @@ packages:
|
|||||||
'@vue/shared': 3.4.15
|
'@vue/shared': 3.4.15
|
||||||
typescript: 5.3.3
|
typescript: 5.3.3
|
||||||
|
|
||||||
|
/web-streams-polyfill@3.3.3:
|
||||||
|
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/webidl-conversions@3.0.1:
|
/webidl-conversions@3.0.1:
|
||||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -5408,3 +5461,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|||||||
Reference in New Issue
Block a user