diff --git a/README.md b/README.md index 62106e9..3abde4a 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,9 @@ test -- 爬虫文件[python] index -- 主入口 +## 🧏‍♂️使用实例 +![help](./img/example.png) + ## 📔使用说明 1. 【可选】下载mongodb(可能会耗费一些时间:影响功能【`#我靠`】) > linux系统下自己装一个mongodb,上一个密码(不上有风险) diff --git a/apps/tools.js b/apps/tools.js index cb16fca..33bb3b4 100644 --- a/apps/tools.js +++ b/apps/tools.js @@ -439,522 +439,7 @@ export class tools extends plugin { proxy: false, }).then((resp) => { const reg = / resp.json()) - .then((text) => text.trans_result) - .then((res) => this.reply(`${ res[0].dst }`, true)) - .catch((err) => logger.error(err)); - return true; - } - - // 抖音解析 - async douyin (e) { - const urlRex = /(http:|https:)\/\/v.douyin.com\/[A-Za-z\d._?%&+\-=\/#]*/g; - const douUrl = urlRex.exec(e.msg.trim())[0]; - - await this.douyinRequest(douUrl).then(async (res) => { - const douRex = /.*video\/(\d+)\/(.*?)/g; - const douId = douRex.exec(res)[1]; - // const url = `https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=${ douId }`; - const url = `https://www.iesdouyin.com/aweme/v1/web/aweme/detail/?aweme_id=${ douId }&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333` - const resp = await fetch(url); - const json = await resp.json(); - const item = json.aweme_detail; - e.reply(`识别:抖音, ${item.desc}`); - const url_2 = item.video.play_addr.url_list[0]; - this.downloadVideo(url_2).then(video => { - e.reply(segment.video(`${this.defaultPath}${this.e.group_id || this.e.user_id}/temp.mp4`)); - }); - }); - return true; - } - - // tiktok解析 - async tiktok (e) { - const urlRex = /(http:|https:)\/\/www.tiktok.com\/[A-Za-z\d._?%&+\-=\/#@]*/g; - const urlShortRex = /(http:|https:)\/\/vt.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g; - let url = e.msg.trim() - // 短号处理 - if (url.includes('vt.tiktok')) { - const temp_url = urlShortRex.exec(url)[0] - await fetch(temp_url, { - redirect: "follow", - follow: 10, - timeout: 10000, - agent: new HttpProxyAgent(this.myProxy) - }).then((resp) => { - url = resp.url - }) - } else { - url = urlRex.exec(url)[0] - } - const idVideo = await this.getIdVideo(url) - // API链接 - const API_URL = `https://api19-core-useast5.us.tiktokv.com/aweme/v1/feed/?aweme_id=${ idVideo }&version_code=262&app_name=musical_ly&channel=App&device_id=null&os_version=14.4.2&device_platform=iphone&device_type=iPhone9`; - - await axios.get(API_URL, { - 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", - "Accept-Encoding": "gzip,deflate,compress" - }, - timeout: 10000, - proxy: false, - httpAgent: tunnel.httpOverHttp({ proxy: { host: this.proxyAddr, port: this.proxyPort } }), - httpsAgent: tunnel.httpOverHttp({ proxy: { host: this.proxyAddr, port: this.proxyPort } }), - }).then(resp => { - const data = resp.data.aweme_list[0]; - e.reply(`识别:tiktok, ${data.desc}`) - this.downloadVideo(data.video.play_addr.url_list[0], true).then(video => { - e.reply(segment.video(`${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp.mp4`)); - }) - }) - return true - } - - // bilibi解析 - async bili (e) { - const urlRex = /(http:|https:)\/\/www.bilibili.com\/[A-Za-z\d._?%&+\-=\/#]*/g; - const bShortRex = /(http:|https:)\/\/b23.tv\/[A-Za-z\d._?%&+\-=\/#]*/g; - let url = e.msg.trim() - // 短号处理 - if (url.includes('b23.tv')) { - const bShortUrl = bShortRex.exec(url)[0] - await fetch(bShortUrl).then(resp => { - url = resp.url; - }) - } else { - url = urlRex.exec(url)[0]; - } - - const path = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp` - // 待优化 - if (fs.existsSync(`${ path }.mp4`)) { - console.log("视频已存在"); - fs.unlinkSync(`${ path }.mp4`); - } - // 视频信息获取例子:http://api.bilibili.com/x/web-interface/view?bvid=BV1hY411m7cB - const baseVideoInfo = "http://api.bilibili.com/x/web-interface/view"; - console.log(url); - const videoId = /video\/(.*?)(\/|\?)/g.exec(url)[1]; - // 获取视频信息,然后发送 - fetch(videoId.startsWith("BV") ? `${baseVideoInfo}?bvid=${videoId}` : `${baseVideoInfo}?aid=${videoId}`) - .then(resp => resp.json()) - .then(resp => { - e.reply(`识别:哔哩哔哩, ${resp.data.title}`) - }) - - await getDownloadUrl(url) - .then(data => { - this.downBili(path, data.videoUrl, data.audioUrl) - .then(data => { - e.reply(segment.video(`${ path }.mp4`)) - }) - .catch(data => { - e.reply('解析失败,请重试一下') - }); - }) - .catch(err => { - e.reply('解析失败,请重试一下') - }); - return true - } - - // 百科 - async wiki (e) { - const key = e.msg.replace(/#|百科|wiki/g, "").trim(); - const url = `https://xiaoapi.cn/API/bk.php?m=json&type=sg&msg=${ encodeURI(key) }` - // 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.get(url, { - 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", - }, - timeout: 10000, - }) - .then(resp => { - return resp.data - }) - ]) - .then(res => { - const data = res[0] - // const data2 = res[0] - const template = ` - 解释:${ _.get(data, 'msg') }\n - 详情:${ _.get(data, 'more') }\n - `; - // 小鸡解释:${ _.get(data2, 'content') } - e.reply(template) - }) - return true - } - - // twitter解析 - // 例子:https://twitter.com/chonkyanimalx/status/1595834168000204800 - async twitter (e) { - // 配置参数及解析 - const reg = /https?:\/\/twitter.com\/[0-9-a-zA-Z_]{1,20}\/status\/([0-9]*)/ - const twitterUrl = reg.exec(e.msg); - const id = twitterUrl[1]; - const httpAgent = new HttpProxyAgent(this.myProxy) - // TODO 需要填写Twitter id - const twitterClient = new TwitterApi('', {httpAgent}); - - // Tell typescript it's a readonly app - const readOnlyClient = twitterClient.readOnly; - - readOnlyClient.v2.singleTweet(id, { - 'media.fields': 'duration_ms,height,media_key,preview_image_url,public_metrics,type,url,width,alt_text,variants', - expansions: [ - 'entities.mentions.username', - 'attachments.media_keys', - ], - }).then(resp => { - e.reply(`识别:腿忒学习版,${resp.data.text}`) - const downloadPath = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }`; - // 创建文件夹(如果没有过这个群) - if (!fs.existsSync(downloadPath)) { - mkdirsSync(downloadPath); - } - // 开始读取数据 - if (resp.includes.media[0].type === 'photo') { - // 图片 - resp.includes.media.map(item => { - const filePath = `${downloadPath}/${item.url.split('/').pop()}` - this.downloadImgs(item.url, downloadPath).then(tmp => { - e.reply(segment.image(fs.readFileSync(filePath))) - }) - }) - } else { - // 视频 - this.downloadVideo(resp.includes.media[0].variants[0].url, true).then(video => { - e.reply(segment.video(`${downloadPath}/temp.mp4`)); - }); - } - }); - 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 = { - 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", - }, - timeout: 10000, - }; - return new Promise((resolve, reject) => { - axios - .head(url, params) - .then((resp) => { - const location = resp.request.res.responseUrl - resolve(location); - }) - .catch((err) => { - reject(err); - }); - }); - } - - // 工具:根URL据下载视频 / 音频 - async downloadVideo (url, isProxy=false) { - const groupPath = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }`; - if (!fs.existsSync(groupPath)) { - mkdirsSync(groupPath); - } - const target = `${ groupPath }/temp.mp4`; - // 待优化 - if (fs.existsSync(target)) { - console.log(`视频已存在`); - fs.unlinkSync(target); - } - let res; - if (!isProxy) { - res = await axios.get(url, { - 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", - }); - } else { - res = await axios.get(url, { - 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 } }), - }); - } - console.log(`开始下载: ${ url }`); - const writer = fs.createWriteStream(target); - res.data.pipe(writer); - - return new Promise((resolve, reject) => { - writer.on("finish", resolve); - writer.on("error", reject); - }); - } - - // 工具:找到tiktok的视频id - async getIdVideo (url) { - const matching = url.includes("/video/") - if (!matching) { - this.e.reply("没找到,正在获取随机视频!") - return null - } - const idVideo = url.substring(url.indexOf("/video/") + 7, url.length); - 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 redbook(e) { - const msgUrl = /(http:|https:)\/\/(xhslink|xiaohongshu).com\/[A-Za-z\d._?%&+\-=\/#@]*/.exec(e.msg)[0]; - const url = `https://dlpanda.com/zh-CN/xhs?url=${msgUrl}` - - await axios.get(url, { - 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", - "Accept-Encoding": "gzip,deflate,compress" - }, - timeout: 10000, - proxy: false, - }).then((resp) => { - const reg = / 0) { - e.reply(Bot.makeForwardMsg(images)) - } else { - e.reply("解析失败,重新解析下"); - } - }) - - return true; - } - - // 工具:下载哔哩哔哩 - async downBili (title, videoUrl, audioUrl) { - return Promise.all([ - downloadBFile( - videoUrl, - title + '-video.m4s', - _.throttle( - value => - console.log('download-progress', { - type: 'video', - data: value, - }), - 1000, - ), - ), - downloadBFile( - audioUrl, - title + '-audio.m4s', - _.throttle( - value => - console.log('download-progress', { - type: 'audio', - data: value, - }), - 1000, - ), - ), - ]) - .then(data => { - return mergeFileToMp4(data[0].fullFileName, data[1].fullFileName, title + '.mp4'); - }) - } - - // 工具:下载一张网络图片 - async downloadImgs(img, dir) { - - const filename = img.split('/').pop(); - const filepath = `${dir}/${filename}`; - const writer = fs.createWriteStream(filepath); - return axios.get(img, { - 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 } }), - }).then(res => { - res.data.pipe(writer); - return new Promise((resolve, reject) => { - writer.on('finish', () => resolve(filepath)); - writer.on('error', reject); - }); - }); - } - } + let res = ''; let images = []; while (res = reg.exec(resp.data)) { diff --git a/config/help.yaml b/config/help.yaml index de0daf7..e134ede 100644 --- a/config/help.yaml +++ b/config/help.yaml @@ -50,7 +50,7 @@ title: "bilibili/b23" desc: 哔哩哔哩分享实时下载 - icon: 推特 - title: "bilibili/b23" + title: "twitter" desc: 推特学习版分享实时下载 - group: 其他指令[实验] list: diff --git a/img/help.jpg b/img/help.jpg deleted file mode 100644 index 18b431a..0000000 Binary files a/img/help.jpg and /dev/null differ