🎈 perf: 性能优化-patch1

This commit is contained in:
zhiyu1998 2023-04-01 21:23:36 +08:00
parent c18bd3fa0e
commit 7672888930
3 changed files with 130 additions and 168 deletions

View File

@ -7,7 +7,7 @@ import axios from "axios";
import _ from "lodash"; import _ from "lodash";
import tunnel from "tunnel"; import tunnel from "tunnel";
import HttpProxyAgent from "https-proxy-agent"; import HttpProxyAgent from "https-proxy-agent";
import { mkdirsSync } from "../utils/file.js"; import { mkdirIfNotExists, checkAndRemoveFile } from "../utils/file.js";
import { downloadBFile, getDownloadUrl, mergeFileToMp4 } from "../utils/bilibili.js"; import { downloadBFile, getDownloadUrl, mergeFileToMp4 } from "../utils/bilibili.js";
import { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } from "../utils/acfun.js"; import { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } from "../utils/acfun.js";
import { transMap, douyinTypeMap, XHS_CK, TEN_THOUSAND } from "../utils/constant.js"; import { transMap, douyinTypeMap, XHS_CK, TEN_THOUSAND } from "../utils/constant.js";
@ -30,7 +30,7 @@ export class tools extends plugin {
priority: 500, priority: 500,
rule: [ rule: [
{ {
reg: "^(翻|trans)(.) (.*)$", reg: "^(翻|trans)(.*)$",
fnc: "trans", fnc: "trans",
}, },
{ {
@ -109,13 +109,14 @@ export class tools extends plugin {
const languageReg = /翻(.)/g; const languageReg = /翻(.)/g;
const msg = e.msg.trim(); const msg = e.msg.trim();
const language = languageReg.exec(msg); const language = languageReg.exec(msg);
if (!transMap.hasOwnProperty(language[1])) { if (!(language[1] in transMap)) {
e.reply( e.reply(
"输入格式有误或暂不支持该语言!\n例子翻中 China's policy has been consistent, but Japan chooses a path of mistrust, decoupling and military expansion", "输入格式有误或暂不支持该语言!\n例子翻中 China's policy has been consistent, but Japan chooses a path of mistrust, decoupling and military expansion",
); );
return; return;
} }
const place = msg.replace(language[0], "").trim(); const place = msg.slice(1 + language[1].length).replaceAll("\n", " ")
logger.info(place)
const translateEngine = new Translate({ const translateEngine = new Translate({
translateAppId: this.toolsConfig.translateAppId, translateAppId: this.toolsConfig.translateAppId,
translateSecret: this.toolsConfig.translateSecret, translateSecret: this.toolsConfig.translateSecret,
@ -127,15 +128,8 @@ export class tools extends plugin {
_.isEmpty(this.toolsConfig.translateAppId) || _.isEmpty(this.toolsConfig.translateAppId) ||
_.isEmpty(this.toolsConfig.translateSecret) _.isEmpty(this.toolsConfig.translateSecret)
) { ) {
try {
// 咕咕翻译
translateResult =
"📝咕咕翻译:" + (await translateEngine.google(place, language[1]));
} catch (err) {
logger.error("咕咕翻译失败");
}
// 腾讯交互式进行补充 // 腾讯交互式进行补充
translateResult += "\n\n🐧翻译" + (await translateEngine.tencent(place, language[1])); translateResult = await translateEngine.tencent(place, language[1]);
} else { } else {
// 如果有百度 // 如果有百度
translateResult = await translateEngine.baidu(place, language[1]); translateResult = await translateEngine.baidu(place, language[1]);
@ -330,10 +324,6 @@ export class tools extends plugin {
return true; return true;
} }
const path = `${this.defaultPath}${this.e.group_id || this.e.user_id}/`;
if (!fs.existsSync(path)) {
mkdirsSync(path);
}
// 视频信息获取例子http://api.bilibili.com/x/web-interface/view?bvid=BV1hY411m7cB // 视频信息获取例子http://api.bilibili.com/x/web-interface/view?bvid=BV1hY411m7cB
// 请求视频信息 // 请求视频信息
const videoInfo = await getVideoInfo(url); const videoInfo = await getVideoInfo(url);
@ -355,6 +345,10 @@ export class tools extends plugin {
`简介:${desc}`; `简介:${desc}`;
e.reply([`识别:哔哩哔哩:${title}`, combineContent]); e.reply([`识别:哔哩哔哩:${title}`, combineContent]);
// 创建文件,如果不存在
const path = `${this.defaultPath}${this.e.group_id || this.e.user_id}/`;
await mkdirIfNotExists(path)
// 下载文件
getDownloadUrl(url) getDownloadUrl(url)
.then(data => { .then(data => {
this.downBili(`${path}temp`, data.videoUrl, data.audioUrl) this.downBili(`${path}temp`, data.videoUrl, data.audioUrl)
@ -715,9 +709,7 @@ export class tools extends plugin {
// acfun解析 // acfun解析
async acfun(e) { async acfun(e) {
const path = `${this.defaultPath}${this.e.group_id || this.e.user_id}/temp/`; const path = `${this.defaultPath}${this.e.group_id || this.e.user_id}/temp/`;
if (!fs.existsSync(path)) { await mkdirIfNotExists(path);
mkdirsSync(path);
}
let inputMsg = e.msg; let inputMsg = e.msg;
// 适配手机分享https://m.acfun.cn/v/?ac=32838812&sid=d2b0991bd6ad9c09 // 适配手机分享https://m.acfun.cn/v/?ac=32838812&sid=d2b0991bd6ad9c09
@ -787,22 +779,21 @@ export class tools extends plugin {
imgPromise.push(this.downloadImg(item.url, downloadPath, index.toString())); imgPromise.push(this.downloadImg(item.url, downloadPath, index.toString()));
}); });
} }
let path = []; const paths = await Promise.all(imgPromise);
const images = await Promise.all(imgPromise).then(paths => { const imagesData = await Promise.all(paths.map(async (item) => {
return paths.map(item => { const fileContent = await fs.promises.readFile(item);
path.push(item); return {
return { message: segment.image(fileContent),
message: segment.image(fs.readFileSync(item)), nickname: e.sender.card || e.user_id,
nickname: e.sender.card || e.user_id, user_id: e.user_id,
user_id: e.user_id, };
}; }));
});
}); // Reply with forward message
await this.reply(await Bot.makeForwardMsg(images)); e.reply(await Bot.makeForwardMsg(imagesData));
// 清理文件
path.forEach(item => { // Clean up files
fs.unlinkSync(item); await Promise.all(paths.map(item => fs.promises.unlink(item)));
});
}); });
return true; return true;
} }
@ -833,18 +824,17 @@ export class tools extends plugin {
async clearTrash(e) { async clearTrash(e) {
const directory = "./data/"; const directory = "./data/";
try { try {
fs.readdir(directory, (err, files) => { const files = await fs.promises.readdir(directory);
for (const file of files) { for (const file of files) {
// 如果文件名符合规则,执行删除操作 // 如果文件名符合规则,执行删除操作
if (/^[0-9a-f]{32}$/.test(file)) { if (/^[0-9a-f]{32}$/.test(file)) {
fs.unlinkSync(directory + file); await fs.promises.unlink(directory + file);
}
} }
}); }
await e.reply(`清理完成!`); e.reply(`清理完成!`);
} catch (err) { } catch (err) {
logger.error(err); logger.error(err);
e.reply("清理失败,重试或者动清理即可"); await e.reply("清理失败,重试或者动清理即可");
} }
} }
@ -1008,33 +998,27 @@ export class tools extends plugin {
} }
const filepath = `${dir}/${fileName}`; const filepath = `${dir}/${fileName}`;
const writer = fs.createWriteStream(filepath); const writer = fs.createWriteStream(filepath);
let req; const axiosConfig = {
headers: {
"User-Agent":
"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36",
},
responseType: "stream",
};
if (isProxy) { if (isProxy) {
req = axios.get(img, { axiosConfig.Referer = "https://imginn.com";
headers: { axiosConfig.httpAgent = tunnel.httpOverHttp({
"User-Agent": proxy: { host: this.proxyAddr, port: this.proxyPort },
"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36",
},
responseType: "stream",
Referer: "https://imginn.com",
httpAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
httpsAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
}); });
} else { axiosConfig.httpsAgent = tunnel.httpOverHttp({
req = axios.get(img, { proxy: { host: this.proxyAddr, port: this.proxyPort },
headers: {
"User-Agent":
"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36",
},
responseType: "stream",
}); });
} }
return req.then(res => { try {
const res = await axios.get(img, axiosConfig);
res.data.pipe(writer); res.data.pipe(writer);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
writer.on("finish", () => { writer.on("finish", () => {
writer.close(() => { writer.close(() => {
@ -1047,7 +1031,9 @@ export class tools extends plugin {
}); });
}); });
}); });
}); } catch (err) {
logger.error("图片下载失败");
}
} }
/** /**
@ -1063,17 +1049,21 @@ export class tools extends plugin {
}, },
timeout: 10000, timeout: 10000,
}; };
return new Promise((resolve, reject) => { try {
axios const resp = await axios.head(url, params);
.head(url, params) const location = resp.request.res.responseUrl;
.then(resp => { return location;
const location = resp.request.res.responseUrl; } catch (error) {
resolve(location); console.error(error);
}) throw error;
.catch(err => { }
reject(err); }
});
}); // 提取视频下载位置
getGroupPathAndTarget() {
const groupPath = `${this.defaultPath}${this.e.group_id || this.e.user_id}`;
const target = `${groupPath}/temp.mp4`;
return { groupPath, target };
} }
/** /**
@ -1084,55 +1074,39 @@ export class tools extends plugin {
* @returns {Promise<unknown>} * @returns {Promise<unknown>}
*/ */
async downloadVideo(url, isProxy = false, headers = null) { async downloadVideo(url, isProxy = false, headers = null) {
const groupPath = `${this.defaultPath}${this.e.group_id || this.e.user_id}`; const { groupPath, target } = this.getGroupPathAndTarget.call(this);
if (!fs.existsSync(groupPath)) {
mkdirsSync(groupPath);
}
const target = `${groupPath}/temp.mp4`;
// 待优化
if (fs.existsSync(target)) {
logger.mark(`视频已存在`);
fs.unlinkSync(target);
}
let res;
if (isProxy) {
res = await axios
.get(url, {
headers: headers || {
"User-Agent":
"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36",
},
responseType: "stream",
httpAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
httpsAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
})
.catch(err => {
logger.error("下载视频发生错误!");
});
} else {
res = await axios
.get(url, {
headers: headers || {
"User-Agent":
"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36",
},
responseType: "stream",
})
.catch(err => {
logger.error("下载视频发生错误!");
});
}
logger.mark(`开始下载: ${url}`);
const writer = fs.createWriteStream(target);
res.data.pipe(writer);
return new Promise((resolve, reject) => { await mkdirIfNotExists(groupPath);
writer.on("finish", () => resolve(groupPath));
writer.on("error", reject); const userAgent =
}); "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36";
const axiosConfig = {
headers: headers || { "User-Agent": userAgent },
responseType: "stream",
...(isProxy && {
httpAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
httpsAgent: tunnel.httpOverHttp({
proxy: { host: this.proxyAddr, port: this.proxyPort },
}),
}),
};
try {
await checkAndRemoveFile(target);
const res = await axios.get(url, axiosConfig);
logger.mark(`开始下载: ${url}`);
const writer = fs.createWriteStream(target);
res.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on("finish", () => resolve(groupPath));
writer.on("error", reject);
});
} catch (err) {
logger.error("下载视频发生错误!");
}
} }
} }

