🌟 feat: 除了哔哩哔哩下载外的其他支持Aria2和axel

This commit is contained in:
zhiyu1998 2024-08-14 11:20:29 +08:00
parent 6f3e27acdc
commit b7a9e031f4
3 changed files with 156 additions and 4 deletions

View File

@ -13,7 +13,7 @@ import {
BILI_DEFAULT_INTRO_LEN_LIMIT,
COMMON_USER_AGENT,
DIVIDING_LINE,
douyinTypeMap,
douyinTypeMap, DOWNLOAD_WAIT_DETECT_FILE_TIME,
HELP_DOC, MESSAGE_RECALL_TIME,
REDIS_YUNZAI_ISOVERSEA,
REDIS_YUNZAI_LAGRANGE, REDOS_YUNZAI_WHITELIST,
@ -1939,6 +1939,10 @@ export class tools extends plugin {
// 如果是用户设置了单线程,则不分片下载
if (numThreads === 1) {
return await this.downloadVideoWithSingleThread(downloadVideoParams);
} else if (numThreads !== 1 && this.biliDownloadMethod === 1) {
return await this.downloadVideoWithAria2(downloadVideoParams, numThreads);
} else if (numThreads !== 1 && this.biliDownloadMethod === 2) {
return await this.downloadVideoUseAxel(downloadVideoParams, numThreads);
} else {
return await this.downloadVideoWithMultiThread(downloadVideoParams, numThreads);
}
@ -2026,6 +2030,148 @@ export class tools extends plugin {
}
}
/**
* 使用Aria2进行多线程下载
* @param downloadVideoParams
* @param numThreads
* @returns {Promise<unknown>}
*/
async downloadVideoWithAria2(downloadVideoParams, numThreads) {
const { url, headers, userAgent, proxyOption, target, groupPath } = downloadVideoParams;
// 构造aria2c命令参数
const aria2cArgs = [
`"${url}"`,
`--out="temp.mp4"`,
`--dir="${groupPath}"`,
`--user-agent="${userAgent}"`,
`--max-connection-per-server=${ numThreads }`, // 每个服务器的最大连接数
`--split=${ numThreads }`, // 分成 6 个部分进行下载
];
// 如果有自定义头信息
if (headers) {
for (const [key, value] of Object.entries(headers)) {
aria2cArgs.push(`--header="${key}: ${value}"`);
}
}
// 如果使用代理
if (proxyOption && proxyOption.httpAgent) {
const proxyUrl = proxyOption.httpAgent.proxy.href;
aria2cArgs.push(`--all-proxy="${proxyUrl}"`);
}
try {
await checkAndRemoveFile(target);
logger.mark(`开始下载: ${url}`);
// 执行aria2c命令
const command = `aria2c ${aria2cArgs.join(' ')}`;
exec(command, (error, stdout, stderr) => {
if (error) {
logger.error(`下载视频发生错误!\ninfo:${stderr}`);
throw error;
} else {
logger.mark(`下载完成: ${url}`);
}
});
// 监听文件生成完成
let count = 0;
return new Promise((resolve, reject) => {
const checkInterval = setInterval(() => {
logger.info(logger.red(`[R插件][Aria2] 没有检测到文件!重试第${ count + 1 }`));
count += 1;
if (fs.existsSync(target)) {
logger.info("[R插件][Aria2] 检测到文件!");
clearInterval(checkInterval);
resolve(groupPath);
}
if (count === 6) {
logger.error(`[R插件][Aria2] 下载视频发生错误!`);
clearInterval(checkInterval);
reject();
}
}, DOWNLOAD_WAIT_DETECT_FILE_TIME);
});
} catch (err) {
logger.error(`下载视频发生错误!\ninfo:${err}`);
throw err;
}
}
/**
* 使用Axel进行多线程下载
* @param downloadVideoParams
* @param numThreads
* @returns {Promise<unknown>}
*/
async downloadVideoUseAxel(downloadVideoParams, numThreads) {
const { url, headers, userAgent, proxyOption, target, groupPath } = downloadVideoParams;
// 构造axel命令参数
const axelArgs = [
`-n ${numThreads}`,
`-o "${target}"`,
`-U "${userAgent}"`,
url
];
// 如果有自定义头信息
if (headers) {
for (const [key, value] of Object.entries(headers)) {
axelArgs.push(`-H "${key}: ${value}"`);
}
}
// 如果使用代理
if (proxyOption && proxyOption.httpAgent) {
const proxyUrl = proxyOption.httpAgent.proxy.href;
axelArgs.push(`--proxy="${proxyUrl}"`);
}
try {
await checkAndRemoveFile(target);
logger.mark(`开始下载: ${url}`);
// 执行axel命令
const command = `axel ${axelArgs.join(' ')}`;
exec(command, (error, stdout, stderr) => {
if (error) {
logger.error(`下载视频发生错误!\ninfo:${stderr}`);
throw error;
} else {
logger.mark(`下载完成: ${url}`);
}
});
let count = 0;
// 监听文件生成完成
return new Promise((resolve, reject) => {
const checkInterval = setInterval(() => {
logger.info(logger.red(`[R插件][Aria2] 没有检测到文件!重试第${ count + 1 }`));
count += 1;
if (fs.existsSync(target)) {
logger.info("[R插件][Axel] 检测到文件!");
clearInterval(checkInterval);
logger.info(`[R插件][Axel] 下载到${groupPath}`);
resolve(groupPath);
}
if (count === 6) {
logger.error(`[R插件][Axel] 下载视频发生错误!`);
clearInterval(checkInterval);
reject();
}
}, DOWNLOAD_WAIT_DETECT_FILE_TIME);
});
} catch (err) {
logger.error(`下载视频发生错误!\ninfo:${err}`);
throw err;
}
}
/**
* 单线程下载视频
* @link {downloadVideo}
@ -2100,7 +2246,7 @@ export class tools extends plugin {
return false;
}
const whiteList = await redisGetKey(REDOS_YUNZAI_WHITELIST);
return whiteList.includes(userId) || whiteList.includes(userId.toString());
return whiteList.includes(userId.toString()) || whiteList.includes(userId);
}
/**

View File

@ -144,4 +144,10 @@ export const BILI_DOWNLOAD_METHOD = Object.freeze([
* 消息撤回时间
* @type {number}
*/
export const MESSAGE_RECALL_TIME = 60;
export const MESSAGE_RECALL_TIME = 60;
/**
* 针对 Aria2 Alex 的下载检测文件时间
* @type {number}
*/
export const DOWNLOAD_WAIT_DETECT_FILE_TIME = 2000;

View File

@ -24,7 +24,7 @@ export function startBBDown(videoUrl, downloadDir, BBDownOptions) {
urlObj.search = newParams.toString();
videoUrl = urlObj.toString();
// 说明:-F 自定义名称,-c 自定义Cookie --work-dir 设置下载目录,-M 多p下载的时候命名
const command = `BBDown ${videoUrl} --work-dir ${downloadDir} ${biliSessData ? '-c SESSDATA=\"' + biliSessData + '\"' : ''} ${pageParam ? '-p ' + pageParam + ' -M \"temp\"' : '-p 1' + ' -M \"temp\"'} -F temp --skip-subtitle --skip-cover ${biliUseAria2 ? '--use-aria2c' : ''} ${biliCDN ? '--upos-host ' + biliCDN : ''}`;
const command = `BBDown ${videoUrl} --work-dir ${downloadDir} ${biliSessData ? '-c SESSDATA=' + biliSessData : ''} ${pageParam ? '-p ' + pageParam + ' -M \"temp\"' : '-p 1' + ' -M \"temp\"'} -F temp --skip-subtitle --skip-cover ${biliUseAria2 ? '--use-aria2c' : ''} ${biliCDN ? '--upos-host ' + biliCDN : ''}`;
logger.info(command);
// logger.info(command);
// 直接调用BBDown因为它已经在系统路径中