mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-08 17:09:07 +08:00
add the ui for dedicate download progress of puppeteer; use JSONParse to parse the download progress; finish the logic to pass the progress to ui
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
"@electron-toolkit/preload": "^3.0.0",
|
"@electron-toolkit/preload": "^3.0.0",
|
||||||
"@electron-toolkit/utils": "^3.0.0",
|
"@electron-toolkit/utils": "^3.0.0",
|
||||||
"@puppeteer/browsers": "^2.0.0",
|
"@puppeteer/browsers": "^2.0.0",
|
||||||
|
"JSONStream": "^1.3.5",
|
||||||
"electron-updater": "^6.1.7",
|
"electron-updater": "^6.1.7",
|
||||||
"element-plus": "^2.5.5",
|
"element-plus": "^2.5.5",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
|
|||||||
+15
-5
@@ -28,13 +28,23 @@ export const getExpectPuppeteerExecutablePath = async () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkAndDownloadPuppeteer = async (options: {
|
export const checkPuppeteerExecutable = async () => {
|
||||||
downloadProgressCallback?: (downloadedBytes: number, totalBytes: number) => void
|
|
||||||
}) => {
|
|
||||||
const puppeteerManager = await getPuppeteerManagerModule()
|
|
||||||
const executablePath = await getExpectPuppeteerExecutablePath()
|
const executablePath = await getExpectPuppeteerExecutablePath()
|
||||||
|
return fs.existsSync(executablePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAndDownloadPuppeteer = async (options: {
|
||||||
|
downloadProgressCallback?: (downloadedBytes: number, totalBytes: number) => void,
|
||||||
|
confirmContinuePromise?: Promise<void>
|
||||||
|
} = {}) => {
|
||||||
|
const puppeteerManager = await getPuppeteerManagerModule()
|
||||||
let installedBrowser: InstalledBrowser
|
let installedBrowser: InstalledBrowser
|
||||||
if (!fs.existsSync(executablePath)) {
|
if (!(await checkPuppeteerExecutable())) {
|
||||||
|
try {
|
||||||
|
await options.confirmContinuePromise
|
||||||
|
} catch {
|
||||||
|
throw new Error('USER_CANCEL_DOWNLOAD_PUPPETEER')
|
||||||
|
}
|
||||||
// maybe the exist installation is broken.
|
// maybe the exist installation is broken.
|
||||||
await puppeteerManager.uninstall({
|
await puppeteerManager.uninstall({
|
||||||
cacheDir,
|
cacheDir,
|
||||||
|
|||||||
@@ -1,9 +1,29 @@
|
|||||||
import checkAndDownloadPuppeteer from './check-and-download-puppeteer'
|
import checkAndDownloadPuppeteer from './check-and-download-puppeteer'
|
||||||
|
import * as net from 'net'
|
||||||
|
|
||||||
export const checkAndDownloadDependenciesForInit = async () => {
|
export const checkAndDownloadDependenciesForInit = async () => {
|
||||||
|
let pipe: null | net.Socket = null
|
||||||
|
try {
|
||||||
|
pipe = new net.Socket({ fd: 3 })
|
||||||
|
} catch {
|
||||||
|
console.warn('pipe is not available')
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe?.write(
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'NEED_WARMING_UP_DEPENDENCIES'
|
||||||
|
}) + '\r\n'
|
||||||
|
)
|
||||||
|
|
||||||
const browser = await checkAndDownloadPuppeteer({
|
const browser = await checkAndDownloadPuppeteer({
|
||||||
downloadProgressCallback(downloadedBytes: number, totalBytes: number) {
|
downloadProgressCallback(downloadedBytes: number, totalBytes: number) {
|
||||||
console.log(`${downloadedBytes} / ${totalBytes}`)
|
pipe?.write(
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'PUPPETEER_DOWNLOAD_PROGRESS',
|
||||||
|
totalBytes,
|
||||||
|
downloadedBytes
|
||||||
|
})
|
||||||
|
) + '\r\n'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ import { app } from 'electron'
|
|||||||
import { SyncHook, AsyncSeriesHook } from 'tapable'
|
import { SyncHook, AsyncSeriesHook } from 'tapable'
|
||||||
import { readConfigFile } from '@bossgeekgo/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
import { readConfigFile } from '@bossgeekgo/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||||
import * as net from 'net'
|
import * as net from 'net'
|
||||||
|
import {
|
||||||
|
checkPuppeteerExecutable,
|
||||||
|
getExpectPuppeteerExecutablePath
|
||||||
|
} from './CHECK_AND_DOWNLOAD_DEPENDENCIES/check-and-download-puppeteer'
|
||||||
|
import * as childProcess from 'node:child_process'
|
||||||
|
import * as JSONStream from 'JSONStream'
|
||||||
|
|
||||||
const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk.json')
|
const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk.json')
|
||||||
|
|
||||||
@@ -20,26 +26,69 @@ export const runAutoChat = async () => {
|
|||||||
pipe?.write(
|
pipe?.write(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: 'INITIALIZE_PUPPETEER'
|
type: 'INITIALIZE_PUPPETEER'
|
||||||
})
|
}) + '\r\n'
|
||||||
)
|
)
|
||||||
try {
|
try {
|
||||||
await (await import('@bossgeekgo/geek-auto-start-chat-with-boss/index.mjs')).initPuppeteer()
|
await (await import('@bossgeekgo/geek-auto-start-chat-with-boss/index.mjs')).initPuppeteer()
|
||||||
pipe?.write(
|
pipe?.write(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: 'PUPPETEER_INITIALIZE_SUCCESSFULLY'
|
type: 'PUPPETEER_INITIALIZE_SUCCESSFULLY'
|
||||||
})
|
}) + '\r\n'
|
||||||
)
|
)
|
||||||
} catch {
|
} catch {
|
||||||
console.error(new Error('PUPPETEER_MAY_NOT_INSTALLED'))
|
console.error(new Error('PUPPETEER_MAY_NOT_INSTALLED'))
|
||||||
pipe?.write(
|
pipe?.write(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: 'PUPPETEER_MAY_NOT_INSTALLED'
|
type: 'PUPPETEER_MAY_NOT_INSTALLED'
|
||||||
})
|
}) + '\r\n'
|
||||||
)
|
)
|
||||||
app.exit(1)
|
app.exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isPuppeteerExecutable = await checkPuppeteerExecutable()
|
||||||
|
if (!isPuppeteerExecutable) {
|
||||||
|
const subProcessEnv = {
|
||||||
|
...process.env,
|
||||||
|
MAIN_BOSSGEEKGO_UI_RUN_MODE: 'checkAndDownloadDependenciesForInit',
|
||||||
|
PUPPETEER_EXECUTABLE_PATH: await getExpectPuppeteerExecutablePath()
|
||||||
|
}
|
||||||
|
const subProcessOfCheckAndDownloadDependencies = childProcess.spawn(
|
||||||
|
process.argv[0],
|
||||||
|
process.argv.slice(1),
|
||||||
|
{
|
||||||
|
env: subProcessEnv,
|
||||||
|
stdio: [null, null, null, 'pipe']
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
subProcessOfCheckAndDownloadDependencies!.stdio[3]!.pipe(JSONStream.parse()).on(
|
||||||
|
'data',
|
||||||
|
(raw) => {
|
||||||
|
const data = raw
|
||||||
|
switch (data.type) {
|
||||||
|
case 'NEED_WARMING_UP_DEPENDENCIES': {
|
||||||
|
pipe?.write(JSON.stringify(data) + '\r\n')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'PUPPETEER_DOWNLOAD_PROGRESS': {
|
||||||
|
pipe?.write(JSON.stringify(data) + '\r\n')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'PUPPETEER_MAY_NOT_INSTALLED': {
|
||||||
|
resolve(data)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const mainLoop = (await import('@bossgeekgo/geek-auto-start-chat-with-boss/index.mjs')).mainLoop
|
const mainLoop = (await import('@bossgeekgo/geek-auto-start-chat-with-boss/index.mjs')).mainLoop
|
||||||
const hooks = {
|
const hooks = {
|
||||||
puppeteerLaunched: new SyncHook(),
|
puppeteerLaunched: new SyncHook(),
|
||||||
@@ -55,7 +104,7 @@ export const runAutoChat = async () => {
|
|||||||
pipe?.write(
|
pipe?.write(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
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'
|
||||||
)
|
)
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
} from '@bossgeekgo/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
} from '@bossgeekgo/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
|
||||||
import { ChildProcess } from 'child_process'
|
import { ChildProcess } from 'child_process'
|
||||||
import { getExpectPuppeteerExecutablePath } from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/check-and-download-puppeteer'
|
import { getExpectPuppeteerExecutablePath } from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/check-and-download-puppeteer'
|
||||||
|
import * as JSONStream from 'JSONStream'
|
||||||
let mainWindow: BrowserWindow
|
let mainWindow: BrowserWindow
|
||||||
|
|
||||||
export function createMainWindow(): void {
|
export function createMainWindow(): void {
|
||||||
@@ -103,14 +104,22 @@ export function createMainWindow(): void {
|
|||||||
})
|
})
|
||||||
console.log(subProcessOfPuppeteer)
|
console.log(subProcessOfPuppeteer)
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
subProcessOfPuppeteer!.stdio[3]!.on('data', (raw) => {
|
subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', (raw) => {
|
||||||
const data = JSON.parse(raw.toString())
|
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':
|
||||||
case 'PUPPETEER_MAY_NOT_INSTALLED': {
|
case 'PUPPETEER_MAY_NOT_INSTALLED': {
|
||||||
resolve(data)
|
resolve(data)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case 'NEED_WARMING_UP_DEPENDENCIES': {
|
||||||
|
mainWindow.webContents.send('NEED_WARMING_UP_DEPENDENCIES', data)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'PUPPETEER_DOWNLOAD_PROGRESS': {
|
||||||
|
mainWindow.webContents.send('PUPPETEER_DOWNLOAD_PROGRESS', data)
|
||||||
|
break
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
import { log } from 'console';
|
||||||
|
|
||||||
|
import { onUnmounted } from 'vue';
|
||||||
|
<template>
|
||||||
|
<el-dialog v-bind="$attrs" @open="percentage = 0">
|
||||||
|
<el-progress :percentage="percentage" :format="(n) => `${n.toFixed(1)}%`" />
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, onUnmounted } from 'vue'
|
||||||
|
|
||||||
|
const percentage = ref(0)
|
||||||
|
const handleProgress = (ev, { downloadedBytes, totalBytes }) => {
|
||||||
|
percentage.value = ((downloadedBytes / totalBytes) * 100)
|
||||||
|
}
|
||||||
|
electron.ipcRenderer.on('PUPPETEER_DOWNLOAD_PROGRESS', handleProgress)
|
||||||
|
onUnmounted(
|
||||||
|
() => electron.ipcRenderer.off('PUPPETEER_DOWNLOAD_PROGRESS', handleProgress)
|
||||||
|
)
|
||||||
|
</script>
|
||||||
@@ -27,14 +27,16 @@
|
|||||||
<el-button type="primary" @click="handleSubmit"> I'm ready, geekgeekgo! </el-button>
|
<el-button type="primary" @click="handleSubmit"> I'm ready, geekgeekgo! </el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
<dependencies-warming-up-dialog v-model="shouldShowDependenciesWarmingUpDialog" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { onUnmounted, ref } from 'vue'
|
||||||
import JSON5 from 'json5'
|
import JSON5 from 'json5'
|
||||||
import { ElForm, ElMessage, ElMessageBox } from 'element-plus'
|
import { ElForm, ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import router from '../../router/index'
|
import router from '../../router/index'
|
||||||
|
import DependenciesWarmingUpDialog from '../../features/DependenciesWarmingUpDialog.vue'
|
||||||
|
|
||||||
const formContent = ref({
|
const formContent = ref({
|
||||||
bossZhipinCookies: '',
|
bossZhipinCookies: '',
|
||||||
@@ -115,6 +117,16 @@ const handleExpectCompaniesInputBlur = (event) => {
|
|||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(',')
|
.join(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const shouldShowDependenciesWarmingUpDialog = ref(false)
|
||||||
|
|
||||||
|
const needWarmingUpDenpendenciesHandler = () => {
|
||||||
|
shouldShowDependenciesWarmingUpDialog.value = true
|
||||||
|
}
|
||||||
|
electron.ipcRenderer.on('NEED_WARMING_UP_DEPENDENCIES', needWarmingUpDenpendenciesHandler)
|
||||||
|
onUnmounted(
|
||||||
|
() => electron.ipcRenderer.off('NEED_WARMING_UP_DEPENDENCIES', needWarmingUpDenpendenciesHandler)
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
Generated
+16
@@ -64,6 +64,9 @@ importers:
|
|||||||
'@puppeteer/browsers':
|
'@puppeteer/browsers':
|
||||||
specifier: ^2.0.0
|
specifier: ^2.0.0
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
|
JSONStream:
|
||||||
|
specifier: ^1.3.5
|
||||||
|
version: 1.3.5
|
||||||
electron-updater:
|
electron-updater:
|
||||||
specifier: ^6.1.7
|
specifier: ^6.1.7
|
||||||
version: 6.1.7
|
version: 6.1.7
|
||||||
@@ -1490,6 +1493,14 @@ packages:
|
|||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/JSONStream@1.3.5:
|
||||||
|
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
jsonparse: 1.3.1
|
||||||
|
through: 2.3.8
|
||||||
|
dev: false
|
||||||
|
|
||||||
/acorn-jsx@5.3.2(acorn@8.11.3):
|
/acorn-jsx@5.3.2(acorn@8.11.3):
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3177,6 +3188,11 @@ packages:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
|
|
||||||
|
/jsonparse@1.3.1:
|
||||||
|
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
|
||||||
|
engines: {'0': node >= 0.2.0}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/keyv@4.5.4:
|
/keyv@4.5.4:
|
||||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user