diff --git a/packages/main/bin/win32/NO_UPDATE b/packages/main/bin/win32/NO_UPDATE deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/main/bin/win32/N_m3u8DL-CLI.exe b/packages/main/bin/win32/N_m3u8DL-CLI.exe deleted file mode 100644 index 30acb3b9..00000000 Binary files a/packages/main/bin/win32/N_m3u8DL-CLI.exe and /dev/null differ diff --git a/packages/main/bin/win32/N_m3u8DL-RE.exe b/packages/main/bin/win32/N_m3u8DL-RE.exe new file mode 100644 index 00000000..73c8119d Binary files /dev/null and b/packages/main/bin/win32/N_m3u8DL-RE.exe differ diff --git a/packages/main/package.json b/packages/main/package.json index f54ddb70..557448ab 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -47,8 +47,6 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-promise": "6.1.1", "gulp": "^5.0.0", - "gulp-chmod": "^4.0.0", - "gulp-if": "^3.0.0", "prebuild-install": "^7.1.1", "prettier": "3.2.5", "semver": "^7.5.4", @@ -75,6 +73,6 @@ "node-pty": "^1.0.0", "reflect-metadata": "^0.2.1", "strip-ansi": "^7.1.0", - "typeorm": "^0.3.19" + "typeorm": "0.3.17" } } diff --git a/packages/main/scripts/config.ts b/packages/main/scripts/config.ts index 7970f660..d98606ec 100644 --- a/packages/main/scripts/config.ts +++ b/packages/main/scripts/config.ts @@ -22,7 +22,7 @@ function getConfig(): esbuild.BuildOptions { process.env.NODE_ENV === "development" ? { // 开发环境中二进制可执行文件的路径 - __bin__: `"${mainResolve("bin", process.platform).replace(/\\/g, "\\\\")}"`, + __bin__: `"${mainResolve("app/bin").replace(/\\/g, "\\\\")}"`, } : { ...env, diff --git a/packages/main/scripts/index.ts b/packages/main/scripts/index.ts index 0e6d24b1..3c3d4866 100644 --- a/packages/main/scripts/index.ts +++ b/packages/main/scripts/index.ts @@ -1,14 +1,15 @@ import { deleteSync } from "del"; -import { ElectronApp, mainResolve, Env, isMac, isLinux } from "./utils"; +import { ElectronApp, mainResolve, Env, isWin } from "./utils"; import gulp from "gulp"; -import chmod from "gulp-chmod"; import * as esbuild from "esbuild"; import consola from "consola"; import { browserOptions, nodeOptions, getReleaseConfig } from "./config"; -import gulpIf from "gulp-if"; import semver from "semver"; import pkg from "../app/package.json"; import * as builder from "electron-builder"; +import glob from "glob"; +import path from "path"; +import fs from "fs"; process.env.NODE_ENV = "development"; @@ -23,25 +24,40 @@ async function clean() { ]); } -// function copySqlLite() { -// const path = "build/Release/better_sqlite3.node"; -// const from = mainResolve("node_modules/better-sqlite3", path); -// const to = mainResolve("app/build/Release"); -// return gulp.src(from).pipe(gulp.dest(to)); -// } - -function copyBin() { - return gulp - .src(mainResolve("bin", process.platform, "*"), { - ignore: [".gitignore", "Logs/**/*"], - }) - .pipe(gulp.dest(mainResolve("app/bin"))); +async function copyBin() { + const sourceDir = mainResolve("bin", process.platform); + const targetDir = mainResolve("app/bin"); + + // 获取源目录下的所有文件 + const files = glob.sync(path.join(sourceDir, "*")); + + // 遍历每个文件 + for (const file of files) { + // 忽略 .gitignore 文件和 Logs 文件夹 + if (file.endsWith(".gitignore") || file.includes("Logs")) { + continue; + } + + // 计算目标文件的路径 + const targetFile = path.join(targetDir, path.basename(file)); + // 如果没有文件夹则创建文件夹 + if (!fs.existsSync(targetDir)) { + fs.mkdirSync(targetDir); + } + + // 复制文件 + fs.copyFileSync(file, targetFile); + } } -function chmodBin() { - return gulp - .src(mainResolve("app/bin/*")) - .pipe(gulpIf(isMac || isLinux, chmod(0o777))); +async function chmodBin() { + // 遍历文件夹下的所有文件,将文件的权限设置为 777 + if (isWin) return; + + const files = glob.sync(mainResolve("app/bin/*")); + for (const file of files) { + fs.chmodSync(file, 0o777); + } } const copy = gulp.parallel(copyBin); diff --git a/packages/main/src/helper/variables.ts b/packages/main/src/helper/variables.ts index 71df23fd..534596d2 100644 --- a/packages/main/src/helper/variables.ts +++ b/packages/main/src/helper/variables.ts @@ -39,11 +39,9 @@ export const PERSIST_WEBVIEW = "persist:webview"; export const db = resolve(workspace, "app.db"); // bin path -const downloaderBinName = isWin ? "N_m3u8DL-CLI" : "N_m3u8DL-RE"; export const ffmpegPath = resolveBin("ffmpeg"); export const biliDownloaderBin = resolveBin("BBDown"); -export const m3u8DownloaderBin = resolveBin(downloaderBinName); -export const videoServerBin = resolveBin("server"); +export const m3u8DownloaderBin = resolveBin("N_m3u8DL-RE"); // plugin path export const pluginPath = resolveStatic("plugin/index.js"); diff --git a/packages/main/src/repository/VideoRepository.ts b/packages/main/src/repository/VideoRepository.ts index a337c445..9f6c2a6a 100644 --- a/packages/main/src/repository/VideoRepository.ts +++ b/packages/main/src/repository/VideoRepository.ts @@ -114,12 +114,12 @@ export default class VideoRepository { async changeVideoStatus(id: number | number[], status: DownloadStatus) { const ids = !Array.isArray(id) ? [id] : id; - return this.db.appDataSource - .createQueryBuilder() - .update(Video) - .set({ status }) - .where({ id: In(ids) }) - .execute(); + const videoRepository = this.db.appDataSource.getRepository(Video); + const videos = await videoRepository.findBy({ id: In(ids) }); + for (const video of videos) { + video.status = status; + } + await videoRepository.save(videos); } async changeVideoIsLive(id: number) { diff --git a/packages/main/src/services/DownloadService.ts b/packages/main/src/services/DownloadService.ts index 61d901b5..31d49af5 100644 --- a/packages/main/src/services/DownloadService.ts +++ b/packages/main/src/services/DownloadService.ts @@ -49,39 +49,7 @@ interface Schema { const processList: Schema[] = [ { type: "m3u8", - platform: [Platform.Windows], - bin: m3u8DownloaderBin, - args: { - url: { - argsName: null, - }, - localDir: { - argsName: ["--workDir"], - }, - name: { - argsName: ["--saveName"], - }, - // headers: { - // argsName: ["--headers"], - // }, - deleteSegments: { - argsName: ["--enableDelAfterDone"], - }, - proxy: { - argsName: ["--proxyAddress"], - }, - }, - consoleReg: { - percent: "([\\d.]+)%", - speed: "([\\d.]+\\s[GMK]B/s)", - error: "ERROR", - start: "开始下载文件|开始录制", - isLive: "识别为直播流, 开始录制", - }, - }, - { - type: "m3u8", - platform: [Platform.MacOS, Platform.Linux], + platform: [Platform.MacOS, Platform.Linux, Platform.Windows], bin: m3u8DownloaderBin, args: { url: { diff --git a/packages/renderer/src/App.tsx b/packages/renderer/src/App.tsx index 2cd98d93..6d44fc4b 100644 --- a/packages/renderer/src/App.tsx +++ b/packages/renderer/src/App.tsx @@ -1,8 +1,7 @@ import { ConfigProvider, theme } from "antd"; import React, { FC, Suspense, lazy, useEffect } from "react"; -import AppLayout from "./layout/App"; import { useDispatch } from "react-redux"; -import { RouterProvider, createHashRouter } from "react-router-dom"; +import { BrowserRouter, Route, Routes } from "react-router-dom"; import { DownloadFilter } from "./nodes/HomePage"; import { setAppStore, increase } from "./store"; import "dayjs/locale/zh-cn"; @@ -11,63 +10,11 @@ import "./App.scss"; import useElectron from "./hooks/electron"; import Loading from "./components/Loading"; +const AppLayout = lazy(() => import("./layout/App")); const HomePage = lazy(() => import("./nodes/HomePage")); const SourceExtract = lazy(() => import("./nodes/SourceExtract")); const SettingPage = lazy(() => import("./nodes/SettingPage")); -const router = createHashRouter([ - { - path: "/", - element: , - children: [ - { - index: true, - element: ( - }> - - - ), - }, - { - path: "done", - element: ( - }> - - - ), - }, - { - path: "source", - element: ( - }> - - - ), - }, - { - path: "settings", - element: ( - }> - - - ), - }, - ], - }, - { - path: "/browser", - element: ( - }> - - - ), - }, - { - path: "*", - element:
404
, - }, -]); - function getAlgorithm(appTheme: "dark" | "light") { return appTheme === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm; } @@ -125,7 +72,60 @@ const App: FC = () => { componentSize="small" theme={{ algorithm: getAlgorithm(appTheme) }} > - + + + }> + + + } + > + }> + + + } + /> + }> + + + } + /> + }> + + + } + /> + }> + + + } + /> + 404} /> + + }> + + + } + /> + + ); }; diff --git a/packages/renderer/src/nodes/HomePage/index.tsx b/packages/renderer/src/nodes/HomePage/index.tsx index 650b06d8..e1774708 100644 --- a/packages/renderer/src/nodes/HomePage/index.tsx +++ b/packages/renderer/src/nodes/HomePage/index.tsx @@ -26,9 +26,9 @@ import { import { useSelector } from "react-redux"; import { selectAppStore } from "../../store"; import DownloadFrom from "../../components/DownloadForm"; -import dayjs from "dayjs"; import { Trans, useTranslation } from "react-i18next"; import Terminal from "../../components/Terminal"; +import { moment } from "../../utils"; const { Text } = Typography; @@ -60,7 +60,12 @@ const HomePage: FC = ({ filter = DownloadFilter.list }) => { } = useElectron(); const appStore = useSelector(selectAppStore); const { t } = useTranslation(); - const { data, loading, pagination, refresh } = usePagination( + const { + data = { total: 0, list: [] }, + loading, + pagination, + refresh, + } = usePagination( ({ current, pageSize }) => { return getDownloadItems({ current, @@ -84,7 +89,7 @@ const HomePage: FC = ({ filter = DownloadFilter.list }) => { log: "", }); - const onDownloadProgress = (e: any, progress: DownloadProgress) => { + const onDownloadProgress = (e: unknown, progress: DownloadProgress) => { setProgress((curProgress) => ({ ...curProgress, [progress.id]: progress, @@ -411,9 +416,7 @@ const HomePage: FC = ({ filter = DownloadFilter.list }) => { const items = batchList.split("\n").map((item: any) => { let [url, name] = item.split(" "); url = url ? url.trim() : ""; - name = name - ? name.trim() - : dayjs().format("YYYY-MM-DDTHH:mm:ssZ"); + name = name ? name.trim() : moment(); return { url, name, @@ -423,7 +426,7 @@ const HomePage: FC = ({ filter = DownloadFilter.list }) => { await addDownloadItems(items); } else { await addDownloadItem({ - name: values.name || dayjs().format("YYYY-MM-DDTHH:mm:ssZ"), + name: values.name || moment(), url: values.url, headers: values.headers, type: DownloadType.m3u8, @@ -464,7 +467,7 @@ const HomePage: FC = ({ filter = DownloadFilter.list }) => { }} rowKey="id" rowSelection={rowSelection} - dataSource={data?.list || []} + dataSource={data.list || []} tableAlertOptionRender={({ selectedRowKeys, onCleanSelected }) => { if (selectedRowKeys.length === 0) { return null; @@ -496,11 +499,11 @@ const HomePage: FC = ({ filter = DownloadFilter.list }) => { tableAlertRender={({ selectedRows }) => { return ( <> - {data?.list.length !== 0 && ( + {data.list.length !== 0 && (