From 81a027219ff8a8ecc417922cb80d48d0ad371fd1 Mon Sep 17 00:00:00 2001 From: RrOrange <1370346834@qq.com> Date: Thu, 30 Mar 2023 23:48:30 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=84=20refactor:=20=E9=87=8D=E5=86=99in?= =?UTF-8?q?dex=20&=20acfun=E9=87=8D=E5=86=99=E5=90=88=E6=88=90=20&=20?= =?UTF-8?q?=F0=9F=8E=88=20perf:=20=E6=90=9C=E4=B9=A6=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=81=A5=E5=A3=AE=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/query.js | 9 +++++ index.js | 40 ++++++++++++--------- utils/acfun.js | 95 ++++++++++++++++++++++---------------------------- 3 files changed, 75 insertions(+), 69 deletions(-) diff --git a/apps/query.js b/apps/query.js index d2dfac1..afb5677 100644 --- a/apps/query.js +++ b/apps/query.js @@ -299,6 +299,10 @@ export class query extends plugin { // 搜书 async searchBook(e) { let keyword = e.msg.replace(/#|搜书/g, "").trim(); + if (_.isEmpty(keyword)) { + e.reply(`请输入书名,例如:#搜书 非暴力沟通`); + return true; + } const thisBookMethod = this; // 主要数据来源 await Promise.all([getZHelper(e, keyword), getYiBook(e, keyword)]).then(async allRes => { @@ -323,6 +327,11 @@ export class query extends plugin { // 通过id搜书 async searchBookById(e) { let keyword = e.msg.replace(/#bookid/, "").trim(); + if (_.isEmpty(keyword)) { + e.reply(`请输入书名,例如:#搜书 12`); + return true; + } + let id, source; if (keyword.includes(" ")) { [id, source] = keyword.split(" "); diff --git a/index.js b/index.js index 95ed81e..7270e05 100644 --- a/index.js +++ b/index.js @@ -1,21 +1,29 @@ -import fs from 'node:fs' -import RConfig from './model/index.js' +import fs from "node:fs"; +import RConfig from "./model/index.js"; -const versionData = RConfig.getConfig('version') +const versionData = RConfig.getConfig("version"); -logger.info('--------------------------') -logger.info(`rconsole插件${versionData[0].version}初始化~`) -logger.info('--------------------------') +logger.info(`R插件${versionData[0].version}初始化`); -// 读取功能 -const files = fs - .readdirSync('./plugins/rconsole-plugin/apps') - .filter((file) => file.endsWith('.js')) +const files = fs.readdirSync("./plugins/rconsole-plugin/apps").filter(file => file.endsWith(".js")); -let apps = {} -for (let file of files) { - let name = file.replace('.js', '') - apps[name] = (await import(`./apps/${file}`))[name] +let ret = []; + +files.forEach(file => { + ret.push(import(`./apps/${file}`)); +}); + +ret = await Promise.allSettled(ret); + +let apps = {}; +for (let i in files) { + let name = files[i].replace(".js", ""); + + if (ret[i].status !== "fulfilled") { + logger.error(`载入插件错误:${logger.red(name)}`); + logger.error(ret[i].reason); + continue; + } + apps[name] = ret[i].value[Object.keys(ret[i].value)[0]]; } - -export { apps } +export { apps }; diff --git a/utils/acfun.js b/utils/acfun.js index 5be5be6..4291bd2 100644 --- a/utils/acfun.js +++ b/utils/acfun.js @@ -1,7 +1,8 @@ -import axios from 'axios' -import fs from 'node:fs' -import path from 'path' -import child_process from 'node:child_process' +import axios from "axios"; +import fs from "node:fs"; +import path from "path"; +import child_process from "node:child_process"; +import util from "util"; /** * 去除JSON的一些转义 \\" -> \" ->" @@ -11,7 +12,7 @@ function escapeSpecialChars(str) { return str.replace(/\\\\"/g, '\\"').replace(/\\"/g, '"'); } -const parseVideoName = (videoInfo) => { +const parseVideoName = videoInfo => { const strAc号 = "ac" + (videoInfo?.dougaId || ""); const str标题 = videoInfo?.title; const str作者 = videoInfo?.user.name; @@ -19,14 +20,14 @@ const parseVideoName = (videoInfo) => { const str描述 = videoInfo?.description; const raw = [strAc号, str标题, str作者, str上传时间, str描述] - .map((d) => d || "") + .map(d => d || "") .join("_") .slice(0, 100); return raw; }; -const parseVideoNameFixed = (videoInfo) => { +const parseVideoNameFixed = videoInfo => { const f = parseVideoName(videoInfo); const t = f.replaceAll(" ", "-"); return t; @@ -38,7 +39,7 @@ async function parseUrl(videoUrlAddress) { const url = videoUrlAddress + urlSuffix; const raw = await axios.get(url).then(resp => { - return resp.data + return resp.data; }); // Split const strsRemoveHeader = raw.split("window.pageInfo = window.videoInfo ="); @@ -56,7 +57,7 @@ async function parseUrl(videoUrlAddress) { const ksPlay = JSON.parse(ksPlayJson); const representations = ksPlay.adaptationSet[0].representation; - const urlM3u8s = representations.map((d) => d.url); + const urlM3u8s = representations.map(d => d.url); return { urlM3u8s, videoName }; } @@ -69,15 +70,14 @@ async function parseM3u8(m3u8Url) { /** 过滤头部 */ const m3u8RelativeLinks = rawPieces.slice(1); /** 修改尾部 去掉尾部多余的结束符 */ - const patchedTail = - m3u8RelativeLinks[m3u8RelativeLinks.length - 1].split("\n")[0]; + const patchedTail = m3u8RelativeLinks[m3u8RelativeLinks.length - 1].split("\n")[0]; m3u8RelativeLinks[m3u8RelativeLinks.length - 1] = patchedTail; /** 完整链接,直接加m3u8Url的通用前缀 */ const m3u8Prefix = m3u8Url.split("/").slice(0, -1).join("/"); - const m3u8FullUrls = m3u8RelativeLinks.map((d) => m3u8Prefix + "/" + d); + const m3u8FullUrls = m3u8RelativeLinks.map(d => m3u8Prefix + "/" + d); /** aria2c下载的文件名,就是取url最后一段,去掉末尾url参数(?之后是url参数) */ - const tsNames = m3u8RelativeLinks.map((d) => d.split("?")[0]); + const tsNames = m3u8RelativeLinks.map(d => d.split("?")[0]); /** 文件夹名,去掉文件名末尾分片号 */ let outputFolderName = tsNames[0].slice(0, -9); /** 输出最后合并的文件名,加个通用mp4后缀 */ @@ -92,82 +92,71 @@ async function parseM3u8(m3u8Url) { } // 下载m3u8 -async function downloadM3u8Videos( - m3u8FullUrls, - outputFolderName -) { +async function downloadM3u8Videos(m3u8FullUrls, outputFolderName) { /** 新建下载文件夹 在当前运行目录下 */ const outPath = outputFolderName; /** 批下载 */ - const strDownloadParamFiles = m3u8FullUrls - .map(async (d, i) => { - - return new Promise((resolve, reject) => { - const writer = fs.createWriteStream(outPath + `${i}.ts`); - axios.get(d, { + const strDownloadParamFiles = m3u8FullUrls.map(async (d, i) => { + return new Promise((resolve, reject) => { + const writer = fs.createWriteStream(outPath + `${i}.ts`); + axios + .get(d, { 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", - }).then(dres => { + }) + .then(dres => { dres.data.pipe(writer); writer.on("finish", () => resolve(true)); writer.on("error", () => reject); }); - }) - - }) + }); + }); /** 写入下载链接列表文件 */ // fs.writeFileSync(path.resolve(outPath, "urls.txt"), str下载参数文件); return Promise.all(strDownloadParamFiles); } - -function mergeAcFileToMp4(tsNames, FullFileName, outputFileName, shouldDelete = true) { - +async function mergeAcFileToMp4(tsNames, FullFileName, outputFileName, shouldDelete = true) { /** 合并参数列表 格式file path */ const concatStrs = tsNames.map( - (d, i) => `file ${path.resolve(FullFileName, i + ".ts").replace(/\\/g, "/")}` + (d, i) => `file ${path.resolve(FullFileName, i + ".ts").replace(/\\/g, "/")}`, ); - const ffmpegList = path.resolve(FullFileName, 'file.txt'); + const ffmpegList = path.resolve(FullFileName, "file.txt"); fs.writeFileSync(ffmpegList, concatStrs.join("\n")); const outPath = path.resolve(outputFileName); - // 执行命令 - let cmd = 'ffmpeg'; // 判断当前环境 let env; if (process.platform === "win32") { - env = process.env + env = process.env; } else if (process.platform === "linux") { env = { ...process.env, - PATH: '/usr/local/bin:' + child_process.execSync('echo $PATH').toString(), + PATH: "/usr/local/bin:" + child_process.execSync("echo $PATH").toString(), }; } else { - console.log("暂时不支持当前操作系统!") + console.log("暂时不支持当前操作系统!"); } - return new Promise((resolve, reject) => { - child_process.exec( - `${ cmd } -y -f concat -safe 0 -i "${ ffmpegList }" -c copy "${ outPath }"`, - { env }, - err => { - if (shouldDelete) { - fs.unlink(FullFileName, f => f); - } + const execFile = util.promisify(child_process.execFile); + try { + const cmd = "ffmpeg"; + const args = ["-y", "-f", "concat", "-safe", "0", "-i", ffmpegList, "-c", "copy", outPath]; + await execFile(cmd, args, { env }); - if (err) { - reject(err); - } + if (shouldDelete) { + await fs.promises.unlink(FullFileName); + } - resolve({ outputFileName }); - }, - ); - }); + return { outputFileName }; + } catch (err) { + logger.error(err); + } } -export { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } \ No newline at end of file +export { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 };