mirror of
https://github.com/putyy/res-downloader.git
synced 2026-01-12 14:14:55 +08:00
新增代理设置、更换证书、mac下增加http的代理设置、完善image content-type等
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,6 +10,7 @@ lerna-debug.log*
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
temp
|
temp
|
||||||
|
test
|
||||||
dist-ssr
|
dist-ssr
|
||||||
dist-electron
|
dist-electron
|
||||||
release
|
release
|
||||||
@@ -28,4 +29,5 @@ release
|
|||||||
|
|
||||||
# lockfile
|
# lockfile
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
16
README.md
16
README.md
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
🎯 基于 [electron-vite-vue](https://github.com/electron-vite/electron-vite-vue.git)
|
🎯 基于 [electron-vite-vue](https://github.com/electron-vite/electron-vite-vue.git)
|
||||||
📦 操作简单、可获取不同类型的资源
|
📦 操作简单、可获取不同类型的资源
|
||||||
💪 支持获取视频、音频、图片、m3u8
|
💪 支持获取视频、音频、图片、m3u8
|
||||||
🖥 支持获取视频号、抖音、快手、小红书、酷狗音乐、qq音乐等网络资源
|
🖥 支持获取视频号、抖音、快手、小红书、酷狗音乐、qq音乐、微信小程序等网络资源
|
||||||
|
🍊 支持设置代理以获取特殊网络下的资源
|
||||||
|
|
||||||
## 软件下载
|
## 软件下载
|
||||||
🆕 [github下载](https://github.com/putyy/res-downloader/releases)
|
🆕 [github下载](https://github.com/putyy/res-downloader/releases)
|
||||||
@@ -28,9 +29,6 @@ yarn run build --mac
|
|||||||
yarn run build --win
|
yarn run build --win
|
||||||
```
|
```
|
||||||
|
|
||||||
## 软件截图
|
|
||||||

|
|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
> 1. 打开本软件
|
> 1. 打开本软件
|
||||||
> 2. 软件首页选择要获取的资源类型(默认选中的视频)
|
> 2. 软件首页选择要获取的资源类型(默认选中的视频)
|
||||||
@@ -42,6 +40,13 @@ yarn run build --win
|
|||||||
> > 手动检测系统代理是否设置正确 本软件代理地址: 127.0.0.1:8899
|
> > 手动检测系统代理是否设置正确 本软件代理地址: 127.0.0.1:8899
|
||||||
> 2. 关闭软件后无法正常上网
|
> 2. 关闭软件后无法正常上网
|
||||||
> > 手动关闭系统代理设置
|
> > 手动关闭系统代理设置
|
||||||
|
> 3. 视频号抓取流程
|
||||||
|
> > 将需要下载的视频发给好友或者文件助手 再打开即可拦截,通常会出现解密下载按钮
|
||||||
|
> >
|
||||||
|
> > 大视频可以复制链接通过其他工具加速下载,然后再通过对应的视频操作项进行"视频解密"
|
||||||
|
|
||||||
|
## 软件截图
|
||||||
|

|
||||||
|
|
||||||
## 实现原理
|
## 实现原理
|
||||||
> 通过代理网络抓包拦截响应,筛选出有用的资源,同fiddler、charles等抓包软件、浏览器F12打开控制也能达到目的,只不过这些软件需要手动进行筛选,对于小白用户上手还是有点难度,所以就有了本项目这样的软件。
|
> 通过代理网络抓包拦截响应,筛选出有用的资源,同fiddler、charles等抓包软件、浏览器F12打开控制也能达到目的,只不过这些软件需要手动进行筛选,对于小白用户上手还是有点难度,所以就有了本项目这样的软件。
|
||||||
@@ -49,3 +54,4 @@ yarn run build --win
|
|||||||
## 参考项目
|
## 参考项目
|
||||||
|
|
||||||
- [WeChatVideoDownloader](https://github.com/lecepin/WeChatVideoDownloader) 原项目是react写的,本项目参考原项目用vue3重写了一下,核心逻辑没什么变化,主要是增加了一些新的功能,再次感谢!
|
- [WeChatVideoDownloader](https://github.com/lecepin/WeChatVideoDownloader) 原项目是react写的,本项目参考原项目用vue3重写了一下,核心逻辑没什么变化,主要是增加了一些新的功能,再次感谢!
|
||||||
|
|
||||||
|
|||||||
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -14,6 +14,7 @@ declare module 'vue' {
|
|||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElHeader: typeof import('element-plus/es')['ElHeader']
|
ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
ElMain: typeof import('element-plus/es')['ElMain']
|
ElMain: typeof import('element-plus/es')['ElMain']
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||||
|
|||||||
@@ -13,14 +13,13 @@ const EXECUTABLE_PATH = path.join(
|
|||||||
)
|
)
|
||||||
|
|
||||||
const HOME_PATH = path.join(os.homedir(), '.res-downloader@putyy')
|
const HOME_PATH = path.join(os.homedir(), '.res-downloader@putyy')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
IS_DEV: isDev,
|
IS_DEV: isDev,
|
||||||
EXECUTABLE_PATH,
|
EXECUTABLE_PATH,
|
||||||
HOME_PATH,
|
HOME_PATH,
|
||||||
CERT_PRIVATE_PATH: path.join(EXECUTABLE_PATH, './keys/private.pem'),
|
CERT_PRIVATE_PATH: path.join(EXECUTABLE_PATH, './keys/private.pem'),
|
||||||
CERT_PUBLIC_PATH: path.join(EXECUTABLE_PATH, './keys/public.pem'),
|
CERT_PUBLIC_PATH: path.join(EXECUTABLE_PATH, './keys/public.pem'),
|
||||||
INSTALL_CERT_FLAG: path.join(HOME_PATH, './installed.lock'),
|
INSTALL_CERT_FLAG: path.join(HOME_PATH, './res-downloader-installed.lock'),
|
||||||
WIN_CERT_INSTALL_HELPER: path.join(EXECUTABLE_PATH, './w_c.exe'),
|
WIN_CERT_INSTALL_HELPER: path.join(EXECUTABLE_PATH, './w_c.exe'),
|
||||||
APP_CN_NAME: '爱享素材下载器',
|
APP_CN_NAME: '爱享素材下载器',
|
||||||
APP_EN_NAME: 'ResDownloader',
|
APP_EN_NAME: 'ResDownloader',
|
||||||
|
|||||||
@@ -156,11 +156,6 @@ function createPreviewWindow(parent: BrowserWindow) {
|
|||||||
// previewWin.hide()
|
// previewWin.hide()
|
||||||
previewWin.setTitle("预览")
|
previewWin.setTitle("预览")
|
||||||
|
|
||||||
previewWin.webContents.session.on('will-download', (event, item, webContents) => {
|
|
||||||
// console.log("取消下载")
|
|
||||||
item.cancel()
|
|
||||||
})
|
|
||||||
|
|
||||||
previewWin.on("page-title-updated", (event) => {
|
previewWin.on("page-title-updated", (event) => {
|
||||||
// 阻止该事件
|
// 阻止该事件
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|||||||
@@ -1,42 +1,20 @@
|
|||||||
import {ipcMain, dialog, BrowserWindow, app, shell} from 'electron'
|
import {ipcMain, dialog, BrowserWindow, app, shell} from 'electron'
|
||||||
import {startServer} from './proxyServer'
|
import {startServer} from './proxyServer'
|
||||||
import {installCert, checkCertInstalled} from './cert'
|
import {installCert, checkCertInstalled} from './cert'
|
||||||
import {downloadFile, decodeWxFile} from './utils'
|
import {downloadFile, decodeWxFile, suffix} from './utils'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {hexMD5} from '../../src/common/md5'
|
import {hexMD5} from '../../src/common/md5'
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import CryptoJS from 'crypto-js'
|
import CryptoJS from 'crypto-js'
|
||||||
import {closeProxy, setProxy} from "./setProxy"
|
import {floor} from "lodash"
|
||||||
import log from "electron-log"
|
|
||||||
import {floor} from "lodash";
|
|
||||||
|
|
||||||
let getMac = require("getmac").default
|
let getMac = require("getmac").default
|
||||||
let win: BrowserWindow
|
let win: BrowserWindow
|
||||||
let previewWin: BrowserWindow
|
let previewWin: BrowserWindow
|
||||||
let isStartProxy = false
|
let isStartProxy = false
|
||||||
let isOpenProxy = false
|
|
||||||
|
|
||||||
let aesKey = "as5d45as4d6qe6wqfar6gt4749q6y7w6h34v64tv7t37ty5qwtv6t6qv"
|
let aesKey = "as5d45as4d6qe6wqfar6gt4749q6y7w6h34v64tv7t37ty5qwtv6t6qv"
|
||||||
|
|
||||||
const suffix = (type: string) => {
|
|
||||||
switch (type) {
|
|
||||||
case "video/mp4":
|
|
||||||
return ".mp4";
|
|
||||||
case "image/png":
|
|
||||||
return ".png";
|
|
||||||
case "image/webp":
|
|
||||||
return ".webp";
|
|
||||||
case "image/svg+xml":
|
|
||||||
return ".svg";
|
|
||||||
case "image/gif":
|
|
||||||
return ".gif";
|
|
||||||
case "audio/mpeg":
|
|
||||||
return ".mp3";
|
|
||||||
case "application/vnd.apple.mpegurl":
|
|
||||||
return ".m3u8";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function initIPC() {
|
export default function initIPC() {
|
||||||
|
|
||||||
ipcMain.handle('invoke_app_is_init', async (event, arg) => {
|
ipcMain.handle('invoke_app_is_init', async (event, arg) => {
|
||||||
@@ -44,47 +22,26 @@ export default function initIPC() {
|
|||||||
return checkCertInstalled()
|
return checkCertInstalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('invoke_init_app', (event, arg) => {
|
ipcMain.handle('invoke_init_app', (event, arg) => {
|
||||||
// 开始 初始化应用 安装证书相关
|
// 开始 初始化应用 安装证书相关
|
||||||
// console.log('invoke_init_app')
|
installCert(false).then(r => {})
|
||||||
return installCert(false)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('invoke_start_proxy', async (event, arg) => {
|
ipcMain.handle('invoke_start_proxy', (event, arg) => {
|
||||||
// 启动代理服务
|
// 启动代理服务
|
||||||
if (isStartProxy) {
|
if (isStartProxy) {
|
||||||
if (isOpenProxy === false) {
|
|
||||||
isOpenProxy = true
|
|
||||||
setProxy('127.0.0.1', 8899)
|
|
||||||
.then(() => {
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isStartProxy = true
|
isStartProxy = true
|
||||||
isOpenProxy = true
|
|
||||||
return startServer({
|
return startServer({
|
||||||
win: win,
|
win: win,
|
||||||
|
upstreamProxy: arg.upstream_proxy ? arg.upstream_proxy : "",
|
||||||
setProxyErrorCallback: err => {
|
setProxyErrorCallback: err => {
|
||||||
isStartProxy = false
|
|
||||||
isOpenProxy = false
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('invoke_close_proxy', (event, arg) => {
|
|
||||||
// 关闭代理
|
|
||||||
try {
|
|
||||||
isOpenProxy = false
|
|
||||||
return closeProxy()
|
|
||||||
} catch (error) {
|
|
||||||
log.log("--------------closeProxy error--------------", error)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcMain.handle('invoke_select_down_dir', async (event, arg) => {
|
ipcMain.handle('invoke_select_down_dir', async (event, arg) => {
|
||||||
// 选择下载位置
|
// 选择下载位置
|
||||||
const result = dialog.showOpenDialogSync({title: '保存', properties: ['openDirectory']})
|
const result = dialog.showOpenDialogSync({title: '保存', properties: ['openDirectory']})
|
||||||
@@ -123,6 +80,10 @@ export default function initIPC() {
|
|||||||
|
|
||||||
let url_sign = hexMD5(down_url)
|
let url_sign = hexMD5(down_url)
|
||||||
let save_path_file = `${save_path}/${url_sign}` + suffix(data.type)
|
let save_path_file = `${save_path}/${url_sign}` + suffix(data.type)
|
||||||
|
if (process.platform === 'win32'){
|
||||||
|
save_path_file = `${save_path}\\${url_sign}` + suffix(data.type)
|
||||||
|
}
|
||||||
|
|
||||||
if (fs.existsSync(save_path_file)) {
|
if (fs.existsSync(save_path_file)) {
|
||||||
return {fullFileName: save_path_file, totalLen: ""}
|
return {fullFileName: save_path_file, totalLen: ""}
|
||||||
}
|
}
|
||||||
@@ -135,7 +96,6 @@ export default function initIPC() {
|
|||||||
win?.webContents.send('on_down_file_schedule', {schedule: floor(res * 100)})
|
win?.webContents.send('on_down_file_schedule', {schedule: floor(res * 100)})
|
||||||
}
|
}
|
||||||
).catch(err => {
|
).catch(err => {
|
||||||
// console.log('invoke_down_file:err', err)
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -156,6 +116,8 @@ export default function initIPC() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('url', url)
|
||||||
|
|
||||||
previewWin.loadURL(url).then(r => {
|
previewWin.loadURL(url).then(r => {
|
||||||
return
|
return
|
||||||
}).catch(res => {
|
}).catch(res => {
|
||||||
@@ -171,6 +133,11 @@ export default function initIPC() {
|
|||||||
ipcMain.handle('invoke_open_file_dir', (event, {save_path}) => {
|
ipcMain.handle('invoke_open_file_dir', (event, {save_path}) => {
|
||||||
shell.showItemInFolder(save_path)
|
shell.showItemInFolder(save_path)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('invoke_window_restart', (event) => {
|
||||||
|
app.relaunch()
|
||||||
|
app.exit()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setWin(w, p) {
|
export function setWin(w, p) {
|
||||||
|
|||||||
@@ -76,106 +76,128 @@ setTimeout(() => {
|
|||||||
|
|
||||||
export async function startServer({
|
export async function startServer({
|
||||||
win,
|
win,
|
||||||
|
upstreamProxy,
|
||||||
setProxyErrorCallback = f => f,
|
setProxyErrorCallback = f => f,
|
||||||
}) {
|
}) {
|
||||||
return new Promise(async (resolve: any, reject) => {
|
return new Promise(async (resolve: any, reject) => {
|
||||||
const proxy = hoXy.createServer({
|
try {
|
||||||
|
const proxy = hoXy.createServer({
|
||||||
|
upstreamProxy: upstreamProxy,
|
||||||
certAuthority: {
|
certAuthority: {
|
||||||
key: fs.readFileSync(CONFIG.CERT_PRIVATE_PATH),
|
key: fs.readFileSync(CONFIG.CERT_PRIVATE_PATH),
|
||||||
cert: fs.readFileSync(CONFIG.CERT_PUBLIC_PATH),
|
cert: fs.readFileSync(CONFIG.CERT_PUBLIC_PATH),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.listen(port, () => {
|
.listen(port, () => {
|
||||||
setProxy('127.0.0.1', port)
|
setProxy('127.0.0.1', port)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
// log.log("--------------setProxy success--------------")
|
resolve()
|
||||||
resolve()
|
})
|
||||||
})
|
.catch((err) => {
|
||||||
.catch((err) => {
|
setProxyErrorCallback(err);
|
||||||
// log.log("--------------setProxy error--------------")
|
reject('setting proxy err: '+ err.toString());
|
||||||
// setProxyErrorCallback(data);
|
});
|
||||||
setProxyErrorCallback({});
|
|
||||||
reject('设置代理失败');
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.on('error', err => {
|
|
||||||
log.log("--------------proxy err--------------", err)
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
proxy.intercept(
|
|
||||||
{
|
|
||||||
phase: 'request',
|
|
||||||
hostname: 'res-downloader.666666.com',
|
|
||||||
as: 'json',
|
|
||||||
},
|
|
||||||
(req, res) => {
|
|
||||||
// console.log('req.json: ', req.json)
|
|
||||||
res.string = 'ok'
|
|
||||||
res.statusCode = 200
|
|
||||||
let url_sign: string = hexMD5(req.json.url)
|
|
||||||
let urlInfo = urlTool.parse(req.json.url, true)
|
|
||||||
win?.webContents?.send?.('on_get_queue', {
|
|
||||||
url_sign: url_sign,
|
|
||||||
url: req.json.url,
|
|
||||||
down_url: req.json.url,
|
|
||||||
high_url: '',
|
|
||||||
platform: urlInfo.hostname,
|
|
||||||
size: toSize(req.json.size ?? 0),
|
|
||||||
type: "video/mp4",
|
|
||||||
type_str: 'video',
|
|
||||||
progress_bar: '',
|
|
||||||
save_path: '',
|
|
||||||
downing: false,
|
|
||||||
decode_key: req.json.decode_key,
|
|
||||||
description: req.json.description,
|
|
||||||
uploader: '',
|
|
||||||
})
|
})
|
||||||
},
|
.on('error', err => {
|
||||||
);
|
setProxyErrorCallback(err);
|
||||||
|
reject('proxy service err: ' + err.toString());
|
||||||
|
});
|
||||||
|
|
||||||
proxy.intercept(
|
|
||||||
{
|
|
||||||
phase: 'response',
|
|
||||||
hostname: 'channels.weixin.qq.com',
|
|
||||||
as: 'string',
|
|
||||||
},
|
|
||||||
async (req, res) => {
|
|
||||||
// console.log('inject[channels.weixin.qq.com] req.url:', req.url);
|
|
||||||
if (req.url.includes('/web/pages/feed') || req.url.includes('/web/pages/home')) {
|
|
||||||
res.string = res.string.replace('</body>', '\n<script>' + injection_script1 + '</script>\n</body>');
|
|
||||||
res.statusCode = 200;
|
|
||||||
// console.log('inject[channels.weixin.qq.com]:', req.url, res.string.length);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
proxy.intercept(
|
proxy.intercept(
|
||||||
{
|
{
|
||||||
phase: 'response',
|
phase: 'request',
|
||||||
},
|
hostname: 'res-downloader.666666.com',
|
||||||
async (req, res) => {
|
as: 'json',
|
||||||
// 拦截响应
|
},
|
||||||
let ctype = res?._data?.headers?.['content-type']
|
(req, res) => {
|
||||||
let url_sign: string = hexMD5(req.fullUrl())
|
res.string = 'ok'
|
||||||
let res_url = req.fullUrl()
|
res.statusCode = 200
|
||||||
let urlInfo = urlTool.parse(res_url, true)
|
let url_sign: string = hexMD5(req.json.url)
|
||||||
switch (ctype) {
|
let urlInfo = urlTool.parse(req.json.url, true)
|
||||||
case "video/mp4":
|
win?.webContents?.send?.('on_get_queue', {
|
||||||
if (videoList.hasOwnProperty(url_sign) === false) {
|
url_sign: url_sign,
|
||||||
videoList[url_sign] = req.fullUrl()
|
url: req.json.url,
|
||||||
let high_url = ''
|
down_url: req.json.url,
|
||||||
let down_url = res_url
|
high_url: '',
|
||||||
// console.log('down_url', down_url)
|
platform: urlInfo.hostname,
|
||||||
|
size: toSize(req.json.size ?? 0),
|
||||||
|
type: "video/mp4",
|
||||||
|
type_str: 'video',
|
||||||
|
progress_bar: '',
|
||||||
|
save_path: '',
|
||||||
|
downing: false,
|
||||||
|
decode_key: req.json.decode_key,
|
||||||
|
description: req.json.description,
|
||||||
|
uploader: '',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
proxy.intercept(
|
||||||
|
{
|
||||||
|
phase: 'response',
|
||||||
|
hostname: 'channels.weixin.qq.com',
|
||||||
|
as: 'string',
|
||||||
|
},
|
||||||
|
async (req, res) => {
|
||||||
|
if (req.url.includes('/web/pages/feed') || req.url.includes('/web/pages/home')) {
|
||||||
|
res.string = res.string.replace('</body>', '\n<script>' + injection_script1 + '</script>\n</body>');
|
||||||
|
res.statusCode = 200;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
proxy.intercept(
|
||||||
|
{
|
||||||
|
phase: 'response',
|
||||||
|
},
|
||||||
|
async (req, res) => {
|
||||||
|
// 拦截响应
|
||||||
|
let ctype = res?._data?.headers?.['content-type']
|
||||||
|
let url_sign: string = hexMD5(req.fullUrl())
|
||||||
|
let res_url = req.fullUrl()
|
||||||
|
let urlInfo = urlTool.parse(res_url, true)
|
||||||
|
switch (ctype) {
|
||||||
|
case "video/mp4":
|
||||||
|
if (videoList.hasOwnProperty(url_sign) === false) {
|
||||||
|
videoList[url_sign] = req.fullUrl()
|
||||||
|
let high_url = ''
|
||||||
|
let down_url = res_url
|
||||||
|
win?.webContents?.send?.('on_get_queue', {
|
||||||
|
url_sign: url_sign,
|
||||||
|
url: down_url,
|
||||||
|
down_url: down_url,
|
||||||
|
high_url: high_url,
|
||||||
|
platform: urlInfo.hostname,
|
||||||
|
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
||||||
|
type: ctype,
|
||||||
|
type_str: 'video',
|
||||||
|
progress_bar: '',
|
||||||
|
save_path: '',
|
||||||
|
downing: false,
|
||||||
|
decode_key: '',
|
||||||
|
description: '',
|
||||||
|
uploader: '',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "image/png":
|
||||||
|
case "image/webp":
|
||||||
|
case "image/jpeg":
|
||||||
|
case "image/jpg":
|
||||||
|
case "image/svg+xml":
|
||||||
|
case "image/gif":
|
||||||
|
case "image/avif":
|
||||||
win?.webContents?.send?.('on_get_queue', {
|
win?.webContents?.send?.('on_get_queue', {
|
||||||
url_sign: url_sign,
|
url_sign: url_sign,
|
||||||
url: down_url,
|
url: res_url,
|
||||||
down_url: down_url,
|
down_url: res_url,
|
||||||
high_url: high_url,
|
high_url: '',
|
||||||
platform: urlInfo.hostname,
|
platform: urlInfo.hostname,
|
||||||
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
||||||
type: ctype,
|
type: ctype,
|
||||||
type_str: 'video',
|
type_str: 'image',
|
||||||
progress_bar: '',
|
progress_bar: '',
|
||||||
save_path: '',
|
save_path: '',
|
||||||
downing: false,
|
downing: false,
|
||||||
@@ -183,70 +205,51 @@ export async function startServer({
|
|||||||
description: '',
|
description: '',
|
||||||
uploader: '',
|
uploader: '',
|
||||||
})
|
})
|
||||||
}
|
break;
|
||||||
break;
|
case "audio/mpeg":
|
||||||
case "image/png":
|
win?.webContents?.send?.('on_get_queue', {
|
||||||
case "image/webp":
|
url_sign: url_sign,
|
||||||
case "image/svg+xml":
|
url: res_url,
|
||||||
case "image/gif":
|
down_url: res_url,
|
||||||
win?.webContents?.send?.('on_get_queue', {
|
high_url: '',
|
||||||
url_sign: url_sign,
|
platform: urlInfo.hostname,
|
||||||
url: res_url,
|
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
||||||
down_url: res_url,
|
type: ctype,
|
||||||
high_url: '',
|
type_str: 'audio',
|
||||||
platform: urlInfo.hostname,
|
progress_bar: '',
|
||||||
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
save_path: '',
|
||||||
type: ctype,
|
downing: false,
|
||||||
type_str: 'image',
|
decode_key: '',
|
||||||
progress_bar: '',
|
description: '',
|
||||||
save_path: '',
|
uploader: '',
|
||||||
downing: false,
|
})
|
||||||
decode_key: '',
|
break;
|
||||||
description: '',
|
case "application/vnd.apple.mpegurl":
|
||||||
uploader: '',
|
win.webContents?.send?.('on_get_queue', {
|
||||||
})
|
url_sign: url_sign,
|
||||||
break;
|
url: res_url,
|
||||||
case "audio/mpeg":
|
down_url: res_url,
|
||||||
win?.webContents?.send?.('on_get_queue', {
|
high_url: '',
|
||||||
url_sign: url_sign,
|
platform: urlInfo.hostname,
|
||||||
url: res_url,
|
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
||||||
down_url: res_url,
|
type: ctype,
|
||||||
high_url: '',
|
type_str: 'm3u8',
|
||||||
platform: urlInfo.hostname,
|
progress_bar: '',
|
||||||
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
save_path: '',
|
||||||
type: ctype,
|
downing: false,
|
||||||
type_str: 'audio',
|
decode_key: '',
|
||||||
progress_bar: '',
|
description: '',
|
||||||
save_path: '',
|
uploader: '',
|
||||||
downing: false,
|
})
|
||||||
decode_key: '',
|
break;
|
||||||
description: '',
|
|
||||||
uploader: '',
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
case "application/vnd.apple.mpegurl":
|
|
||||||
win.webContents?.send?.('on_get_queue', {
|
|
||||||
url_sign: url_sign,
|
|
||||||
url: res_url,
|
|
||||||
down_url: res_url,
|
|
||||||
high_url: '',
|
|
||||||
platform: urlInfo.hostname,
|
|
||||||
size: toSize(res?._data?.headers?.['content-length'] ?? 0),
|
|
||||||
type: ctype,
|
|
||||||
type_str: 'm3u8',
|
|
||||||
progress_bar: '',
|
|
||||||
save_path: '',
|
|
||||||
downing: false,
|
|
||||||
decode_key: '',
|
|
||||||
description: '',
|
|
||||||
uploader: '',
|
|
||||||
})
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
} catch (e) {
|
||||||
|
log.log("--------------proxy catch err--------------", e)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,13 @@ export async function setProxy(host, port) {
|
|||||||
if (error) {
|
if (error) {
|
||||||
reject(null)
|
reject(null)
|
||||||
} else {
|
} else {
|
||||||
resolve(network)
|
exec(`networksetup -setwebproxy "${network}" ${host} ${port}`, error => {
|
||||||
|
if (error) {
|
||||||
|
reject(null)
|
||||||
|
} else {
|
||||||
|
resolve(network)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -63,7 +69,13 @@ export async function closeProxy() {
|
|||||||
if (error) {
|
if (error) {
|
||||||
reject(null)
|
reject(null)
|
||||||
} else {
|
} else {
|
||||||
resolve(network)
|
exec(`networksetup -setwebproxystate "${network}" off`, error => {
|
||||||
|
if (error) {
|
||||||
|
reject(null)
|
||||||
|
} else {
|
||||||
|
resolve(network)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import {Transform } from 'stream'
|
import {Transform } from 'stream'
|
||||||
import {getDecryptionArray} from '../wxjs/decrypt'
|
import {getDecryptionArray} from '../wxjs/decrypt.js'
|
||||||
|
|
||||||
const axios = require('axios')
|
const axios = require('axios')
|
||||||
function xorTransform(decryptionArray) {
|
function xorTransform(decryptionArray) {
|
||||||
@@ -92,4 +92,30 @@ function toSize(size: number) {
|
|||||||
return size + 'b'
|
return size + 'b'
|
||||||
}
|
}
|
||||||
|
|
||||||
export {downloadFile, toSize, decodeWxFile}
|
function suffix(type: string) {
|
||||||
|
switch (type) {
|
||||||
|
case "video/mp4":
|
||||||
|
return ".mp4";
|
||||||
|
case "image/png":
|
||||||
|
return ".png";
|
||||||
|
case "image/webp":
|
||||||
|
return ".webp";
|
||||||
|
case "image/svg+xml":
|
||||||
|
return ".svg";
|
||||||
|
case "image/gif":
|
||||||
|
return ".gif";
|
||||||
|
case "audio/mpeg":
|
||||||
|
return ".mp3";
|
||||||
|
case "application/vnd.apple.mpegurl":
|
||||||
|
return ".m3u8";
|
||||||
|
case "image/jpeg":
|
||||||
|
return ".jpeg";
|
||||||
|
case "image/jpg":
|
||||||
|
return ".jpg";
|
||||||
|
case "image/avif":
|
||||||
|
return ".avif";
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
export {downloadFile, toSize, decodeWxFile, suffix}
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
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
|
||||||
-----END RSA PRIVATE KEY-----
|
ILKEQKmPPzKs7kp/7Nz+2cT3
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
|||||||
@@ -1,27 +1,28 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
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
|
||||||
-----END RSA PRIVATE KEY-----
|
ILKEQKmPPzKs7kp/7Nz+2cT3
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIICuDCCAaACCQC7PQmrxgWOlTANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDDBJs
|
MIIDwzCCAqugAwIBAgIUFAnC6268dp/z1DR9E1UepiWgWzkwDQYJKoZIhvcNAQEL
|
||||||
ZWNlcGluLTIwMjItMDUtMTkwIBcNMjIwNTE5MTI1NjA0WhgPMzAyMTA5MTkxMjU2
|
BQAwcDELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUNob25ncWluZzESMBAGA1UEBwwJ
|
||||||
MDRaMB0xGzAZBgNVBAMMEmxlY2VwaW4tMjAyMi0wNS0xOTCCASIwDQYJKoZIhvcN
|
Q2hvbmdxaW5nMQ4wDAYDVQQKDAVnb3dhczEWMBQGA1UECwwNSVQgRGVwYXJ0bWVu
|
||||||
AQEBBQADggEPADCCAQoCggEBALJgKp94WHf2GXK34KjNUOsYByOdBAXJGzpHwqk1
|
dDERMA8GA1UEAwwIZ293YXMuY24wIBcNMjQwMjE4MDIwOTI2WhgPMjEyNDAxMjUw
|
||||||
ktclRWYyxWzHoVm/cRhWSQ9tQObMZeMXpSFm5YXrcvmE1Wv5p9ghCYd43tOvaHlC
|
MjA5MjZaMHAxCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAlDaG9uZ3FpbmcxEjAQBgNV
|
||||||
313c4YR8n/3ItCJaCYb1/tkSfte+rkyinFobjrTVbOVXhaBw6FHCEp06pGlclnni
|
BAcMCUNob25ncWluZzEOMAwGA1UECgwFZ293YXMxFjAUBgNVBAsMDUlUIERlcGFy
|
||||||
32n4Kzlu8DfIqddvJ7gcdfcpSMoG/wxC5oykUQkqcdrzsNiRK0zPC+a9H+Hlnaos
|
dG1lbnQxETAPBgNVBAMMCGdvd2FzLmNuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||||
ATsLtDR1skr4fWBvAd9VD4GuCPBWxYcmzj/XEDUD2nzkn48LmaIuQgLciW8E+ysi
|
MIIBCgKCAQEA3A7dt7eoqAaBxv2Npjo8Z7VkGvXT93jZfpgAuuNuQ5RLcnOnMzQC
|
||||||
CPYjA++G2dZk8dsaJJkNk3ogkikhfDMff/BqvveZs77yG0cCAwEAATANBgkqhkiG
|
CrrjPcLfsAMA0AIK3eUWsXXKSR9SZTJBLQRZCJHZ9AIPfA+58JVQPTjd8UIuQZJf
|
||||||
9w0BAQsFAAOCAQEADymHk+wLJAdv3p+4hHo57VLaBtwVYXc5oRUbUzgMYTTtPWIs
|
rDf6FjhPJTsLzcjTU+mT7t6lEimPEl2VWN9eXWqs9nkVrJtqLao6m1hoYfXOxRh6
|
||||||
xuILEqXftMspt6PzdEt0V1WeCWNyypsAbur/CKpAOoVjBDPIo09TiYnYIn9xt5wQ
|
96/WgBtPHcmjujryteBiSITVflDjx+YQzDGsbqw7fM52klMPd2+w/vmhJ4pxq6P7
|
||||||
AmR5kVEZheuazcvzW3C9NAY1T6QDmxNvFCiCXRbtklOg2HqFDZX+pkj8CylQ9TDk
|
Ni2OBvdXYDPIuLfPFFqG16arORjBkyNCJy19iOuh5LXh+EUX11wvbLwNgsTd8j9v
|
||||||
rroUg17b/FD1ds1uyPXzucEWfxqkOaujvsCnzrbFs9luB5VfM+QzLU+l9QRN9Tmj
|
eBSD+4HUUNQhiXiXJbs7I7cdFYthvb609QIDAQABo1MwUTAdBgNVHQ4EFgQUdI8p
|
||||||
z7CpGuP6vKvhXJLUjXkZ0q5JyL5wEAe6Ttbu+c/8HhPFKQsW6q/lQSDo0v0LGDrd
|
aY1A47rWCRvQKSTRCCk6FoMwHwYDVR0jBBgwFoAUdI8paY1A47rWCRvQKSTRCCk6
|
||||||
ikjWXhSrVjd8+qTTVgia/UNqv/wi+bkWnVdRzQ==
|
FoMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEArMCAfqidgXL7
|
||||||
-----END CERTIFICATE-----
|
cW5TAZTCqnUeKzbbqMJgk6iFsma8scMRsUXz9ZhF0UVf98376KvoJpy4vd81afbi
|
||||||
|
TehQ8wVBuKTtkHeh/MkXMWC/FU4HqSjtvxpic2+Or5dMjIrfa5VYPgzfqNaBIUh4
|
||||||
|
InD5lo8b/n5V+jdwX7RX9VYAKug6QZlCg5YSKIvgNRChb36JmrGcvsp5R0Vejnii
|
||||||
|
e3oowvgwikqm6XR6BEcRpPkztqcKST7jPFGHiXWsAqiibc+/plMW9qebhfMXEGhQ
|
||||||
|
5yVNeSxX2zqasZvP/fRy+3I5iVilxtKvJuVpPZ0UZzGS0CJ/lF67ntibktiPa3sR
|
||||||
|
D8HixYbEDg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIICuDCCAaACCQC7PQmrxgWOlTANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDDBJs
|
MIIDwzCCAqugAwIBAgIUFAnC6268dp/z1DR9E1UepiWgWzkwDQYJKoZIhvcNAQEL
|
||||||
ZWNlcGluLTIwMjItMDUtMTkwIBcNMjIwNTE5MTI1NjA0WhgPMzAyMTA5MTkxMjU2
|
BQAwcDELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUNob25ncWluZzESMBAGA1UEBwwJ
|
||||||
MDRaMB0xGzAZBgNVBAMMEmxlY2VwaW4tMjAyMi0wNS0xOTCCASIwDQYJKoZIhvcN
|
Q2hvbmdxaW5nMQ4wDAYDVQQKDAVnb3dhczEWMBQGA1UECwwNSVQgRGVwYXJ0bWVu
|
||||||
AQEBBQADggEPADCCAQoCggEBALJgKp94WHf2GXK34KjNUOsYByOdBAXJGzpHwqk1
|
dDERMA8GA1UEAwwIZ293YXMuY24wIBcNMjQwMjE4MDIwOTI2WhgPMjEyNDAxMjUw
|
||||||
ktclRWYyxWzHoVm/cRhWSQ9tQObMZeMXpSFm5YXrcvmE1Wv5p9ghCYd43tOvaHlC
|
MjA5MjZaMHAxCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAlDaG9uZ3FpbmcxEjAQBgNV
|
||||||
313c4YR8n/3ItCJaCYb1/tkSfte+rkyinFobjrTVbOVXhaBw6FHCEp06pGlclnni
|
BAcMCUNob25ncWluZzEOMAwGA1UECgwFZ293YXMxFjAUBgNVBAsMDUlUIERlcGFy
|
||||||
32n4Kzlu8DfIqddvJ7gcdfcpSMoG/wxC5oykUQkqcdrzsNiRK0zPC+a9H+Hlnaos
|
dG1lbnQxETAPBgNVBAMMCGdvd2FzLmNuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||||
ATsLtDR1skr4fWBvAd9VD4GuCPBWxYcmzj/XEDUD2nzkn48LmaIuQgLciW8E+ysi
|
MIIBCgKCAQEA3A7dt7eoqAaBxv2Npjo8Z7VkGvXT93jZfpgAuuNuQ5RLcnOnMzQC
|
||||||
CPYjA++G2dZk8dsaJJkNk3ogkikhfDMff/BqvveZs77yG0cCAwEAATANBgkqhkiG
|
CrrjPcLfsAMA0AIK3eUWsXXKSR9SZTJBLQRZCJHZ9AIPfA+58JVQPTjd8UIuQZJf
|
||||||
9w0BAQsFAAOCAQEADymHk+wLJAdv3p+4hHo57VLaBtwVYXc5oRUbUzgMYTTtPWIs
|
rDf6FjhPJTsLzcjTU+mT7t6lEimPEl2VWN9eXWqs9nkVrJtqLao6m1hoYfXOxRh6
|
||||||
xuILEqXftMspt6PzdEt0V1WeCWNyypsAbur/CKpAOoVjBDPIo09TiYnYIn9xt5wQ
|
96/WgBtPHcmjujryteBiSITVflDjx+YQzDGsbqw7fM52klMPd2+w/vmhJ4pxq6P7
|
||||||
AmR5kVEZheuazcvzW3C9NAY1T6QDmxNvFCiCXRbtklOg2HqFDZX+pkj8CylQ9TDk
|
Ni2OBvdXYDPIuLfPFFqG16arORjBkyNCJy19iOuh5LXh+EUX11wvbLwNgsTd8j9v
|
||||||
rroUg17b/FD1ds1uyPXzucEWfxqkOaujvsCnzrbFs9luB5VfM+QzLU+l9QRN9Tmj
|
eBSD+4HUUNQhiXiXJbs7I7cdFYthvb609QIDAQABo1MwUTAdBgNVHQ4EFgQUdI8p
|
||||||
z7CpGuP6vKvhXJLUjXkZ0q5JyL5wEAe6Ttbu+c/8HhPFKQsW6q/lQSDo0v0LGDrd
|
aY1A47rWCRvQKSTRCCk6FoMwHwYDVR0jBBgwFoAUdI8paY1A47rWCRvQKSTRCCk6
|
||||||
ikjWXhSrVjd8+qTTVgia/UNqv/wi+bkWnVdRzQ==
|
FoMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEArMCAfqidgXL7
|
||||||
-----END CERTIFICATE-----
|
cW5TAZTCqnUeKzbbqMJgk6iFsma8scMRsUXz9ZhF0UVf98376KvoJpy4vd81afbi
|
||||||
|
TehQ8wVBuKTtkHeh/MkXMWC/FU4HqSjtvxpic2+Or5dMjIrfa5VYPgzfqNaBIUh4
|
||||||
|
InD5lo8b/n5V+jdwX7RX9VYAKug6QZlCg5YSKIvgNRChb36JmrGcvsp5R0Vejnii
|
||||||
|
e3oowvgwikqm6XR6BEcRpPkztqcKST7jPFGHiXWsAqiibc+/plMW9qebhfMXEGhQ
|
||||||
|
5yVNeSxX2zqasZvP/fRy+3I5iVilxtKvJuVpPZ0UZzGS0CJ/lF67ntibktiPa3sR
|
||||||
|
D8HixYbEDg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|||||||
616
override/hoxy/lib/cycle.js
Normal file
616
override/hoxy/lib/cycle.js
Normal file
@@ -0,0 +1,616 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 by Greg Reimer <gregreimer@gmail.com>
|
||||||
|
* MIT License. See mit-license.txt for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _createClass = require('babel-runtime/helpers/create-class')['default'];
|
||||||
|
|
||||||
|
var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default'];
|
||||||
|
|
||||||
|
var _get = require('babel-runtime/helpers/get')['default'];
|
||||||
|
|
||||||
|
var _inherits = require('babel-runtime/helpers/inherits')['default'];
|
||||||
|
|
||||||
|
var _Promise = require('babel-runtime/core-js/promise')['default'];
|
||||||
|
|
||||||
|
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
|
||||||
|
|
||||||
|
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', {
|
||||||
|
value: true
|
||||||
|
});
|
||||||
|
|
||||||
|
var _request = require('./request');
|
||||||
|
|
||||||
|
var _request2 = _interopRequireDefault(_request);
|
||||||
|
|
||||||
|
var _response = require('./response');
|
||||||
|
|
||||||
|
var _response2 = _interopRequireDefault(_response);
|
||||||
|
|
||||||
|
var _streams = require('./streams');
|
||||||
|
|
||||||
|
var _streams2 = _interopRequireDefault(_streams);
|
||||||
|
|
||||||
|
var _await = require('await');
|
||||||
|
|
||||||
|
var _await2 = _interopRequireDefault(_await);
|
||||||
|
|
||||||
|
var _mkdirp = require('mkdirp');
|
||||||
|
|
||||||
|
var _mkdirp2 = _interopRequireDefault(_mkdirp);
|
||||||
|
|
||||||
|
var _lodash = require('lodash');
|
||||||
|
|
||||||
|
var _lodash2 = _interopRequireDefault(_lodash);
|
||||||
|
|
||||||
|
var _nodeStatic = require('node-static');
|
||||||
|
|
||||||
|
var _http = require('http');
|
||||||
|
|
||||||
|
var _http2 = _interopRequireDefault(_http);
|
||||||
|
|
||||||
|
var _https = require('https');
|
||||||
|
|
||||||
|
var _https2 = _interopRequireDefault(_https);
|
||||||
|
|
||||||
|
var _url = require('url');
|
||||||
|
|
||||||
|
var _url2 = _interopRequireDefault(_url);
|
||||||
|
|
||||||
|
var _fs = require('fs');
|
||||||
|
|
||||||
|
var _fs2 = _interopRequireDefault(_fs);
|
||||||
|
|
||||||
|
var _util = require('util');
|
||||||
|
|
||||||
|
var _util2 = _interopRequireDefault(_util);
|
||||||
|
|
||||||
|
var _path = require('path');
|
||||||
|
|
||||||
|
var _path2 = _interopRequireDefault(_path);
|
||||||
|
|
||||||
|
var _zlib = require('zlib');
|
||||||
|
|
||||||
|
var _zlib2 = _interopRequireDefault(_zlib);
|
||||||
|
|
||||||
|
var _events = require('events');
|
||||||
|
|
||||||
|
var _co = require('co');
|
||||||
|
|
||||||
|
var _co2 = _interopRequireDefault(_co);
|
||||||
|
|
||||||
|
var _uglyAdapter = require('ugly-adapter');
|
||||||
|
|
||||||
|
var _uglyAdapter2 = _interopRequireDefault(_uglyAdapter);
|
||||||
|
|
||||||
|
var _wait = require('./wait');
|
||||||
|
|
||||||
|
var _wait2 = _interopRequireDefault(_wait);
|
||||||
|
|
||||||
|
var _task = require('./task');
|
||||||
|
|
||||||
|
var _task2 = _interopRequireDefault(_task);
|
||||||
|
|
||||||
|
var _urlPath = require('./url-path');
|
||||||
|
const url = require("url");
|
||||||
|
|
||||||
|
var _urlPath2 = _interopRequireDefault(_urlPath);
|
||||||
|
|
||||||
|
var staticServer = (function () {
|
||||||
|
|
||||||
|
var getStatic = (function () {
|
||||||
|
var statics = {};
|
||||||
|
return function (docroot) {
|
||||||
|
var stat = statics[docroot];
|
||||||
|
if (!stat) {
|
||||||
|
stat = statics[docroot] = new _nodeStatic.Server(docroot);
|
||||||
|
}
|
||||||
|
return stat;
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Start up the server and serve out of various docroots.
|
||||||
|
var server = _http2['default'].createServer(function (req, resp) {
|
||||||
|
var docroot = req.headers['x-hoxy-static-docroot'];
|
||||||
|
var pDocroot = new _urlPath2['default'](docroot);
|
||||||
|
var stat = getStatic(pDocroot.toSystemPath());
|
||||||
|
stat.serve(req, resp);
|
||||||
|
}).listen(0, 'localhost');
|
||||||
|
|
||||||
|
return server;
|
||||||
|
})();
|
||||||
|
|
||||||
|
var httpsOverHttpAgent, httpsOverHttpsAgent, httpOverHttpsAgent;
|
||||||
|
var tunnelAgent = require('tunnel-agent');
|
||||||
|
var ptGetTunnelAgent = function (requestIsSSL, externalProxyUrl) {
|
||||||
|
var urlObject = url.parse(externalProxyUrl);
|
||||||
|
var protocol = urlObject.protocol || 'http:';
|
||||||
|
var port = urlObject.port;
|
||||||
|
if (!port) {
|
||||||
|
port = protocol === 'http:' ? 80 : 443;
|
||||||
|
}
|
||||||
|
var hostname = urlObject.hostname || 'localhost';
|
||||||
|
|
||||||
|
if (requestIsSSL) {
|
||||||
|
if (protocol === 'http:') {
|
||||||
|
if (!httpsOverHttpAgent) {
|
||||||
|
httpsOverHttpAgent = tunnelAgent.httpsOverHttp({
|
||||||
|
proxy: {
|
||||||
|
host: hostname,
|
||||||
|
port: port
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return httpsOverHttpAgent;
|
||||||
|
} else {
|
||||||
|
if (!httpsOverHttpsAgent) {
|
||||||
|
httpsOverHttpsAgent = tunnelAgent.httpsOverHttps({
|
||||||
|
proxy: {
|
||||||
|
host: hostname,
|
||||||
|
port: port
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return httpsOverHttpsAgent;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (protocol === 'http:') {
|
||||||
|
// if (!httpOverHttpAgent) {
|
||||||
|
// httpOverHttpAgent = tunnelAgent.httpOverHttp({
|
||||||
|
// proxy: {
|
||||||
|
// host: hostname,
|
||||||
|
// port: port
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!httpOverHttpsAgent) {
|
||||||
|
httpOverHttpsAgent = tunnelAgent.httpOverHttps({
|
||||||
|
proxy: {
|
||||||
|
host: hostname,
|
||||||
|
port: port
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return httpOverHttpsAgent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ProvisionableRequest = (function () {
|
||||||
|
function ProvisionableRequest(opts) {
|
||||||
|
_classCallCheck(this, ProvisionableRequest);
|
||||||
|
|
||||||
|
this._respProm = (0, _task2['default'])();
|
||||||
|
var h = /https/i.test(opts.protocol) ? _https2['default'] : _http2['default'];
|
||||||
|
if (opts.proxy) {
|
||||||
|
// var proxyInfo = _url2['default'].parse(opts.proxy),
|
||||||
|
// proxyPort = proxyInfo.port,
|
||||||
|
// proxyHostname = proxyInfo.hostname,
|
||||||
|
// proxyPath = 'http://' + opts.hostname + (opts.port ? ':' + opts.port : '') + opts.path;
|
||||||
|
// opts.hostname = proxyHostname;
|
||||||
|
// opts.port = proxyPort;
|
||||||
|
// opts.path = proxyPath;
|
||||||
|
opts.agent = ptGetTunnelAgent(/https/i.test(opts.protocol), opts.proxy);
|
||||||
|
// console.log('opts.agent', opts.proxy)
|
||||||
|
opts.proxy = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
this._writable = h.request(opts, this._respProm.resolve);
|
||||||
|
this._writable.on('error', this._respProm.reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This check() function made me scratch my head when I came back to
|
||||||
|
* it months later. It simply does too many things. It still isn't perfect,
|
||||||
|
* but hopefully now this beast is slightly easier to follow. It returns
|
||||||
|
* a promise on a boolean indicating whether or not the passed file was
|
||||||
|
* created. IF the strategy is NOT 'mirror' it resolves false since 'mirror'
|
||||||
|
* is the only strategy that creates files. Otherwise if the file exists
|
||||||
|
* it resolves false. Otherwise it has a side effect of creating the file
|
||||||
|
* by requesting out to the remote server and writing the result to the
|
||||||
|
* file, then resolves true.
|
||||||
|
*/
|
||||||
|
|
||||||
|
_createClass(ProvisionableRequest, [{
|
||||||
|
key: 'send',
|
||||||
|
value: function send(readable) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
return new _Promise(function (resolve, reject) {
|
||||||
|
if (!readable || typeof readable === 'string') {
|
||||||
|
_this._writable.end(readable || '', resolve);
|
||||||
|
} else {
|
||||||
|
readable.on('error', reject);
|
||||||
|
readable.on('end', resolve);
|
||||||
|
readable.pipe(_this._writable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'receive',
|
||||||
|
value: function receive() {
|
||||||
|
return this._respProm;
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return ProvisionableRequest;
|
||||||
|
})();
|
||||||
|
|
||||||
|
function check(strategy, file, req, upstreamProxy) {
|
||||||
|
var parsed = _url2['default'].parse(file);
|
||||||
|
file = parsed.pathname; // stripped of query string.
|
||||||
|
|
||||||
|
return (0, _co2['default'])(_regeneratorRuntime.mark(function callee$1$0() {
|
||||||
|
var provReq, mirrResp, writeToFile, gunzip;
|
||||||
|
return _regeneratorRuntime.wrap(function callee$1$0$(context$2$0) {
|
||||||
|
while (1) switch (context$2$0.prev = context$2$0.next) {
|
||||||
|
case 0:
|
||||||
|
if (!(strategy !== 'mirror')) {
|
||||||
|
context$2$0.next = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return context$2$0.abrupt('return', false);
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
context$2$0.prev = 2;
|
||||||
|
context$2$0.next = 5;
|
||||||
|
return (0, _uglyAdapter2['default'])(_fs2['default'].stat, file);
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
return context$2$0.abrupt('return', false);
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
context$2$0.prev = 8;
|
||||||
|
context$2$0.t0 = context$2$0['catch'](2);
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
context$2$0.next = 12;
|
||||||
|
return (0, _uglyAdapter2['default'])(_mkdirp2['default'], _path2['default'].dirname(file));
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
provReq = new ProvisionableRequest({
|
||||||
|
protocol: req.protocol,
|
||||||
|
proxy: upstreamProxy,
|
||||||
|
method: 'GET',
|
||||||
|
hostname: req.hostname,
|
||||||
|
port: req.port,
|
||||||
|
path: req.url
|
||||||
|
});
|
||||||
|
|
||||||
|
provReq.send();
|
||||||
|
context$2$0.next = 16;
|
||||||
|
return provReq.receive();
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
mirrResp = context$2$0.sent;
|
||||||
|
|
||||||
|
if (!(mirrResp.statusCode !== 200)) {
|
||||||
|
context$2$0.next = 19;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('mirroring failed: ' + req.fullUrl() + ' => ' + mirrResp.statusCode);
|
||||||
|
|
||||||
|
case 19:
|
||||||
|
writeToFile = _fs2['default'].createWriteStream(file);
|
||||||
|
|
||||||
|
if (mirrResp.headers['content-encoding'] === 'gzip') {
|
||||||
|
gunzip = _zlib2['default'].createGunzip();
|
||||||
|
|
||||||
|
mirrResp = mirrResp.pipe(gunzip);
|
||||||
|
}
|
||||||
|
context$2$0.next = 23;
|
||||||
|
return new _Promise(function (resolve, reject) {
|
||||||
|
mirrResp.pipe(writeToFile);
|
||||||
|
mirrResp.on('end', resolve);
|
||||||
|
writeToFile.on('error', reject);
|
||||||
|
});
|
||||||
|
|
||||||
|
case 23:
|
||||||
|
case 'end':
|
||||||
|
return context$2$0.stop();
|
||||||
|
}
|
||||||
|
}, callee$1$0, this, [[2, 8]]);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
|
||||||
|
var Cycle = (function (_EventEmitter) {
|
||||||
|
_inherits(Cycle, _EventEmitter);
|
||||||
|
|
||||||
|
function Cycle(proxy) {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
_classCallCheck(this, Cycle);
|
||||||
|
|
||||||
|
_get(Object.getPrototypeOf(Cycle.prototype), 'constructor', this).call(this);
|
||||||
|
this._proxy = proxy;
|
||||||
|
this._request = new _request2['default']();
|
||||||
|
this._response = new _response2['default']();
|
||||||
|
this._request.on('log', function (log) {
|
||||||
|
return _this2.emit('log', log);
|
||||||
|
});
|
||||||
|
this._response.on('log', function (log) {
|
||||||
|
return _this2.emit('log', log);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_createClass(Cycle, [{
|
||||||
|
key: 'data',
|
||||||
|
value: function data(name, val) {
|
||||||
|
if (!this._userData) {
|
||||||
|
this._userData = {};
|
||||||
|
}
|
||||||
|
if (arguments.length === 2) {
|
||||||
|
this._userData[name] = val;
|
||||||
|
}
|
||||||
|
return this._userData[name];
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: 'serve',
|
||||||
|
value: function serve(opts) {
|
||||||
|
|
||||||
|
return _co2['default'].call(this, _regeneratorRuntime.mark(function callee$2$0() {
|
||||||
|
var req, resp, _opts, docroot, path, strategy, headers, pDocroot, pPath, pFullPath, fullSysPath,
|
||||||
|
created, staticResp, code, useResponse, isError, message;
|
||||||
|
|
||||||
|
return _regeneratorRuntime.wrap(function callee$2$0$(context$3$0) {
|
||||||
|
while (1) switch (context$3$0.prev = context$3$0.next) {
|
||||||
|
case 0:
|
||||||
|
req = this._request;
|
||||||
|
resp = this._response;
|
||||||
|
|
||||||
|
if (typeof opts === 'string') {
|
||||||
|
opts = {path: opts};
|
||||||
|
}
|
||||||
|
opts = _lodash2['default'].extend({
|
||||||
|
docroot: _path2['default'].sep,
|
||||||
|
path: _url2['default'].parse(req.url).pathname,
|
||||||
|
strategy: 'replace'
|
||||||
|
}, opts);
|
||||||
|
_opts = opts;
|
||||||
|
docroot = _opts.docroot;
|
||||||
|
path = _opts.path;
|
||||||
|
strategy = _opts.strategy;
|
||||||
|
headers = _lodash2['default'].extend({
|
||||||
|
'x-hoxy-static-docroot': docroot
|
||||||
|
}, req.headers);
|
||||||
|
|
||||||
|
delete headers['if-none-match'];
|
||||||
|
delete headers['if-modified-since'];
|
||||||
|
|
||||||
|
// Now call the static file service.
|
||||||
|
pDocroot = new _urlPath2['default'](docroot), pPath = new _urlPath2['default'](path), pFullPath = pPath.rootTo(pDocroot), fullSysPath = pFullPath.toSystemPath();
|
||||||
|
context$3$0.next = 14;
|
||||||
|
return check(strategy, fullSysPath, req, this._proxy._upstreamProxy);
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
created = context$3$0.sent;
|
||||||
|
|
||||||
|
if (created) {
|
||||||
|
this.emit('log', {
|
||||||
|
level: 'info',
|
||||||
|
message: 'copied ' + req.fullUrl() + ' to ' + fullSysPath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
context$3$0.next = 18;
|
||||||
|
return new _Promise(function (resolve, reject) {
|
||||||
|
var addr = staticServer.address();
|
||||||
|
_http2['default'].get({
|
||||||
|
hostname: addr.address,
|
||||||
|
port: addr.port,
|
||||||
|
headers: headers,
|
||||||
|
path: pPath.toUrlPath()
|
||||||
|
}, resolve).on('error', reject);
|
||||||
|
});
|
||||||
|
|
||||||
|
case 18:
|
||||||
|
staticResp = context$3$0.sent;
|
||||||
|
code = staticResp.statusCode, useResponse = undefined, isError = undefined;
|
||||||
|
|
||||||
|
if (/^2\d\d$/.test(code)) {
|
||||||
|
useResponse = true;
|
||||||
|
} else if (/^4\d\d$/.test(code)) {
|
||||||
|
if (strategy === 'replace') {
|
||||||
|
useResponse = true;
|
||||||
|
} else if (strategy === 'mirror') {
|
||||||
|
isError = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isError = true; // nope
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isError) {
|
||||||
|
context$3$0.next = 26;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message = _util2['default'].format('Failed to serve static file: %s => %s. Static server returned %d. Strategy: %s', req.fullUrl(), fullSysPath, staticResp.statusCode, strategy);
|
||||||
|
throw new Error(message);
|
||||||
|
|
||||||
|
case 26:
|
||||||
|
if (useResponse) {
|
||||||
|
resp._setHttpSource(staticResp);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 27:
|
||||||
|
case 'end':
|
||||||
|
return context$3$0.stop();
|
||||||
|
}
|
||||||
|
}, callee$2$0, this);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: '_setPhase',
|
||||||
|
value: function _setPhase(phase) {
|
||||||
|
this._phase = this._request.phase = this._response.phase = phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This returns a promise on a partially fulfilled request
|
||||||
|
* (an instance of class ProvisionableRequest). At the time
|
||||||
|
* the promise is fulfilled, the request is in a state where
|
||||||
|
* it's been fully piped out, but nothing received. It's up
|
||||||
|
* to the caller of this function to call receive() on it, thus
|
||||||
|
* getting a promise on the serverResponse object. That enables
|
||||||
|
* hoxy to implement the 'request-sent' phase.
|
||||||
|
*/
|
||||||
|
}, {
|
||||||
|
key: '_sendToServer',
|
||||||
|
value: function _sendToServer() {
|
||||||
|
var req = this._request._finalize(),
|
||||||
|
resp = this._response,
|
||||||
|
upstreamProxy = this._proxy._upstreamProxy,
|
||||||
|
source = req._source,
|
||||||
|
pSlow = this._proxy._slow || {},
|
||||||
|
rSlow = req.slow() || {},
|
||||||
|
latency = rSlow.latency || 0;
|
||||||
|
if (resp._populated) {
|
||||||
|
return _Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
return _co2['default'].call(this, _regeneratorRuntime.mark(function callee$2$0() {
|
||||||
|
var provisionableReq, brake, groupedBrake;
|
||||||
|
return _regeneratorRuntime.wrap(function callee$2$0$(context$3$0) {
|
||||||
|
while (1) switch (context$3$0.prev = context$3$0.next) {
|
||||||
|
case 0:
|
||||||
|
provisionableReq = new ProvisionableRequest({
|
||||||
|
protocol: req.protocol,
|
||||||
|
proxy: upstreamProxy,
|
||||||
|
hostname: req.hostname,
|
||||||
|
port: req.port || req._getDefaultPort(),
|
||||||
|
method: req.method,
|
||||||
|
path: req.url,
|
||||||
|
headers: req.headers
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!(latency > 0)) {
|
||||||
|
context$3$0.next = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
context$3$0.next = 4;
|
||||||
|
return (0, _wait2['default'])(latency);
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (rSlow.rate > 0) {
|
||||||
|
brake = _streams2['default'].brake(rSlow.rate);
|
||||||
|
|
||||||
|
source = source.pipe(brake);
|
||||||
|
}
|
||||||
|
if (pSlow.rate) {
|
||||||
|
groupedBrake = pSlow.rate.throttle();
|
||||||
|
|
||||||
|
source = source.pipe(groupedBrake);
|
||||||
|
}
|
||||||
|
if (pSlow.up) {
|
||||||
|
groupedBrake = pSlow.up.throttle();
|
||||||
|
|
||||||
|
source = source.pipe(groupedBrake);
|
||||||
|
}
|
||||||
|
req._tees().forEach(function (writable) {
|
||||||
|
return source.pipe(writable);
|
||||||
|
});
|
||||||
|
context$3$0.next = 10;
|
||||||
|
return provisionableReq.send(source);
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
return context$3$0.abrupt('return', provisionableReq);
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
case 'end':
|
||||||
|
return context$3$0.stop();
|
||||||
|
}
|
||||||
|
}, callee$2$0, this);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: '_sendToClient',
|
||||||
|
value: function _sendToClient(outResp) {
|
||||||
|
var resp = this._response._finalize(),
|
||||||
|
source = resp._source,
|
||||||
|
rSlow = resp.slow() || {},
|
||||||
|
pSlow = this._proxy._slow || {},
|
||||||
|
rLatency = rSlow.latency || 0,
|
||||||
|
pLatency = pSlow.latency || 0,
|
||||||
|
latency = Math.max(pLatency, rLatency);
|
||||||
|
return _co2['default'].call(this, _regeneratorRuntime.mark(function callee$2$0() {
|
||||||
|
var brake, groupedBrake, tees;
|
||||||
|
return _regeneratorRuntime.wrap(function callee$2$0$(context$3$0) {
|
||||||
|
while (1) switch (context$3$0.prev = context$3$0.next) {
|
||||||
|
case 0:
|
||||||
|
if (!(latency > 0)) {
|
||||||
|
context$3$0.next = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
context$3$0.next = 3;
|
||||||
|
return (0, _wait2['default'])(latency);
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
outResp.writeHead(resp.statusCode, resp.headers);
|
||||||
|
if (rSlow.rate > 0) {
|
||||||
|
brake = _streams2['default'].brake(rSlow.rate);
|
||||||
|
|
||||||
|
source = source.pipe(brake);
|
||||||
|
}
|
||||||
|
if (pSlow.rate) {
|
||||||
|
groupedBrake = pSlow.rate.throttle();
|
||||||
|
|
||||||
|
source = source.pipe(groupedBrake);
|
||||||
|
}
|
||||||
|
if (pSlow.down) {
|
||||||
|
groupedBrake = pSlow.down.throttle();
|
||||||
|
|
||||||
|
source = source.pipe(groupedBrake);
|
||||||
|
}
|
||||||
|
tees = resp._tees();
|
||||||
|
|
||||||
|
tees.forEach(function (writable) {
|
||||||
|
return source.pipe(writable);
|
||||||
|
});
|
||||||
|
context$3$0.next = 11;
|
||||||
|
return new _Promise(function (resolve, reject) {
|
||||||
|
source.on('error', reject);
|
||||||
|
source.on('end', resolve);
|
||||||
|
source.pipe(outResp);
|
||||||
|
});
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
case 'end':
|
||||||
|
return context$3$0.stop();
|
||||||
|
}
|
||||||
|
}, callee$2$0, this);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
key: '_start',
|
||||||
|
value: function _start() {
|
||||||
|
// for now, an immediately-kept promise
|
||||||
|
return (0, _await2['default'])('started').keep('started');
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return Cycle;
|
||||||
|
})(_events.EventEmitter);
|
||||||
|
|
||||||
|
exports['default'] = Cycle;
|
||||||
|
module.exports = exports['default'];
|
||||||
|
|
||||||
|
// file does not exist, so continue
|
||||||
|
|
||||||
|
// TODO: test coverage for mkdirp
|
||||||
|
|
||||||
|
// TODO: test coverage
|
||||||
|
|
||||||
|
// First, get all our ducks in a row WRT to
|
||||||
|
// options, setting variables, etc.
|
||||||
|
// return the outer promise
|
||||||
|
// wait for it all to pipe out
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "res-downloader",
|
"name": "res-downloader",
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"main": "dist-electron/main/index.js",
|
"main": "dist-electron/main/index.js",
|
||||||
"description": "Electron + Vue + Vite 实现的资源下载软件,支持微信视频号下载、抖音视频下载、快手视频下载、酷狗音乐下载等",
|
"description": "Electron + Vue + Vite 实现的资源下载软件,支持微信视频号下载、抖音视频下载、快手视频下载、酷狗音乐下载等",
|
||||||
"author": "putyy@qq.com",
|
"author": "putyy@qq.com",
|
||||||
@@ -56,6 +56,7 @@
|
|||||||
"axios": "^1.5.0",
|
"axios": "^1.5.0",
|
||||||
"electron-store": "^8.1.0",
|
"electron-store": "^8.1.0",
|
||||||
"getmac": "^5.20.0",
|
"getmac": "^5.20.0",
|
||||||
"hoxy": "^3.3.1"
|
"hoxy": "^3.3.1",
|
||||||
|
"tunnel-agent": "^0.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
public/show.jpg
BIN
public/show.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
BIN
public/show.webp
Normal file
BIN
public/show.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
@@ -35,6 +35,10 @@ const str = "使用方法\n" +
|
|||||||
" 手动检测系统代理是否设置正确 本软件代理地址: 127.0.0.1:8899\n" +
|
" 手动检测系统代理是否设置正确 本软件代理地址: 127.0.0.1:8899\n" +
|
||||||
" 2. 关闭软件后无法正常上网\n" +
|
" 2. 关闭软件后无法正常上网\n" +
|
||||||
" 手动关闭系统代理设置\n" +
|
" 手动关闭系统代理设置\n" +
|
||||||
|
" 3. 视频号抓取流程\n" +
|
||||||
|
" 将需要下载的视频发给好友或者文件助手 再打开该视频即可拦截到,通常软件界面对应视频会出现标题描述、对应操作会出现解密下载按钮\n" +
|
||||||
|
" 大视频可以复制链接通过其他工具加速下载,然后再通过对应的视频操作项进行\"视频解密\"\n" +
|
||||||
|
|
||||||
"实现原理\n" +
|
"实现原理\n" +
|
||||||
" 通过代理网络抓包拦截响应,筛选出有用的资源,\n" +
|
" 通过代理网络抓包拦截响应,筛选出有用的资源,\n" +
|
||||||
" 同fiddler、charles等抓包软件、浏览器F12打开控制也能达到目的,\n" +
|
" 同fiddler、charles等抓包软件、浏览器F12打开控制也能达到目的,\n" +
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, onMounted} from "vue"
|
import {ref, onMounted, onUnmounted, watch} from "vue"
|
||||||
import {ipcRenderer} from 'electron'
|
import {ipcRenderer} from 'electron'
|
||||||
import {onUnmounted} from "@vue/runtime-core"
|
|
||||||
import {ElMessage, ElLoading, ElTable} from "element-plus"
|
import {ElMessage, ElLoading, ElTable} from "element-plus"
|
||||||
import localStorageCache from "../common/localStorage"
|
import localStorageCache from "../common/localStorage"
|
||||||
import {Delete, Promotion} from "@element-plus/icons-vue";
|
import {Delete, Promotion} from "@element-plus/icons-vue";
|
||||||
@@ -37,6 +36,7 @@ const isInitApp = ref(false)
|
|||||||
|
|
||||||
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
|
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
|
||||||
const multipleSelection = ref<resData[]>([])
|
const multipleSelection = ref<resData[]>([])
|
||||||
|
const loading = ref()
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
let resTypeCache = localStorageCache.get("res-type")
|
let resTypeCache = localStorageCache.get("res-type")
|
||||||
@@ -49,36 +49,39 @@ onMounted(() => {
|
|||||||
tableData.value = tableDataCache
|
tableData.value = tableDataCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipcRenderer.on('on_get_queue', (res, data) => {
|
||||||
|
// @ts-ignore
|
||||||
|
if (resType.value.hasOwnProperty(data.type_str) && resType.value[data.type_str]) {
|
||||||
|
tableData.value.push(data)
|
||||||
|
localStorageCache.set("res-table-data", tableData.value, -1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcRenderer.on('on_down_file_schedule', (res: any, data: any) => {
|
||||||
|
loading.value && loading.value.setText(`已下载 ${data.schedule}%`)
|
||||||
|
})
|
||||||
|
|
||||||
ipcRenderer.invoke('invoke_app_is_init').then((isInit: boolean) => {
|
ipcRenderer.invoke('invoke_app_is_init').then((isInit: boolean) => {
|
||||||
if (!isInit) {
|
if (!isInit && !isInitApp.value) {
|
||||||
isInitApp.value = true
|
isInitApp.value = true
|
||||||
ipcRenderer.invoke('invoke_init_app')
|
ipcRenderer.invoke('invoke_init_app')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let loading = ElLoading.service({
|
loading.value = ElLoading.service({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: 'Loading',
|
text: 'Loading',
|
||||||
background: 'rgba(0, 0, 0, 0.7)',
|
background: 'rgba(0, 0, 0, 0.7)',
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcRenderer.invoke('invoke_start_proxy').then(() => {
|
ipcRenderer.invoke('invoke_start_proxy', {upstream_proxy: localStorageCache.get("upstream_proxy")}).then(() => {
|
||||||
loading.close()
|
loading.value.close()
|
||||||
ipcRenderer.on('on_get_queue', (res, data) => {
|
|
||||||
// @ts-ignore
|
|
||||||
if (resType.value.hasOwnProperty(data.type_str) && resType.value[data.type_str]) {
|
|
||||||
tableData.value.push(data)
|
|
||||||
localStorageCache.set("res-table-data", tableData.value, -1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
})
|
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
// console.log('invoke_start_proxy err', err)
|
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: err,
|
message: err,
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
loading.close()
|
loading.value.close()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -90,14 +93,12 @@ onUnmounted(() => {
|
|||||||
ipcRenderer.removeListener('on_down_file_schedule', (res) => {
|
ipcRenderer.removeListener('on_down_file_schedule', (res) => {
|
||||||
// console.log(res)
|
// console.log(res)
|
||||||
})
|
})
|
||||||
|
|
||||||
// ipcRenderer.invoke('invoke_close_proxy').then((res) => {
|
|
||||||
// })
|
|
||||||
|
|
||||||
localStorageCache.set("res-table-data", tableData.value, -1)
|
|
||||||
localStorageCache.set("res-type", resType.value, -1)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(resType, (res, res1)=>{
|
||||||
|
localStorageCache.set("res-type", resType.value, -1)
|
||||||
|
}, {deep: true})
|
||||||
|
|
||||||
const handleSelectionChange = (val: resData[]) => {
|
const handleSelectionChange = (val: resData[]) => {
|
||||||
multipleSelection.value = val
|
multipleSelection.value = val
|
||||||
}
|
}
|
||||||
@@ -117,16 +118,12 @@ const handleBatchDown = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let loading = ElLoading.service({
|
loading.value = ElLoading.service({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: '下载中',
|
text: '下载中',
|
||||||
background: 'rgba(0, 0, 0, 0.7)',
|
background: 'rgba(0, 0, 0, 0.7)',
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcRenderer.on('on_down_file_schedule', (res: any, data: any) => {
|
|
||||||
loading.setText(`已下载 ${data.schedule}%`)
|
|
||||||
})
|
|
||||||
|
|
||||||
for (const item of multipleSelection.value) {
|
for (const item of multipleSelection.value) {
|
||||||
let result = await ipcRenderer.invoke('invoke_file_exists', {
|
let result = await ipcRenderer.invoke('invoke_file_exists', {
|
||||||
save_path: save_dir,
|
save_path: save_dir,
|
||||||
@@ -151,7 +148,7 @@ const handleBatchDown = async () => {
|
|||||||
item.save_path = downRes.fullFileName
|
item.save_path = downRes.fullFileName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loading.close()
|
loading.value.close()
|
||||||
multipleTableRef.value!.clearSelection()
|
multipleTableRef.value!.clearSelection()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +165,7 @@ const handleDown = async (index: number, row: any, high: boolean) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let loading = ElLoading.service({
|
loading.value = ElLoading.service({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: '下载中',
|
text: '下载中',
|
||||||
background: 'rgba(0, 0, 0, 0.7)',
|
background: 'rgba(0, 0, 0, 0.7)',
|
||||||
@@ -186,14 +183,11 @@ const handleDown = async (index: number, row: any, high: boolean) => {
|
|||||||
message: "文件已存在(" + result.fileName + ")",
|
message: "文件已存在(" + result.fileName + ")",
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
loading.close()
|
loading.value.close()
|
||||||
|
localStorageCache.set("res-table-data", tableData.value, -1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcRenderer.on('on_down_file_schedule', (res: any, data: any) => {
|
|
||||||
loading.setText(`已下载 ${data.schedule}%`)
|
|
||||||
})
|
|
||||||
|
|
||||||
ipcRenderer.invoke('invoke_down_file', {
|
ipcRenderer.invoke('invoke_down_file', {
|
||||||
index: index,
|
index: index,
|
||||||
data: Object.assign({}, tableData.value[index]),
|
data: Object.assign({}, tableData.value[index]),
|
||||||
@@ -203,24 +197,25 @@ const handleDown = async (index: number, row: any, high: boolean) => {
|
|||||||
if (res !== false) {
|
if (res !== false) {
|
||||||
tableData.value[index].progress_bar = "100%"
|
tableData.value[index].progress_bar = "100%"
|
||||||
tableData.value[index].save_path = res.fullFileName
|
tableData.value[index].save_path = res.fullFileName
|
||||||
|
localStorageCache.set("res-table-data", tableData.value, -1)
|
||||||
}else{
|
}else{
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: "下载失败",
|
message: "下载失败",
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
loading.close()
|
loading.value.close()
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: "下载失败",
|
message: "下载失败",
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
loading.close()
|
loading.value.close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const decodeWxFile = (index: number) => {
|
const decodeWxFile = (index: number) => {
|
||||||
let loading = ElLoading.service({
|
loading.value = ElLoading.service({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: "解密中",
|
text: "解密中",
|
||||||
background: 'rgba(0, 0, 0, 0.7)',
|
background: 'rgba(0, 0, 0, 0.7)',
|
||||||
@@ -237,19 +232,20 @@ const decodeWxFile = (index: number) => {
|
|||||||
})
|
})
|
||||||
tableData.value[index].progress_bar = "100%"
|
tableData.value[index].progress_bar = "100%"
|
||||||
tableData.value[index].save_path = res.fullFileName
|
tableData.value[index].save_path = res.fullFileName
|
||||||
|
localStorageCache.set("res-table-data", tableData.value, -1)
|
||||||
}else{
|
}else{
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: "解密失败",
|
message: "解密失败",
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
loading.close()
|
loading.value.close()
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: "解密失败",
|
message: "解密失败",
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
})
|
})
|
||||||
loading.close()
|
loading.value.close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,6 +276,7 @@ const handleDel = (index: number)=>{
|
|||||||
let arr = tableData.value
|
let arr = tableData.value
|
||||||
arr.splice(index, 1);
|
arr.splice(index, 1);
|
||||||
tableData.value = arr
|
tableData.value = arr
|
||||||
|
localStorageCache.set("res-table-data", tableData.value, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const openFileDir = (index: number)=>{
|
const openFileDir = (index: number)=>{
|
||||||
@@ -326,7 +323,7 @@ el-container.container
|
|||||||
template(#default="scope")
|
template(#default="scope")
|
||||||
div.show_res
|
div.show_res
|
||||||
video.video(v-if="scope.row.type_str === 'video'" :src="scope.row.down_url" controls preload="none") 您的浏览器不支持 video 标签。
|
video.video(v-if="scope.row.type_str === 'video'" :src="scope.row.down_url" controls preload="none") 您的浏览器不支持 video 标签。
|
||||||
img.img(v-if="scope.row.type_str === 'image'" :src="scope.row.down_url")
|
img.img(v-if="scope.row.type_str === 'image'" :src="scope.row.down_url" crossorigin="anonymous")
|
||||||
audio.audio(v-if="scope.row.type_str === 'audio'" controls preload="none")
|
audio.audio(v-if="scope.row.type_str === 'audio'" controls preload="none")
|
||||||
source(:src="scope.row.down_url" :type="scope.row.type")
|
source(:src="scope.row.down_url" :type="scope.row.type")
|
||||||
div {{scope.row.description}}
|
div {{scope.row.description}}
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ import {ipcRenderer} from "electron";
|
|||||||
import localStorageCache from "../common/localStorage";
|
import localStorageCache from "../common/localStorage";
|
||||||
import {ElMessage} from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
|
|
||||||
|
const saveDir = ref("")
|
||||||
|
const upstream_proxy = ref("")
|
||||||
|
const upstream_proxy_old = ref("")
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
saveDir.value = localStorageCache.get("save_dir")
|
saveDir.value = localStorageCache.get("save_dir") ? localStorageCache.get("save_dir") : ""
|
||||||
saveDir.value = !saveDir.value ? "" : saveDir.value
|
upstream_proxy.value = localStorageCache.get("upstream_proxy") ? localStorageCache.get("upstream_proxy") : ""
|
||||||
|
upstream_proxy_old.value = upstream_proxy.value
|
||||||
})
|
})
|
||||||
|
|
||||||
const saveDir = ref("")
|
|
||||||
const selectSaveDir = () => {
|
const selectSaveDir = () => {
|
||||||
ipcRenderer.invoke('invoke_select_down_dir').then(save_path => {
|
ipcRenderer.invoke('invoke_select_down_dir').then(save_path => {
|
||||||
if (save_path !== false) {
|
if (save_path !== false) {
|
||||||
@@ -20,6 +24,10 @@ const selectSaveDir = () => {
|
|||||||
|
|
||||||
const onSetting = () => {
|
const onSetting = () => {
|
||||||
localStorageCache.set("save_dir", saveDir.value, -1)
|
localStorageCache.set("save_dir", saveDir.value, -1)
|
||||||
|
localStorageCache.set("upstream_proxy", upstream_proxy.value, -1)
|
||||||
|
if (upstream_proxy_old.value != upstream_proxy.value){
|
||||||
|
ipcRenderer.invoke('invoke_window_restart')
|
||||||
|
}
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: "操作成功",
|
message: "操作成功",
|
||||||
type: 'success',
|
type: 'success',
|
||||||
@@ -30,7 +38,9 @@ const onSetting = () => {
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
el-form
|
el-form
|
||||||
el-form-item(label="保存位置")
|
el-form-item(label="保存位置")
|
||||||
el-button.select-dir(@click="selectSaveDir") {{saveDir ? saveDir : '选择'}}
|
el-button(@click="selectSaveDir") {{saveDir ? saveDir : '选择'}}
|
||||||
|
el-form-item(label="代理服务")
|
||||||
|
el-input(v-model="upstream_proxy" placeholder="例如: http://127.0.0.1:7890 修改此项需重启本软件" )
|
||||||
el-form-item
|
el-form-item
|
||||||
el-button(type="primary" @click="onSetting") 保存
|
el-button(type="primary" @click="onSetting") 保存
|
||||||
</template>
|
</template>
|
||||||
Reference in New Issue
Block a user