From 535b9f6f0732051fe6c2b772d4521ef94f506c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A3=AB=E5=AD=90=E2=98=80=EF=B8=8F?= <84996057@qq.com> Date: Wed, 21 Feb 2024 21:44:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20=20node=20=E4=BC=AA?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E8=8E=B7=E5=8F=96=E8=AF=A6=E7=BB=86=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 1 - .env.production | 1 - packages/main/package.json | 2 +- packages/main/scripts/config.ts | 1 + packages/main/src/services/DownloadService.ts | 81 +++++++------------ pnpm-lock.yaml | 27 ++++++- 6 files changed, 56 insertions(+), 57 deletions(-) diff --git a/.env.development b/.env.development index b608a43..03653e2 100644 --- a/.env.development +++ b/.env.development @@ -1,6 +1,5 @@ APP_TD_APPID= APP_CLARITY_APPID= -APP_DOWNLOAD_DEBUG=true GH_TOKEN= LOAD_DEVTOOLS= diff --git a/.env.production b/.env.production index 429b2fb..7975c72 100644 --- a/.env.production +++ b/.env.production @@ -1,5 +1,4 @@ APP_TD_APPID= APP_CLARITY_APPID= -APP_DOWNLOAD_DEBUG= GH_TOKEN= diff --git a/packages/main/package.json b/packages/main/package.json index ce3f1b4..f132805 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -56,9 +56,9 @@ "electron-store": "^8.1.0", "execa": "^8.0.1", "fs-extra": "^11.2.0", - "iconv-lite": "^0.6.3", "inversify": "^6.0.2", "lodash": "^4.17.21", + "node-pty": "^1.0.0", "reflect-metadata": "^0.2.1", "ts-node": "^10.9.2", "typeorm": "^0.3.19" diff --git a/packages/main/scripts/config.ts b/packages/main/scripts/config.ts index bb0b6ae..dfcefe0 100644 --- a/packages/main/scripts/config.ts +++ b/packages/main/scripts/config.ts @@ -4,4 +4,5 @@ export const external = [ "aws-sdk", "mock-aws-s3", "@cliqz/adblocker-electron-preload", + "node-pty", ]; diff --git a/packages/main/src/services/DownloadService.ts b/packages/main/src/services/DownloadService.ts index d59645a..86c95d3 100644 --- a/packages/main/src/services/DownloadService.ts +++ b/packages/main/src/services/DownloadService.ts @@ -10,8 +10,6 @@ import { TYPES } from "../types"; import LoggerServiceImpl from "./LoggerService"; import StoreService from "./StoreService"; import VideoRepository from "../repository/VideoRepository"; -import { execa, Options as ExecaOptions } from "execa"; -import iconv from "iconv-lite"; import { biliDownloaderBin, formatHeaders, @@ -19,12 +17,12 @@ import { m3u8DownloaderBin, stripColors, } from "../helper"; +import * as pty from "node-pty"; export interface DownloadOptions { abortSignal: AbortController; encoding?: string; onMessage?: (message: string) => void; - onErrMessage?: (message: string) => void; } @injectable() @@ -35,8 +33,6 @@ export default class DownloadService extends EventEmitter { private limit: number; - private debug = process.env.APP_DOWNLOAD_DEBUG; - private signal: Record = {}; constructor( @@ -64,7 +60,7 @@ export default class DownloadService extends EventEmitter { async stopTask(id: number) { if (this.signal[id]) { - this.log(`taskId: ${id} stop`); + this.logger.info(`taskId: ${id} stop`); this.signal[id].abort(); } } @@ -77,7 +73,7 @@ export default class DownloadService extends EventEmitter { ); this.emit("download-start", task.id); - this.log(`taskId: ${task.id} start`); + this.logger.info(`taskId: ${task.id} start`); const controller = new AbortController(); this.signal[task.id] = controller; @@ -106,7 +102,7 @@ export default class DownloadService extends EventEmitter { await this.process(params); delete this.signal[task.id]; - this.log(`taskId: ${task.id} success`); + this.logger.info(`taskId: ${task.id} success`); await this.videoRepository.changeVideoStatus( task.id, @@ -114,8 +110,8 @@ export default class DownloadService extends EventEmitter { ); this.emit("download-success", task.id); } catch (err: any) { - this.log(`taskId: ${task.id} failed`); - if (err.name === "AbortError") { + this.logger.info(`taskId: ${task.id} failed`); + if (err.message === "AbortError") { // 下载暂停 await this.videoRepository.changeVideoStatus( task.id, @@ -160,60 +156,45 @@ export default class DownloadService extends EventEmitter { } } - log(...args: unknown[]) { - if (this.debug) { - this.logger.info(`[DownloadService] `, ...args); - } - } - private _execa( binPath: string, args: string[], - params: DownloadOptions & ExecaOptions, + params: DownloadOptions, ): Promise { - const { - abortSignal, - encoding = "utf-8", - onMessage, - onErrMessage, - ...execOptions - } = params; + const { abortSignal, onMessage } = params; return new Promise((resolve, reject) => { - const process = (data: Buffer, callback: (message: string) => void) => { - const items = iconv.decode(data, encoding); - items.split("\n").forEach((item) => { - const message = item.trim(); - if (!message) return; - try { - this.logger.debug("DownloadService: ", message); - callback(message); - } catch (err) { - reject(err); - } - }); + const process = (lines: string, callback: (message: string) => void) => { + const message = lines.replace(/\\./g, ""); + if (!message) return; + try { + console.log(message); + callback(message); + } catch (err) { + reject(err); + } }; - const downloader = execa(binPath, args, { - ...execOptions, - signal: abortSignal.signal, + console.log("args", binPath, args); + const ptyProcess = pty.spawn(binPath, args, { + cols: 200, + rows: 100, }); - if (downloader.stdout && onMessage) { - downloader.stdout.on("data", (data) => process(data, onMessage)); - } - - if (downloader.stderr && onErrMessage) { - downloader.stderr.on("data", (data) => process(data, onErrMessage)); + if (onMessage) { + ptyProcess.onData((data) => process(data, onMessage)); } - downloader.on("error", (err) => { - reject(err); + abortSignal.signal.addEventListener("abort", () => { + ptyProcess.kill(); }); - downloader.on("close", (code) => { - if (code === 0) { + ptyProcess.onExit(({ exitCode, signal }) => { + console.log("exitCode", exitCode, "signal", signal); + if (exitCode === 0 && signal === 0) { resolve(); + } else if (exitCode === 0 && signal === 1) { + reject(new Error("AbortError")); } else { reject(new Error("未知错误")); } @@ -232,8 +213,6 @@ export default class DownloadService extends EventEmitter { const spawnParams = [url, "--work-dir", local]; await this._execa(biliDownloaderBin, spawnParams, { - detached: true, - shell: true, abortSignal, onMessage: (message) => { if (isLiveReg.test(message) || startDownloadReg.test(message)) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c9099e..3e20021 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,18 +118,21 @@ importers: fs-extra: specifier: ^11.2.0 version: 11.2.0 - iconv-lite: - specifier: ^0.6.3 - version: 0.6.3 inversify: specifier: ^6.0.2 version: 6.0.2 lodash: specifier: ^4.17.21 version: 4.17.21 + node-pty: + specifier: ^1.0.0 + version: 1.0.0 reflect-metadata: specifier: ^0.2.1 version: 0.2.1 + strip-final-newline: + specifier: ^4.0.0 + version: 4.0.0 ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) @@ -7027,6 +7030,7 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 + dev: true /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -8173,6 +8177,10 @@ packages: thenify-all: 1.6.0 dev: false + /nan@2.18.0: + resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==} + dev: false + /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -8265,6 +8273,13 @@ packages: - supports-color dev: true + /node-pty@1.0.0: + resolution: {integrity: sha512-wtBMWWS7dFZm/VgqElrTvtfMq4GzJ6+edFI0Y0zyzygUSZMgZdraDUMUhCIvkjhJjme15qWmbyJbtAx4ot4uZA==} + requiresBuild: true + dependencies: + nan: 2.18.0 + dev: false + /nopt@6.0.0: resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -9869,6 +9884,7 @@ packages: /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true /sanitize-filename@1.6.3: resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} @@ -10308,6 +10324,11 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + /strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + dev: false + /strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'}