diff --git a/README.md b/README.md index ddff489..cb01e6e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -# V2.0重磅更新,所见即所得! -## res-downloader(爱享素材下载器) +## res-downloader(爱享素材下载器) 【[点击加入群聊](https://qm.qq.com/q/W8mVeZideE)】 +🎯 基于 [electron-vite-vue](https://github.com/electron-vite/electron-vite-vue.git) +📦 操作简单、可获取不同类型的资源 🖥️ 支持Win10、Win11、Mac 🌐 支持视频、音频、图片、m3u8等网络资源下载 💪 支持微信视频号、小程序、抖音、快手、小红书、酷狗音乐、qq音乐等网络资源下载 @@ -38,5 +39,25 @@ Win7无法使用 >> MAC: /Users/你的用户名称/.res-downloader@putyy/res-downloader-installed.lock >> Win: C:\Users\Admin\.res-downloader@putyy/res-downloader-installed.lock +其他问题请留言 https://github.com/putyy/res-downloader/issues + +## 二次开发 +> ps: 打包慢的问题可以参考 https://www.putyy.com/articles/87 +```sh +git clone https://github.com/putyy/res-downloader + +cd res-downloader + +yarn install + +yarn run dev + +# 打包mac +yarn run build --universal --mac + +# 打包win +yarn run build --win +``` + ## 免责声明 本软件用于学习研究使用,若因使用本软件造成的一切法律责任均与本人无关! diff --git a/components.d.ts b/components.d.ts index 13d3cfb..8e70bbc 100755 --- a/components.d.ts +++ b/components.d.ts @@ -15,10 +15,13 @@ declare module 'vue' { ElHeader: typeof import('element-plus/es')['ElHeader'] ElIcon: typeof import('element-plus/es')['ElIcon'] ElInput: typeof import('element-plus/es')['ElInput'] + ElLink: typeof import('element-plus/es')['ElLink'] ElMain: typeof import('element-plus/es')['ElMain'] ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] + ElOption: typeof import('element-plus/es')['ElOption'] ElRow: typeof import('element-plus/es')['ElRow'] + ElSelect: typeof import('element-plus/es')['ElSelect'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] Footer: typeof import('./src/components/layout/Footer.vue')['default'] Index: typeof import('./src/components/layout/Index.vue')['default'] diff --git a/electron-builder.json5 b/electron-builder.json5 index 586af0f..eba3e06 100644 --- a/electron-builder.json5 +++ b/electron-builder.json5 @@ -3,7 +3,7 @@ */ { "$schema": "https://raw.githubusercontent.com/electron-userland/electron-builder/master/packages/app-builder-lib/scheme.json", - "appId": "com.putyy.ResDownloader", + "appId": "com.putyy.res-downloader", "asar": true, "directories": { "output": "release/${version}" @@ -14,7 +14,7 @@ "electron/res/**/*" ], "mac": { - "icon": "electron/res/icon/icons/mac/icon.icns", + "icon": "electron/res/icon/mac.icns", "artifactName": "${productName}_${version}.${arch}.${ext}", "singleArchFiles": "*", "target": [ @@ -22,13 +22,27 @@ "target": "dmg", "arch": [ 'x64', - 'arm64' + 'arm64', + 'universal' ] } + ], + "extraResources": [ + { + "from": "electron/res/mac/aria2/aria2.conf", + "to": "electron/res/mac/aria2/aria2.conf", + "filter": ["**/*"] + }, + { + "from": "electron/res/mac/aria2/${arch}/aria2c", + "to": "electron/res/mac/aria2/aria2c", + "filter": ["**/*"], + } ] }, "win": { - "icon": "electron/res/icon/icons/win/icon.ico", + "icon": "electron/res/icon/win.ico", + "artifactName": "${productName}_${version}.${ext}", "target": [ { "target": "nsis", @@ -37,7 +51,13 @@ ] } ], - "artifactName": "${productName}_${version}.${ext}" + "extraResources": [ + { + "from": "electron/res/win", + "to": "electron/res/win", + "filter": ["**/*"], + } + ] }, "nsis": { "oneClick": false, @@ -47,6 +67,7 @@ "deleteAppDataOnUninstall": false }, "extraResources": [ - "electron/res" + "electron/res/icon", + "electron/res/keys", ] } diff --git a/electron/main/aria2Rpc.ts b/electron/main/aria2Rpc.ts new file mode 100644 index 0000000..e84dcdb --- /dev/null +++ b/electron/main/aria2Rpc.ts @@ -0,0 +1,51 @@ +const axios = require('axios') +import CONFIG from './const' + +export class Aria2RPC { + constructor() { + this.url = `http://127.0.0.1:${CONFIG.ARIA_PORT}/jsonrpc` + this.id = 1 + } + + call(method, params) { + const requestData = { + jsonrpc: "2.0", + method: method, + params: params, + id: this.id++ + }; + return axios.post(this.url, requestData, { + headers: { + 'Content-Type': 'application/json' + }, + }).then((response)=>{ + return response.data + }) + } + + addUri(uri, dir, filename, headers = {}) { + return this.call('aria2.addUri', [uri, { + dir: dir, + out: filename, + headers: headers, + }]); + } + + tellStatus(gid) { + return this.call('aria2.tellStatus', [gid]); + } + + calculateDownloadProgress(bitfield) { + // 将十六进制的 bitfield 转换为二进制字符串 + const totalPieces = bitfield.length * 4; // 每个十六进制字符对应 4 位 + const binaryString = bitfield.split('').map(hex => parseInt(hex, 16).toString(2).padStart(4, '0')).join(''); + + // 计算已下载的部分数 + const downloadedPieces = binaryString.split('').filter(bit => bit === '1').length; + + // 计算进度百分比 + const progressPercentage = (downloadedPieces / totalPieces) * 100; + + return progressPercentage.toFixed(2); // 保留两位小数 + } +} \ No newline at end of file diff --git a/electron/main/cert.ts b/electron/main/cert.ts index 99699e1..b566db4 100755 --- a/electron/main/cert.ts +++ b/electron/main/cert.ts @@ -21,7 +21,7 @@ export async function installCert(checkInstalled = true) { `echo "输入本地登录密码" && sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "${CONFIG.CERT_PUBLIC_PATH}" && touch ${CONFIG.INSTALL_CERT_FLAG} && echo "安装完成"`, ) dialog.showMessageBoxSync({ - type: 'info', + type: "info", message: `命令已复制到剪贴板,粘贴命令到终端并运行以安装并信任证书`, }); diff --git a/electron/main/const.ts b/electron/main/const.ts index c79ec21..0bc2a90 100755 --- a/electron/main/const.ts +++ b/electron/main/const.ts @@ -17,13 +17,14 @@ export default { IS_DEV: isDev, EXECUTABLE_PATH, HOME_PATH, + APP_CN_NAME: '爱享素材下载器', + APP_EN_NAME: 'ResDownloader', CERT_PRIVATE_PATH: path.join(EXECUTABLE_PATH, './keys/private.pem'), CERT_PUBLIC_PATH: path.join(EXECUTABLE_PATH, './keys/public.pem'), INSTALL_CERT_FLAG: path.join(HOME_PATH, './res-downloader-installed.lock'), - WIN_CERT_INSTALL_HELPER: path.join(EXECUTABLE_PATH, './w_c.exe'), - APP_CN_NAME: '爱享素材下载器', - APP_EN_NAME: 'ResDownloader', - REGEDIT_VBS_PATH: path.join(EXECUTABLE_PATH, './regedit-vbs'), - OPEN_SSL_BIN_PATH: path.join(EXECUTABLE_PATH, './openssl/openssl.exe'), - OPEN_SSL_CNF_PATH: path.join(EXECUTABLE_PATH, './openssl/openssl.cnf'), + WIN_CERT_INSTALL_HELPER: path.join(EXECUTABLE_PATH, './win/w_c.exe'), + REGEDIT_VBS_PATH: path.join(EXECUTABLE_PATH, './win/regedit-vbs'), + OPEN_SSL_BIN_PATH: path.join(EXECUTABLE_PATH, './win/openssl/openssl.exe'), + OPEN_SSL_CNF_PATH: path.join(EXECUTABLE_PATH, './win/openssl/openssl.cnf'), + ARIA_PORT: "18899", }; diff --git a/electron/main/index.ts b/electron/main/index.ts index 89191b0..c462f66 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -3,6 +3,10 @@ import {release} from 'node:os' import {join} from 'node:path' import CONFIG from './const' import initIPC, {setWin} from './ipc' +import {closeProxy} from "./setProxy" +import log from "electron-log" +import path from 'path' +import {spawn} from 'child_process' // The built directory structure // @@ -45,6 +49,7 @@ process.on('unhandledRejection', () => { let mainWindow: BrowserWindow | null = null let previewWin: BrowserWindow | null = null +let aria2Process // Here, you can also use other preload const preload = join(__dirname, '../preload/index.js') @@ -77,21 +82,16 @@ app.on('activate', () => { } }) -// New window example arg: new windows url -ipcMain.handle('open-win', (_, arg) => { - const childWindow = new BrowserWindow({ - webPreferences: { - preload, - nodeIntegration: true, - contextIsolation: false, - }, - }) - - if (process.env.VITE_DEV_SERVER_URL) { - childWindow.loadURL(`${url}#${arg}`) - } else { - childWindow.loadFile(indexHtml, {hash: arg}) +app.on('before-quit', async e => { + e.preventDefault() + try { + await closeProxy() + aria2Process && aria2Process.kill(); + log.log("--------------closeProxy success--------------") + } catch (error) { + log.log("--------------proxy catch err--------------", error) } + app.exit() }) function createWindow() { @@ -169,9 +169,45 @@ function createPreviewWindow(parent: BrowserWindow) { }) } +function createArua2Process() { + // 根据操作系统选择 aria2 的路径 + try { + let aria2Path, aria2Conf + if (process.platform === 'win32') { + // Windows + aria2Path = path.join(CONFIG.EXECUTABLE_PATH, "./win/aria2/aria2c.exe") + aria2Conf = path.join(CONFIG.EXECUTABLE_PATH, "./win/aria2/aria2.conf") + } else { + aria2Path = path.join(CONFIG.EXECUTABLE_PATH, "./mac/aria2" + (CONFIG.IS_DEV ? `/${process.arch}` : '/') + "/aria2c"); + aria2Conf = path.join(CONFIG.EXECUTABLE_PATH, "./mac/aria2/aria2.conf") + } + // 启动 aria2 + console.log("启动 aria2") + aria2Process = spawn(aria2Path, [`--conf-path=${aria2Conf}`, `--rpc-listen-port=${CONFIG.ARIA_PORT}`], { + windowsHide: false, + stdio: CONFIG.IS_DEV ? 'pipe' : 'ignore' + }); + if(!aria2Process){ + console.log("启动 aria2 失败") + } + if (CONFIG.IS_DEV) { + aria2Process.stdout.on('data', (data) => { + console.log(`aria2: ${data}`); + }); + aria2Process.stderr.on('data', (data) => { + console.log(`aria2 error: ${data}`); + }); + } + console.log("aria2 成功启动") + } catch (e) { + console.log(`aria2 process start err`, e); + } +} + app.whenReady().then(() => { initIPC() createWindow() createPreviewWindow(mainWindow) + createArua2Process() setWin(mainWindow, previewWin) -}) +}) \ No newline at end of file diff --git a/electron/main/ipc.ts b/electron/main/ipc.ts index ea61bfd..d1a1174 100755 --- a/electron/main/ipc.ts +++ b/electron/main/ipc.ts @@ -1,26 +1,27 @@ import {ipcMain, dialog, BrowserWindow, app, shell} from 'electron' import {startServer} from './proxyServer' import {installCert, checkCertInstalled} from './cert' -import {downloadFile, decodeWxFile, suffix} from './utils' +import {decodeWxFile, suffix, getCurrentDateTimeFormatted} from './utils' // @ts-ignore import {hexMD5} from '../../src/common/md5' +import {Aria2RPC} from './aria2Rpc' import fs from "fs" -import {floor} from "lodash" let win: BrowserWindow let previewWin: BrowserWindow let isStartProxy = false +const aria2RpcClient = new Aria2RPC() export default function initIPC() { - ipcMain.handle('invoke_app_is_init', async (event, arg) => { // 初始化应用 安装证书相关 return checkCertInstalled() }) - ipcMain.handle('invoke_init_app', (event, arg) => { + ipcMain.handle('invoke_init_app', (event, arg) => { // 开始 初始化应用 安装证书相关 - installCert(false).then(r => {}) + installCert(false).then(r => { + }) }) ipcMain.handle('invoke_start_proxy', (event, arg) => { @@ -33,7 +34,7 @@ export default function initIPC() { win: win, upstreamProxy: arg.upstream_proxy ? arg.upstream_proxy : "", setProxyErrorCallback: err => { - + console.log('setProxyErrorCallback', err) }, }) }) @@ -63,33 +64,77 @@ export default function initIPC() { return {is_file: res, fileName: `${save_path}/${fileName}.mp4`} }) - ipcMain.handle('invoke_down_file', async (event, {data, save_path}) => { - + ipcMain.handle('invoke_down_file', async (event, {data, save_path, quality}) => { let down_url = data.url if (!down_url) { - return false + return new Promise((resolve, reject) => { + resolve(false); + }); + } + if (quality !== "-1" && data.decode_key && data.file_format) { + const format = data.file_format.split('#'); + const qualityMap = [ + format[0], + format[Math.floor(format.length / 2)], + format[format.length - 1] + ]; + down_url += "&X-snsvideoflag=" + qualityMap[quality]; } let fileName = data?.description ? data.description.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '') : hexMD5(down_url); - let save_path_file = `${save_path}/${fileName}` + suffix(data.type) + fileName = fileName + "_" + getCurrentDateTimeFormatted() + suffix(data.type) + let save_path_file = `${save_path}/${fileName}` if (process.platform === 'win32') { - save_path_file = `${save_path}\\${fileName}` + suffix(data.type) + save_path_file = `${save_path}\\${fileName}` } - if (fs.existsSync(save_path_file)) { - return {fullFileName: save_path_file, totalLen: ""} + let headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36', } - // 开始下载 - return downloadFile( - down_url, - data.decode_key, - save_path_file, - (res) => { - win?.webContents.send('on_down_file_schedule', {schedule: floor(res * 100)}) + + return new Promise((resolve, reject) => { + + if (down_url.includes("douyin")) { + headers['Referer'] = down_url } - ).catch(err => { - // console.log("err:", err) - return false - }) + + aria2RpcClient.addUri([down_url], save_path, fileName, headers).then((response) => { + let currentGid = response.result // 保存当前下载的 gid + let progressIntervalId = null + // // 开始定时查询下载进度 + progressIntervalId = setInterval(() => { + aria2RpcClient.tellStatus(currentGid).then((status) => { + if (status.result.status !== "complete") { + const progress = aria2RpcClient.calculateDownloadProgress(status.result.bitfield); + win?.webContents.send('on_down_file_schedule', {schedule: `已下载${progress}%`}) + } else { + clearInterval(progressIntervalId); + if (data.decode_key) { + win?.webContents.send('on_down_file_schedule', {schedule: `开始解密`}) + decodeWxFile(save_path_file, data.decode_key, save_path_file.replace(".mp4", "_wx.mp4")).then((res) => { + fs.unlink(save_path_file, (err) => { + }) + resolve(res); + }).catch((error) => { + console.log("err:", error) + resolve(false); + }); + } else { + resolve({ + fullFileName: save_path_file, + }); + } + } + }).catch((error) => { + console.error(error); + clearInterval(progressIntervalId); + resolve(false); + }); + }, 1000); + }).catch((error) => { + console.log("err:", error) + resolve(false); + }); + }); }); ipcMain.handle('invoke_resources_preview', async (event, {url}) => { @@ -106,7 +151,8 @@ export default function initIPC() { }) ipcMain.handle('invoke_open_default_browser', (event, {url}) => { - shell.openExternal(url).then(r => {}) + shell.openExternal(url).then(r => { + }) }) ipcMain.handle('invoke_open_file_dir', (event, {save_path}) => { @@ -114,7 +160,7 @@ export default function initIPC() { }) ipcMain.handle('invoke_file_del', (event, {url_sign}) => { - if (url_sign === "all"){ + if (url_sign === "all") { global.videoList = {} return } @@ -125,8 +171,8 @@ export default function initIPC() { }) ipcMain.handle('invoke_window_restart', (event) => { - app.relaunch() - app.exit() + app.relaunch() + app.exit() }) } diff --git a/electron/main/proxyServer.ts b/electron/main/proxyServer.ts index ff7f07c..db4a1ff 100755 --- a/electron/main/proxyServer.ts +++ b/electron/main/proxyServer.ts @@ -23,6 +23,8 @@ if (process.platform === 'win32') { const resObject = { url: "", url_sign: "", + cover_url: "", + file_format: "", platform: "", size: "", type: "video/mp4", @@ -84,8 +86,10 @@ export async function startServer({win, upstreamProxy, setProxyErrorCallback = f win.webContents.send('on_get_queue', Object.assign({}, resObject, { url_sign: url_sign, url: media.url + media.urlToken, + cover_url: media.coverUrl, + file_format: media.spec.map((res)=> res.fileFormat).join('#'), platform: urlInfo.hostname, - size: media?.fileSize ? toSize(media.fileSize) : 0, + size: toSize(media.fileSize), type: "video/mp4", type_str: 'video', decode_key: media.decodeKey, @@ -234,14 +238,4 @@ export async function startServer({win, upstreamProxy, setProxyErrorCallback = f log.log("--------------proxy catch err--------------", e) } }) -} - -app.on('before-quit', async e => { - e.preventDefault() - try { - await closeProxy() - log.log("--------------closeProxy success--------------") - } catch (error) { - } - app.exit() -}) +} \ No newline at end of file diff --git a/electron/main/setProxy.ts b/electron/main/setProxy.ts index dbc9503..74c8042 100755 --- a/electron/main/setProxy.ts +++ b/electron/main/setProxy.ts @@ -125,4 +125,4 @@ function getMacAvailableNetworks() { } }) }) -} +} \ No newline at end of file diff --git a/electron/main/utils.ts b/electron/main/utils.ts index 632f440..0452d33 100755 --- a/electron/main/utils.ts +++ b/electron/main/utils.ts @@ -144,4 +144,17 @@ function suffix(type: string) { return "" } -export {downloadFile, toSize, decodeWxFile, suffix} +function getCurrentDateTimeFormatted() { + const now = new Date(); + + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始,所以要加1 + const day = String(now.getDate()).padStart(2, '0'); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + + return `${year}${month}${day}${hours}${minutes}${seconds}`; +} + +export {downloadFile, toSize, decodeWxFile, suffix, getCurrentDateTimeFormatted} diff --git a/electron/res/icon/icons/mac/icon.icns b/electron/res/icon/mac.icns old mode 100755 new mode 100644 similarity index 100% rename from electron/res/icon/icons/mac/icon.icns rename to electron/res/icon/mac.icns diff --git a/electron/res/icon/icons/win/icon.ico b/electron/res/icon/win.ico old mode 100755 new mode 100644 similarity index 100% rename from electron/res/icon/icons/win/icon.ico rename to electron/res/icon/win.ico diff --git a/electron/res/mac/aria2/aria2.conf b/electron/res/mac/aria2/aria2.conf new file mode 100644 index 0000000..cd66159 --- /dev/null +++ b/electron/res/mac/aria2/aria2.conf @@ -0,0 +1,23 @@ +#允许rpc +enable-rpc=true +#允许非外部访问 +rpc-listen-all=true + +#最大同时下载数(任务数), 路由建议值: 3 +max-concurrent-downloads=3 +#断点续传 +continue=true +#同服务器连接数 +max-connection-per-server=10 +#最小文件分片大小, 下载线程数上限取决于能分出多少片, 对于小文件重要 +min-split-size=10M +#单文件最大线程数, 路由建议值: 5 +split=10 +#下载速度限制 +max-overall-download-limit=0 +#单文件速度限制 +max-download-limit=0 +#上传速度限制 +max-overall-upload-limit=0 +#单文件速度限制 +max-upload-limit=0 \ No newline at end of file diff --git a/electron/res/mac/aria2/arm64/aria2c b/electron/res/mac/aria2/arm64/aria2c new file mode 100644 index 0000000..f4a2740 Binary files /dev/null and b/electron/res/mac/aria2/arm64/aria2c differ diff --git a/electron/res/mac/aria2/x64/aria2c b/electron/res/mac/aria2/x64/aria2c new file mode 100644 index 0000000..b0b1cab Binary files /dev/null and b/electron/res/mac/aria2/x64/aria2c differ diff --git a/electron/res/win/aria2/aria2.conf b/electron/res/win/aria2/aria2.conf new file mode 100644 index 0000000..d57b6d6 --- /dev/null +++ b/electron/res/win/aria2/aria2.conf @@ -0,0 +1,25 @@ +#允许rpc +enable-rpc=true +#允许非外部访问 +rpc-listen-all=true + +#最大同时下载数(任务数), 路由建议值: 3 +max-concurrent-downloads=3 +#断点续传 +continue=true +#同服务器连接数 +max-connection-per-server=10 +#最小文件分片大小, 下载线程数上限取决于能分出多少片, 对于小文件重要 +min-split-size=10M +#单文件最大线程数, 路由建议值: 5 +split=10 +#下载速度限制 +max-overall-download-limit=0 +#单文件速度限制 +max-download-limit=0 +#上传速度限制 +max-overall-upload-limit=0 +#单文件速度限制 +max-upload-limit=0 + +check-certificate=false \ No newline at end of file diff --git a/electron/res/win/aria2/aria2c.exe b/electron/res/win/aria2/aria2c.exe new file mode 100644 index 0000000..d950831 Binary files /dev/null and b/electron/res/win/aria2/aria2c.exe differ diff --git a/electron/res/openssl/HashInfo.txt b/electron/res/win/openssl/HashInfo.txt old mode 100755 new mode 100644 similarity index 100% rename from electron/res/openssl/HashInfo.txt rename to electron/res/win/openssl/HashInfo.txt diff --git a/electron/res/openssl/OpenSSL License.txt b/electron/res/win/openssl/OpenSSL License.txt old mode 100755 new mode 100644 similarity index 100% rename from electron/res/openssl/OpenSSL License.txt rename to electron/res/win/openssl/OpenSSL License.txt diff --git a/electron/res/openssl/ReadMe.txt b/electron/res/win/openssl/ReadMe.txt old mode 100755 new mode 100644 similarity index 100% rename from electron/res/openssl/ReadMe.txt rename to electron/res/win/openssl/ReadMe.txt diff --git a/electron/res/openssl/libeay32.dll b/electron/res/win/openssl/libeay32.dll old mode 100755 new mode 100644 similarity index 100% rename from electron/res/openssl/libeay32.dll rename to electron/res/win/openssl/libeay32.dll diff --git a/electron/res/openssl/openssl.cnf b/electron/res/win/openssl/openssl.cnf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/openssl/openssl.cnf rename to electron/res/win/openssl/openssl.cnf diff --git a/electron/res/openssl/openssl.exe b/electron/res/win/openssl/openssl.exe old mode 100755 new mode 100644 similarity index 100% rename from electron/res/openssl/openssl.exe rename to electron/res/win/openssl/openssl.exe diff --git a/electron/res/openssl/ssleay32.dll b/electron/res/win/openssl/ssleay32.dll old mode 100755 new mode 100644 similarity index 100% rename from electron/res/openssl/ssleay32.dll rename to electron/res/win/openssl/ssleay32.dll diff --git a/electron/res/regedit-vbs/1.wsf b/electron/res/win/regedit-vbs/1.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/1.wsf rename to electron/res/win/regedit-vbs/1.wsf diff --git a/electron/res/regedit-vbs/ArchitectureAgnosticRegistry.vbs b/electron/res/win/regedit-vbs/ArchitectureAgnosticRegistry.vbs old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/ArchitectureAgnosticRegistry.vbs rename to electron/res/win/regedit-vbs/ArchitectureAgnosticRegistry.vbs diff --git a/electron/res/regedit-vbs/ArchitectureSpecificRegistry.vbs b/electron/res/win/regedit-vbs/ArchitectureSpecificRegistry.vbs old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/ArchitectureSpecificRegistry.vbs rename to electron/res/win/regedit-vbs/ArchitectureSpecificRegistry.vbs diff --git a/electron/res/regedit-vbs/JsonSafeTest.wsf b/electron/res/win/regedit-vbs/JsonSafeTest.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/JsonSafeTest.wsf rename to electron/res/win/regedit-vbs/JsonSafeTest.wsf diff --git a/electron/res/regedit-vbs/regCreateKey.wsf b/electron/res/win/regedit-vbs/regCreateKey.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/regCreateKey.wsf rename to electron/res/win/regedit-vbs/regCreateKey.wsf diff --git a/electron/res/regedit-vbs/regDeleteKey.wsf b/electron/res/win/regedit-vbs/regDeleteKey.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/regDeleteKey.wsf rename to electron/res/win/regedit-vbs/regDeleteKey.wsf diff --git a/electron/res/regedit-vbs/regDeleteValue.wsf b/electron/res/win/regedit-vbs/regDeleteValue.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/regDeleteValue.wsf rename to electron/res/win/regedit-vbs/regDeleteValue.wsf diff --git a/electron/res/regedit-vbs/regList.wsf b/electron/res/win/regedit-vbs/regList.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/regList.wsf rename to electron/res/win/regedit-vbs/regList.wsf diff --git a/electron/res/regedit-vbs/regListStream.wsf b/electron/res/win/regedit-vbs/regListStream.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/regListStream.wsf rename to electron/res/win/regedit-vbs/regListStream.wsf diff --git a/electron/res/regedit-vbs/regPutValue.wsf b/electron/res/win/regedit-vbs/regPutValue.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/regPutValue.wsf rename to electron/res/win/regedit-vbs/regPutValue.wsf diff --git a/electron/res/regedit-vbs/regUtil.vbs b/electron/res/win/regedit-vbs/regUtil.vbs old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/regUtil.vbs rename to electron/res/win/regedit-vbs/regUtil.vbs diff --git a/electron/res/regedit-vbs/util.vbs b/electron/res/win/regedit-vbs/util.vbs old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/util.vbs rename to electron/res/win/regedit-vbs/util.vbs diff --git a/electron/res/regedit-vbs/wsRegReadList.wsf b/electron/res/win/regedit-vbs/wsRegReadList.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/wsRegReadList.wsf rename to electron/res/win/regedit-vbs/wsRegReadList.wsf diff --git a/electron/res/regedit-vbs/wsRegReadListStream.wsf b/electron/res/win/regedit-vbs/wsRegReadListStream.wsf old mode 100755 new mode 100644 similarity index 100% rename from electron/res/regedit-vbs/wsRegReadListStream.wsf rename to electron/res/win/regedit-vbs/wsRegReadListStream.wsf diff --git a/electron/res/win/w_c.exe b/electron/res/win/w_c.exe new file mode 100644 index 0000000..8607884 Binary files /dev/null and b/electron/res/win/w_c.exe differ diff --git a/package.json b/package.json index b8a5c84..d7e7a7f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "res-downloader", - "version": "2.0.1", + "version": "2.1.0", "main": "dist-electron/main/index.js", "description": "res-downloader(爱享素材下载器),支持视频号、小程序、抖音、快手、小红书、酷狗音乐、qq音乐、qq短视频等", "author": "putyy@qq.com", @@ -19,8 +19,8 @@ } }, "scripts": { - "dev": "vite", - "build": "vue-tsc --noEmit && vite build && electron-builder", + "dev": "node script/hoxy.ts && vite", + "build": "node script/hoxy.ts && vue-tsc --noEmit && vite build && electron-builder", "preview": "vite preview" }, "devDependencies": { diff --git a/script/hoxy.ts b/script/hoxy.ts new file mode 100644 index 0000000..e6be9a5 --- /dev/null +++ b/script/hoxy.ts @@ -0,0 +1,7 @@ +const fs = require('fs'); +const path = require('path'); +const currentDir = process.cwd(); + +// 移动文件 +fs.copyFile(currentDir + '/override/hoxy/lib/cycle.js', currentDir + '/node_modules/hoxy/lib/cycle.js', fs.constants.COPYFILE_FICLONE, (err) => { +}); \ No newline at end of file diff --git a/src/views/Index.vue b/src/views/Index.vue index 7aeb6d3..f5672ed 100755 --- a/src/views/Index.vue +++ b/src/views/Index.vue @@ -54,7 +54,7 @@ onMounted(() => { }) ipcRenderer.on('on_down_file_schedule', (res: any, data: any) => { - loading.value && loading.value.setText(`已下载 ${data.schedule}%`) + loading.value && loading.value.setText(`${data.schedule}%`) }) ipcRenderer.invoke('invoke_app_is_init').then((isInit: boolean) => { @@ -119,22 +119,12 @@ const handleBatchDown = async () => { text: '下载中', background: 'rgba(0, 0, 0, 0.7)', }) - + const quality = localStorageCache.get("quality") ? localStorageCache.get("quality") : -1 for (const item of multipleSelection.value) { - let result = await ipcRenderer.invoke('invoke_file_exists', { - save_path: save_dir, - url: item.url, - }) - - if (result.is_file) { - item.progress_bar = "100%" - item.save_path = result.fileName - continue - } - let downRes = await ipcRenderer.invoke('invoke_down_file', { data: Object.assign({}, item), save_path: save_dir, + quality: quality, }) if (downRes !== false) { @@ -148,9 +138,7 @@ const handleBatchDown = async () => { const handleDown = async (index: number, row: any) => { - - let save_dir = localStorageCache.get("save_dir") - + const save_dir = localStorageCache.get("save_dir") if (!save_dir) { ElMessage({ message: '请设置保存目录', @@ -165,26 +153,11 @@ const handleDown = async (index: number, row: any) => { background: 'rgba(0, 0, 0, 0.7)', }) - let result = await ipcRenderer.invoke('invoke_file_exists', { - save_path: save_dir, - url: row.url, - description: row.description - }) - - if (result.is_file) { - tableData.value[index].progress_bar = "100%" - tableData.value[index].save_path = result.fileName - ElMessage({ - message: "文件已存在(" + result.fileName + ")", - type: 'warning', - }) - loading.value.close() - localStorageCache.set("res-table-data", tableData.value, -1) - return - } + const quality = localStorageCache.get("quality") ? localStorageCache.get("quality") : -1 ipcRenderer.invoke('invoke_down_file', { data: Object.assign({}, tableData.value[index]), - save_path: save_dir + save_path: save_dir, + quality: quality, }).then((res) => { if (res !== false) { tableData.value[index].progress_bar = "100%" @@ -334,7 +307,7 @@ el-container.container template(#default="scope") div.actions template(v-if="scope.row.type_str !== 'm3u8'" ) - el-button(v-if="!scope.row.save_path" link type="primary" @click="handleDown(scope.$index, scope.row)") {{scope.row.decode_key || scope.row.decryptor_array ? "解密下载(视频号)" : "下载"}} + el-button(link type="primary" @click="handleDown(scope.$index, scope.row)") {{scope.row.decode_key || scope.row.decryptor_array ? "解密下载(视频号)" : "下载"}} el-button(v-if="scope.row.decode_key || scope.row.decryptor_array" link type="primary" @click="decodeWxFile(scope.$index)") 视频解密(视频号) el-button(link type="primary" @click="handlePreview(scope.$index, scope.row)") 窗口预览 el-button(link type="primary" @click="handleCopy(scope.row.url)") 复制链接 diff --git a/src/views/Setting.vue b/src/views/Setting.vue index e1e33d8..7a51313 100755 --- a/src/views/Setting.vue +++ b/src/views/Setting.vue @@ -7,9 +7,26 @@ import {ElMessage} from "element-plus" const saveDir = ref("") const upstream_proxy = ref("") const upstream_proxy_old = ref("") +const quality = ref("-1") +const qualityOptions = ref([ + { + value: '-1', + label: '默认(推荐)' + }, { + value: '0', + label: '高画质' + }, { + value: '1', + label: '中画质' + }, { + value: '2', + label: '低画质' + } +]) onMounted(() => { saveDir.value = localStorageCache.get("save_dir") ? localStorageCache.get("save_dir") : "" + quality.value = localStorageCache.get("quality") ? localStorageCache.get("quality") : "-1" upstream_proxy.value = localStorageCache.get("upstream_proxy") ? localStorageCache.get("upstream_proxy") : "" upstream_proxy_old.value = upstream_proxy.value }) @@ -25,22 +42,29 @@ const selectSaveDir = () => { const onSetting = () => { localStorageCache.set("save_dir", saveDir.value, -1) localStorageCache.set("upstream_proxy", upstream_proxy.value, -1) + localStorageCache.set("quality", quality.value, -1) if (upstream_proxy_old.value != upstream_proxy.value){ ipcRenderer.invoke('invoke_window_restart') } ElMessage({ - message: "操作成功", + message: "保存成功", type: 'success', }) }