View File

@ -3,7 +3,7 @@ import common from "../../../lib/common/common.js";
import axios from "axios"; import axios from "axios";
import fs from "node:fs"; import fs from "node:fs";
import fetch from "node-fetch"; import fetch from "node-fetch";
import { mkdirsSync } from "./file.js"; import { mkdirIfNotExists } from "./file.js";
/** /**
* 请求模板 * 请求模板
@ -135,11 +135,10 @@ async function downloadMp3(mp3Url, path, redirect = "manual") {
}, },
responseType: "stream", responseType: "stream",
redirect: redirect, redirect: redirect,
}).then(res => { }).then(async res => {
// 如果没有目录就创建一个 // 如果没有目录就创建一个
if (!fs.existsSync(path)) { await mkdirIfNotExists(path)
mkdirsSync(path);
}
// 补充保存文件名 // 补充保存文件名
path += "/temp.mp3"; path += "/temp.mp3";
if (fs.existsSync(path)) { if (fs.existsSync(path)) {

View File

@ -1,48 +1,37 @@
import fs from "node:fs"; import fs from "node:fs";
import path from "path";
// 同步递归创建文件夹 /**
function mkdirsSync (dirname) { * 检查文件是否存在并且删除
if (fs.existsSync(dirname)) { * @param file
return true; * @returns {Promise<void>}
} else { */
if (mkdirsSync(path.dirname(dirname))) { async function checkAndRemoveFile(file) {
fs.mkdirSync(dirname); try {
return true; await fs.promises.access(file);
await fs.promises.unlink(file);
logger.mark('视频已存在');
} catch (err) {
if (err.code !== 'ENOENT') {
throw err;
} }
} }
} }
// 递归创建目录 异步方法
function mkdirs (dirname, callback) {
fs.exists(dirname, function (exists) {
if (exists) {
callback();
} else {
// console.log(path.dirname(dirname));
mkdirs(path.dirname(dirname), function () {
fs.mkdir(dirname, callback);
});
}
});
}
/** /**
* 删除文件夹下所有问价及将文件夹下所有文件清空 * 创建文件夹如果不存在
* @param {*} path * @param dir
* @returns {Promise<void>}
*/ */
function emptyDir(path) { async function mkdirIfNotExists(dir) {
const files = fs.readdirSync(path); try {
files.forEach(file => { await fs.promises.access(dir);
const filePath = `${path}/${file}`; } catch (err) {
const stats = fs.statSync(filePath); if (err.code === 'ENOENT') {
if (stats.isDirectory()) { await fs.promises.mkdir(dir, { recursive: true });
emptyDir(filePath);
} else { } else {
fs.unlinkSync(filePath); throw err;
console.log(`删除${file}文件成功`);
} }
}); }
} }
export { mkdirs, mkdirsSync, emptyDir } export { checkAndRemoveFile, mkdirIfNotExists }