From 11e73d2cd76781805daa86d4a0c9ed721dd9f7c2 Mon Sep 17 00:00:00 2001 From: zhiyu1998 Date: Sun, 29 Jan 2023 16:57:29 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=8A=A0=E5=85=A5acfun?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=EF=BC=8C=E8=A7=A3=E5=86=B3=E9=83=A8=E5=88=86?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/query.js | 65 ++++++++++++-- apps/tools.js | 98 +++++++++++++++----- config/help.yaml | 6 ++ resources/img/icon/buyer.png | Bin 0 -> 10273 bytes resources/img/icon/推特.png | Bin 0 -> 5319 bytes utils/acfun.js | 164 ++++++++++++++++++++++++++++++++++ utils/file.js | 20 ++++- 7 files changed, 325 insertions(+), 28 deletions(-) create mode 100644 resources/img/icon/buyer.png create mode 100644 resources/img/icon/推特.png create mode 100644 utils/acfun.js diff --git a/apps/query.js b/apps/query.js index ce6993a..4049d40 100644 --- a/apps/query.js +++ b/apps/query.js @@ -19,6 +19,10 @@ export class query extends plugin { reg: '^#*医药查询 (.*)$', fnc: 'doctor' }, + { + reg: '^#*评分 (.*)', + fnc: 'videoScore' + }, { reg: '^#(cat)$', fnc: 'cat' @@ -77,6 +81,41 @@ export class query extends plugin { return !!this.reply(await Bot.makeForwardMsg(msg)) } + async videoScore(e) { + let keyword = e.msg.split(' ')[1] + const api = `https://movie.douban.com/j/subject_suggest?q=${encodeURI(keyword)}`; + + let movieId = 30433417; + fetch(api, { + 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", + "Content-Type": "application/json", + } + }).then(resp => resp.json()).then(resp => { + if (resp.length === 0 || resp === "") { + e.reply("没找到!"); + return true; + } + movieId = resp[0].id; + const doubanApi = `https://movie.querydata.org/api?id=${movieId}`; + fetch(doubanApi, { + 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", + "Content-Type": "application/json", + } + }).then(resp => resp.json()).then(resp => { + if (resp.length === 0 || resp === "") { + e.reply("没找到!"); + return true; + } + e.reply(`识别:${resp.data[0].name}\n烂番茄评分:${resp.imdbRating}\n豆瓣评分:${resp.doubanRating}\n评分:${resp.imdbRating}`); + }) + }) + return true; + } + async cat (e) { const numb = this.catConfig.count let images = [] @@ -196,13 +235,27 @@ export class query extends plugin { } async buyerShow (e) { - const urls = ['https://api.vvhan.com/api/tao', 'http://3650000.xyz/api/?type=img'] - const randomIndex = Math.floor(Math.random() * urls.length); - const randomElement = urls.splice(randomIndex, 1)[0]; - await fetch(randomElement).then(resp => { - e.reply(segment.image(resp.url)) + // http://3650000.xyz/api/?type=img + // https://api.vvhan.com/api/tao + // https://api.uomg.com/api/rand.img3?format=json + // const randomIndex = Math.floor(Math.random() * urls.length); + // const randomElement = urls.splice(randomIndex, 1)[0]; + const p1 = new Promise((resolve, reject) => { + fetch("https://api.vvhan.com/api/tao").then(resp => { + return resolve(resp.url) + }).catch(err => reject(err)) }) - return true + const p2 = new Promise((resolve, reject) => { + fetch("https://api.uomg.com/api/rand.img3?format=json").then(resp => resp.json()).then(resp => { + return resolve(resp.imgurl) + }).catch(err => reject(err)) + }) + Promise.all([p1, p2]).then(res => { + res.forEach(item => { + e.reply(segment.image(item)) + }) + }) + return true; } // 删除标签 diff --git a/apps/tools.js b/apps/tools.js index 3e5aa4e..9869ae1 100644 --- a/apps/tools.js +++ b/apps/tools.js @@ -11,7 +11,8 @@ import { TwitterApi } from 'twitter-api-v2' import HttpProxyAgent from 'https-proxy-agent' import { mkdirsSync } from '../utils/file.js' import { downloadBFile, getDownloadUrl, mergeFileToMp4 } from '../utils/bilibili.js' -import { get, remove, add } from "../utils/redisu.js"; +import { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } from '../utils/acfun.js' +// import { get, remove, add } from "../utils/redisu.js"; const transMap = { "中": "zh", "日": "jp", "文": "wyw", "英": "en" } @@ -46,6 +47,14 @@ export class tools extends plugin { { reg: "(.*)(twitter.com)", fnc: "twitter", + }, + { + reg: "https:\/\/(m.)?v.qq.com\/(.*)", + fnc: "tx" + }, + { + reg: "(.*)(acfun.cn)", + fnc: "acfun" } ], }); @@ -199,24 +208,24 @@ export class tools extends plugin { async wiki (e) { const key = e.msg.replace(/#|百科|wiki/g, "").trim(); const url = `https://xiaoapi.cn/API/bk.php?m=json&type=bd&msg=${ encodeURI(key) }` - const url2 = 'https://api.jikipedia.com/go/auto_complete' + // const url2 = 'https://api.jikipedia.com/go/auto_complete' Promise.all([ - axios.post(url2, { - 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", - "Content-Type": "application/json", - }, - timeout: 10000, - "phrase": key, - }) - .then(resp => { - const data = resp.data.data - if (_.isEmpty(data)) { - return data; - } - return data[0].entities[0]; - }), + // axios.post(url2, { + // 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", + // "Content-Type": "application/json", + // }, + // timeout: 10000, + // "phrase": key, + // }) + // .then(resp => { + // const data = resp.data.data + // if (_.isEmpty(data)) { + // return data; + // } + // return data[0].entities[0]; + // }), axios.get(url, { headers: { "User-Agent": @@ -229,13 +238,13 @@ export class tools extends plugin { }) ]) .then(res => { - const data = res[1] - const data2 = res[0] + const data = res[0] + // const data2 = res[0] const template = ` 解释:${ _.get(data, 'msg') }\n 详情:${ _.get(data, 'more') }\n - 小鸡解释:${ _.get(data2, 'content') } `; + // 小鸡解释:${ _.get(data2, 'content') } e.reply(template) }) return true @@ -286,6 +295,27 @@ export class tools extends plugin { return true; } + // 视频解析 + async tx( e ) { + const url = e.msg + const data = await ( await fetch( `https://xian.txma.cn/API/jx_txjx.php?url=${url}` ) ) + .json() + const k = data.url + const name = data.title + if( k && name ) { + e.reply( name + '\n' + k ) + let forward = await this.makeForwardMsg( url ) + e.reply( forward ) + return true + } else { + e.reply( '解析腾讯视频失败~\n去浏览器使用拼接接口吧...' ) + let forward = await this.makeForwardMsg( url ) + e.reply( forward ) + return true + } + } + + // 请求参数 async douyinRequest (url) { const params = { @@ -361,6 +391,32 @@ export class tools extends plugin { return (idVideo.length > 19) ? idVideo.substring(0, idVideo.indexOf("?")) : idVideo; } + // acfun解析 + async acfun(e) { + const path = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp/` + if (!fs.existsSync(path)) { + mkdirsSync(path); + } + + let inputMsg = e.msg; + // 适配手机分享:https://m.acfun.cn/v/?ac=32838812&sid=d2b0991bd6ad9c09 + if (inputMsg.includes("m.acfun.cn")) { + inputMsg = `https://www.acfun.cn/v/ac${/ac=([^&?]*)/.exec(inputMsg)[1]}` + } + + parseUrl(inputMsg).then(res => { + e.reply(`识别:猴山,${res.videoName}`) + parseM3u8(res.urlM3u8s[res.urlM3u8s.length-1]).then(res2 => { + downloadM3u8Videos(res2.m3u8FullUrls, path).then(_ => { + mergeAcFileToMp4( res2.tsNames, path, `${path}out.mp4`).then(_ => { + e.reply(segment.video(`${path}out.mp4`)) + }) + }) + }) + }) + return true; + } + // 工具:下载哔哩哔哩 async downBili (title, videoUrl, audioUrl) { return Promise.all([ diff --git a/config/help.yaml b/config/help.yaml index 6760ba1..de0daf7 100644 --- a/config/help.yaml +++ b/config/help.yaml @@ -15,6 +15,9 @@ - icon: android title: "#安卓软件推荐" desc: 推荐安卓软件 + - icon: buyer + title: "#买家秀" + desc: 淘宝买家秀 - group: 神秘功能合集 list: - icon: pic1 @@ -46,6 +49,9 @@ - icon: bilibili title: "bilibili/b23" desc: 哔哩哔哩分享实时下载 + - icon: 推特 + title: "bilibili/b23" + desc: 推特学习版分享实时下载 - group: 其他指令[实验] list: - icon: update diff --git a/resources/img/icon/buyer.png b/resources/img/icon/buyer.png new file mode 100644 index 0000000000000000000000000000000000000000..528b5e99692ab30bca3215cfb652da6e7ee063aa GIT binary patch literal 10273 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 \" ->" + * @param str + */ +function escapeSpecialChars(str) { + return str.replace(/\\\\"/g, '\\"').replace(/\\"/g, '"'); +} + +const parseVideoName = (videoInfo) => { + const strAc号 = "ac" + (videoInfo?.dougaId || ""); + const str标题 = videoInfo?.title; + const str作者 = videoInfo?.user.name; + const str上传时间 = videoInfo?.createTime; + const str描述 = videoInfo?.description; + + const raw = [strAc号, str标题, str作者, str上传时间, str描述] + .map((d) => d || "") + .join("_") + .slice(0, 100); + + return raw; +}; + +const parseVideoNameFixed = (videoInfo) => { + const f = parseVideoName(videoInfo); + const t = f.replaceAll(" ", "-"); + return t; +}; + +async function parseUrl(videoUrlAddress) { + // eg https://www.acfun.cn/v/ac4621380?quickViewId=videoInfo_new&ajaxpipe=1 + const urlSuffix = "?quickViewId=videoInfo_new&ajaxpipe=1"; + const url = videoUrlAddress + urlSuffix; + + const raw = await axios.get(url).then(resp => { + return resp.data + }); + // Split + const strsRemoveHeader = raw.split("window.pageInfo = window.videoInfo ="); + const strsRemoveTail = strsRemoveHeader[1].split(""); + const strJson = strsRemoveTail[0]; + + const strJsonEscaped = escapeSpecialChars(strJson); + /** Object videoInfo */ + const videoInfo = JSON.parse(strJsonEscaped); + + const videoName = parseVideoNameFixed(videoInfo); + + const ksPlayJson = videoInfo.currentVideoInfo.ksPlayJson; + /** Object ksPlay */ + const ksPlay = JSON.parse(ksPlayJson); + + const representations = ksPlay.adaptationSet[0].representation; + const urlM3u8s = representations.map((d) => d.url); + + return { urlM3u8s, videoName }; +} + +async function parseM3u8(m3u8Url) { + const m3u8File = await axios.get(m3u8Url).then(resp => resp.data); + + /** 分离ts文件链接 */ + const rawPieces = m3u8File.split(/\n#EXTINF:.{8},\n/); + /** 过滤头部 */ + const m3u8RelativeLinks = rawPieces.slice(1); + /** 修改尾部 去掉尾部多余的结束符 */ + 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); + /** aria2c下载的文件名,就是取url最后一段,去掉末尾url参数(?之后是url参数) */ + const tsNames = m3u8RelativeLinks.map((d) => d.split("?")[0]); + /** 文件夹名,去掉文件名末尾分片号 */ + let outputFolderName = tsNames[0].slice(0, -9); + /** 输出最后合并的文件名,加个通用mp4后缀 */ + const outputFileName = outputFolderName + ".mp4"; + + return { + m3u8FullUrls, + tsNames, + outputFolderName, + outputFileName, + }; +} + +// 下载m3u8 +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, { + 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 => { + 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) { + + /** 合并参数列表 格式file path */ + const concatStrs = tsNames.map( + (d, i) => `file ${path.resolve(FullFileName, i + ".ts").replace(/\\/g, "/")}` + ); + + const ffmpegList = path.resolve(FullFileName, 'file.txt'); + fs.writeFileSync(ffmpegList, concatStrs.join("\n")); + const outPath = path.resolve(outputFileName); + + let cmd = 'ffmpeg'; + const env = { + ...process.env, + PATH: '/usr/local/bin:' + child_process.execSync('echo $PATH').toString(), + }; + + 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); + } + + if (err) { + reject(err); + } + + resolve({ outputFileName }); + }, + ); + }); +} + +export { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } \ No newline at end of file diff --git a/utils/file.js b/utils/file.js index 606563f..9404719 100644 --- a/utils/file.js +++ b/utils/file.js @@ -27,4 +27,22 @@ function mkdirs (dirname, callback) { }); } -export { mkdirs, mkdirsSync } \ No newline at end of file +/** + * 删除文件夹下所有问价及将文件夹下所有文件清空 + * @param {*} path + */ +function emptyDir(path) { + const files = fs.readdirSync(path); + files.forEach(file => { + const filePath = `${path}/${file}`; + const stats = fs.statSync(filePath); + if (stats.isDirectory()) { + emptyDir(filePath); + } else { + fs.unlinkSync(filePath); + console.log(`删除${file}文件成功`); + } + }); +} + +export { mkdirs, mkdirsSync, emptyDir } \ No newline at end of file