mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-05-31 21:21:15 +08:00
Merge branch 'feature/ui-use-users-own-browser' into feature/ui
This commit is contained in:
@@ -9,12 +9,12 @@ export default defineConfig({
|
||||
main: {
|
||||
build: {
|
||||
rollupOptions: {
|
||||
external: ['puppeteer', 'puppeteer-extra', 'puppeteer-extra-plugin-stealth', '@puppeteer/browsers']
|
||||
external: ['puppeteer', 'puppeteer-extra', 'puppeteer-extra-plugin-stealth', '@puppeteer/browsers', 'find-chrome-bin']
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
externalizeDepsPlugin({
|
||||
exclude: ['@geekgeekrun/geek-auto-start-chat-with-boss', '@geekgeekrun/dingtalk-plugin']
|
||||
exclude: ['@geekgeekrun/geek-auto-start-chat-with-boss', '@geekgeekrun/dingtalk-plugin', 'find-chrome-bin']
|
||||
})
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Object.assign(module.exports, {
|
||||
puppeteerExtra: require('puppeteer-extra'),
|
||||
PuppeteerExtraPluginStealth: require('puppeteer-extra-plugin-stealth'),
|
||||
puppeteerManager: require('@puppeteer/browsers')
|
||||
})
|
||||
puppeteerManager: require('@puppeteer/browsers'),
|
||||
findChromeBin: require('find-chrome-bin')
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export * as puppeteerExtra from 'puppeteer-extra'
|
||||
export * as PuppeteerExtraPluginStealth from 'puppeteer-extra-plugin-stealth'
|
||||
export * as puppeteerManager from '@puppeteer/browsers'
|
||||
|
||||
export * as findChromeBin from 'find-chrome-bin'
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "^2.0.0",
|
||||
"find-chrome-bin": "^2.0.1",
|
||||
"puppeteer": "^22.0.0",
|
||||
"puppeteer-extra": "^3.3.6",
|
||||
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
||||
@@ -497,6 +498,37 @@
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/find-chrome-bin": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/find-chrome-bin/-/find-chrome-bin-2.0.1.tgz",
|
||||
"integrity": "sha512-aDwC2y0dLxt0GFmQ+q8bqBCZ10VW9zYT/lNV806tRDqDAh5XpkTWulB96RKDHDuKu36m/dEvhmhD5IU237oOTg==",
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "^1.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/find-chrome-bin/node_modules/@puppeteer/browsers": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmmirror.com/@puppeteer/browsers/-/browsers-1.9.1.tgz",
|
||||
"integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==",
|
||||
"dependencies": {
|
||||
"debug": "4.3.4",
|
||||
"extract-zip": "2.0.1",
|
||||
"progress": "2.0.3",
|
||||
"proxy-agent": "6.3.1",
|
||||
"tar-fs": "3.0.4",
|
||||
"unbzip2-stream": "1.4.3",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"browsers": "lib/cjs/main-cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/for-in": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/for-in/-/for-in-1.0.2.tgz",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "^2.0.0",
|
||||
"find-chrome-bin": "^2.0.1",
|
||||
"puppeteer": "^22.0.0",
|
||||
"puppeteer-extra": "^3.3.6",
|
||||
"puppeteer-extra-plugin-stealth": "^2.11.2"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"JSONStream": "^1.3.5",
|
||||
"electron-updater": "^6.1.7",
|
||||
"element-plus": "^2.5.5",
|
||||
"find-chrome-bin": "^2.0.1",
|
||||
"normalize.css": "^8.0.1",
|
||||
"vue-router": "^4.2.5"
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import * as fs from 'node:fs'
|
||||
import type { InstalledBrowser } from '@puppeteer/browsers'
|
||||
import { is } from '@electron-toolkit/utils'
|
||||
import electron from 'electron'
|
||||
import { saveLastUsedAndAvailableBrowserPath } from './history-utils'
|
||||
|
||||
const expectBuildId = process.env.EXPECT_CHROME_FOR_PUPPETEER_BUILD_ID || '121.0.6167.85'
|
||||
const cacheDir = path.join(
|
||||
@@ -31,7 +32,7 @@ const getPuppeteerManagerModule = async () => {
|
||||
return puppeteerManager
|
||||
}
|
||||
|
||||
export const getExpectPuppeteerExecutablePath = async () => {
|
||||
export const getExpectCachedPuppeteerExecutablePath = async () => {
|
||||
const puppeteerManager = await getPuppeteerManagerModule()
|
||||
|
||||
return puppeteerManager.computeExecutablePath({
|
||||
@@ -41,9 +42,9 @@ export const getExpectPuppeteerExecutablePath = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
export const checkPuppeteerExecutable = async () => {
|
||||
export const checkCachedPuppeteerExecutable = async () => {
|
||||
try {
|
||||
const executablePath = await getExpectPuppeteerExecutablePath()
|
||||
const executablePath = await getExpectCachedPuppeteerExecutablePath()
|
||||
return fs.existsSync(executablePath)
|
||||
} catch {
|
||||
// should limit [ERR_MODULE_NOT_FOUND]
|
||||
@@ -59,7 +60,7 @@ const checkAndDownloadPuppeteerExecutable = async (
|
||||
) => {
|
||||
const puppeteerManager = await getPuppeteerManagerModule()
|
||||
let installedBrowser: InstalledBrowser
|
||||
if (!(await checkPuppeteerExecutable())) {
|
||||
if (!(await checkCachedPuppeteerExecutable())) {
|
||||
try {
|
||||
await options.confirmContinuePromise
|
||||
} catch {
|
||||
@@ -84,6 +85,7 @@ const checkAndDownloadPuppeteerExecutable = async (
|
||||
})
|
||||
).find((it) => it.buildId === expectBuildId)!
|
||||
}
|
||||
await saveLastUsedAndAvailableBrowserPath(await getExpectCachedPuppeteerExecutablePath())
|
||||
|
||||
return installedBrowser
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { is } from '@electron-toolkit/utils'
|
||||
import electron from 'electron'
|
||||
import * as os from 'node:os'
|
||||
import path from 'node:path'
|
||||
|
||||
export default async function findAndLocateExistedChromiumExecutable() {
|
||||
let findChrome: typeof import('find-chrome-bin').findChrome
|
||||
if (is.dev) {
|
||||
findChrome = (await import('find-chrome-bin')).findChrome
|
||||
} else {
|
||||
findChrome = (
|
||||
await import(
|
||||
path.resolve(
|
||||
electron.app.getAppPath(),
|
||||
'..',
|
||||
'external-node-runtime-dependencies/index.mjs'
|
||||
)
|
||||
)
|
||||
).findChromeBin.findChrome
|
||||
}
|
||||
// For windows, try to find Edge(chromium)
|
||||
if (os.platform() === 'win32') {
|
||||
// TODO: handle windows
|
||||
}
|
||||
// For other, use findChrome
|
||||
const targetBrowser = await findChrome({})
|
||||
if (!targetBrowser?.executablePath) {
|
||||
throw new Error('NO_EXPECT_CHROMIUM_FOUND')
|
||||
}
|
||||
return {
|
||||
path: targetBrowser.executablePath
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import * as path from 'path'
|
||||
import * as os from 'os'
|
||||
import * as fs from 'fs'
|
||||
import * as fsPromise from 'fs/promises'
|
||||
|
||||
const runtimeFolderPath = path.join(os.homedir(), '.geekgeekrun')
|
||||
export const lastUsedBrowserRecordFilePath = path.join(
|
||||
runtimeFolderPath,
|
||||
'last-used-browser-record'
|
||||
)
|
||||
/**
|
||||
* check if last used browser is still available.
|
||||
*
|
||||
* look if last used one is exist, maybe it's downloaded by puppeteer
|
||||
* immediately return its path
|
||||
* else remove its history
|
||||
* @returns
|
||||
*/
|
||||
export const getLastUsedAndAvailableBrowserPath = async (): Promise<string | null> => {
|
||||
if (!fs.existsSync(lastUsedBrowserRecordFilePath)) {
|
||||
return null
|
||||
}
|
||||
try {
|
||||
const fileContent = (await fsPromise.readFile(lastUsedBrowserRecordFilePath)).toString()
|
||||
if (!fileContent || !fs.existsSync(fileContent)) {
|
||||
await removeLastUsedAndAvailableBrowserPath()
|
||||
return null
|
||||
}
|
||||
return fileContent
|
||||
} catch {
|
||||
await removeLastUsedAndAvailableBrowserPath()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export const saveLastUsedAndAvailableBrowserPath = async (pathToBrowser: string) => {
|
||||
try {
|
||||
if (!fs.existsSync(runtimeFolderPath)) {
|
||||
await fsPromise.mkdir(runtimeFolderPath)
|
||||
}
|
||||
await fsPromise.writeFile(lastUsedBrowserRecordFilePath, pathToBrowser)
|
||||
} catch {
|
||||
console.warn('lastUsedBrowserRecordFile write error')
|
||||
}
|
||||
}
|
||||
|
||||
export const removeLastUsedAndAvailableBrowserPath = async () => {
|
||||
if (!fs.existsSync(lastUsedBrowserRecordFilePath)) {
|
||||
return
|
||||
}
|
||||
await fsPromise.unlink(lastUsedBrowserRecordFilePath)
|
||||
}
|
||||
@@ -1,12 +1,45 @@
|
||||
import { app } from 'electron'
|
||||
import checkAndDownloadPuppeteerExecutable from './check-and-download-puppeteer-executable'
|
||||
import checkAndDownloadPuppeteerExecutable, {
|
||||
checkCachedPuppeteerExecutable,
|
||||
getExpectCachedPuppeteerExecutablePath
|
||||
} from './check-and-download-puppeteer-executable'
|
||||
import * as fs from 'fs'
|
||||
import { pipeWriteRegardlessError } from '../utils/pipe'
|
||||
import {
|
||||
removeLastUsedAndAvailableBrowserPath,
|
||||
getLastUsedAndAvailableBrowserPath,
|
||||
saveLastUsedAndAvailableBrowserPath
|
||||
} from './history-utils'
|
||||
import findAndLocateExistedChromiumExecutable from './check-and-locate-existed-chromium-executable'
|
||||
|
||||
export enum DOWNLOAD_ERROR_EXIT_CODE {
|
||||
NO_ERROR = 0,
|
||||
DOWNLOAD_ERROR = 1
|
||||
}
|
||||
export const getAnyAvailablePuppeteerExecutablePath = async (): Promise<string | null> => {
|
||||
const lastUsedOnePath = await getLastUsedAndAvailableBrowserPath()
|
||||
if (lastUsedOnePath) {
|
||||
return lastUsedOnePath
|
||||
}
|
||||
// find existed browser - the one maybe actively installed by user or ship with os like Edge on windows
|
||||
try {
|
||||
const existedOnePath = (await findAndLocateExistedChromiumExecutable()).path
|
||||
await saveLastUsedAndAvailableBrowserPath(existedOnePath)
|
||||
// save its path
|
||||
return existedOnePath
|
||||
} catch {
|
||||
console.log('no existed browser path found')
|
||||
}
|
||||
// find existed browser - the fallback one
|
||||
if (await checkCachedPuppeteerExecutable()) {
|
||||
return await getExpectCachedPuppeteerExecutablePath()
|
||||
}
|
||||
|
||||
// if no one available, then return null and remove last used browser
|
||||
await removeLastUsedAndAvailableBrowserPath()
|
||||
return null
|
||||
}
|
||||
|
||||
export const checkAndDownloadDependenciesForInit = async () => {
|
||||
process.on('disconnect', () => app.exit())
|
||||
app.dock?.hide()
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
checkPuppeteerExecutable,
|
||||
} from './CHECK_AND_DOWNLOAD_DEPENDENCIES/check-and-download-puppeteer-executable'
|
||||
import { pipeWriteRegardlessError } from './utils/pipe'
|
||||
import { getAnyAvailablePuppeteerExecutablePath } from './CHECK_AND_DOWNLOAD_DEPENDENCIES'
|
||||
|
||||
const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk.json')
|
||||
|
||||
@@ -46,12 +47,13 @@ export const runAutoChat = async () => {
|
||||
type: 'PUPPETEER_INITIALIZE_SUCCESSFULLY'
|
||||
}) + '\r\n'
|
||||
)
|
||||
} catch {
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
app.exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
const isPuppeteerExecutable = await checkPuppeteerExecutable()
|
||||
const isPuppeteerExecutable = !!(await getAnyAvailablePuppeteerExecutablePath())
|
||||
if (!isPuppeteerExecutable) {
|
||||
app.exit(1)
|
||||
return
|
||||
|
||||
@@ -9,13 +9,12 @@ import {
|
||||
writeConfigFile
|
||||
} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||
import { ChildProcess } from 'child_process'
|
||||
import {
|
||||
checkPuppeteerExecutable,
|
||||
getExpectPuppeteerExecutablePath
|
||||
} from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/check-and-download-puppeteer-executable'
|
||||
import * as JSONStream from 'JSONStream'
|
||||
import { DOWNLOAD_ERROR_EXIT_CODE } from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES'
|
||||
let mainWindow: BrowserWindow = null
|
||||
import {
|
||||
DOWNLOAD_ERROR_EXIT_CODE,
|
||||
getAnyAvailablePuppeteerExecutablePath
|
||||
} from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES'
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
|
||||
export function createMainWindow(): void {
|
||||
// Create the browser window.
|
||||
@@ -95,7 +94,7 @@ export function createMainWindow(): void {
|
||||
const subProcessEnv = {
|
||||
...process.env,
|
||||
MAIN_BOSSGEEKGO_UI_RUN_MODE: 'geekAutoStartWithBoss',
|
||||
PUPPETEER_EXECUTABLE_PATH: await getExpectPuppeteerExecutablePath()
|
||||
PUPPETEER_EXECUTABLE_PATH: (await getAnyAvailablePuppeteerExecutablePath())!
|
||||
}
|
||||
subProcessOfPuppeteer = childProcess.spawn(process.argv[0], process.argv.slice(1), {
|
||||
env: subProcessEnv,
|
||||
@@ -130,9 +129,11 @@ export function createMainWindow(): void {
|
||||
})
|
||||
|
||||
ipcMain.handle('check-dependencies', async () => {
|
||||
const [puppeteerExecutableAvailable] = await Promise.all([checkPuppeteerExecutable()])
|
||||
const [anyAvailablePuppeteerExecutablePath] = await Promise.all([
|
||||
getAnyAvailablePuppeteerExecutablePath()
|
||||
])
|
||||
return {
|
||||
puppeteerExecutableAvailable
|
||||
puppeteerExecutableAvailable: !!anyAvailablePuppeteerExecutablePath
|
||||
}
|
||||
})
|
||||
|
||||
@@ -144,7 +145,6 @@ export function createMainWindow(): void {
|
||||
const subProcessEnv = {
|
||||
...process.env,
|
||||
MAIN_BOSSGEEKGO_UI_RUN_MODE: 'checkAndDownloadDependenciesForInit',
|
||||
PUPPETEER_EXECUTABLE_PATH: await getExpectPuppeteerExecutablePath()
|
||||
}
|
||||
subProcessOfCheckAndDownloadDependencies = childProcess.spawn(
|
||||
process.argv[0],
|
||||
|
||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -69,6 +69,9 @@ importers:
|
||||
element-plus:
|
||||
specifier: ^2.5.5
|
||||
version: 2.5.5(vue@3.4.15)
|
||||
find-chrome-bin:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
normalize.css:
|
||||
specifier: ^8.0.1
|
||||
version: 8.0.1
|
||||
@@ -3056,6 +3059,15 @@ packages:
|
||||
to-regex-range: 5.0.1
|
||||
dev: true
|
||||
|
||||
/find-chrome-bin@2.0.1:
|
||||
resolution: {integrity: sha512-aDwC2y0dLxt0GFmQ+q8bqBCZ10VW9zYT/lNV806tRDqDAh5XpkTWulB96RKDHDuKu36m/dEvhmhD5IU237oOTg==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
dependencies:
|
||||
'@puppeteer/browsers': 1.9.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/find-up@5.0.0:
|
||||
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
Reference in New Issue
Block a user