diff --git a/README.md b/README.md index cace263..78d09c9 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,9 @@ chmod a+rx ~/.local/bin/yt-dlp 小程序解析 +### ✖️ 小蓝鸟问题 +**2024-2-5**,修复小蓝鸟的时候看到free计划已经[没有给查看Tweet的api](https://developer.twitter.com/en/portal/products/basic),原先[使用的库也出现了403报错](https://github.com/PLhery/node-twitter-api-v2),开通会员要100美元,不值得。目前暂停更新,后续有方案和精力再更新! + ## 🤺 R插件交流群 扫码不行就:575663150 @@ -161,7 +164,9 @@ chmod a+rx ~/.local/bin/yt-dlp * [x0rz4](https://gitee.com/x0rz4) 提供依赖掉包解决方案 感谢以下框架的开源: -YouTube解析参考了:[yt-dlp:A youtube-dl fork with additional features and fixes](https://github.com/yt-dlp/yt-dlp) + +YouTube解析参考了: +- [yt-dlp:A youtube-dl fork with additional features and fixes](https://github.com/yt-dlp/yt-dlp) ## ☕ 请我喝一杯瑞幸咖啡 如果你觉得插件能帮助到你增进好友关系,那么你可以在有条件的情况下[请我喝一杯瑞幸咖啡](https://afdian.net/a/zhiyu1998),这是我开源这个插件的最大动力! diff --git a/apps/tools.js b/apps/tools.js index 60c73f5..cfed092 100644 --- a/apps/tools.js +++ b/apps/tools.js @@ -16,6 +16,7 @@ import { DIVIDING_LINE, XHS_NO_WATERMARK_HEADER, REDIS_YUNZAI_ISOVERSEA, + TWITTER_BEARER_TOKEN, } from "../constants/constant.js"; import { containsChinese, formatBiliInfo, getIdVideo, secondsToTime } from "../utils/common.js"; import config from "../model/index.js"; @@ -27,8 +28,8 @@ import { av2BV } from "../utils/bilibili-bv-av-convert.js"; import querystring from "querystring"; import TokenBucket from "../utils/token-bucket.js"; import { getWbi } from "../utils/biliWbi.js"; -import { BILI_SUMMARY } from "../constants/bili.js"; -import { XHS_VIDEO } from "../constants/xhs.js"; +import { BILI_SUMMARY, DY_INFO, TIKTOK_INFO, TWITTER_TWEET_INFO, XHS_REQ_LINK } from "../constants/tools.js"; +import { XHS_VIDEO } from "../constants/tools.js"; import child_process from 'node:child_process' import { getAudio, getVideo } from "../utils/y2b.js"; import { processTikTokUrl } from "../utils/tiktok.js"; @@ -168,7 +169,7 @@ export class tools extends plugin { Referer: "https://www.douyin.com/", cookie: this.douyinCookie, }; - const dyApi = `https://www.douyin.com/aweme/v1/web/aweme/detail/?device_platform=webapp&aid=6383&channel=channel_pc_web&aweme_id=${ douId }&pc_client_type=1&version_code=190500&version_name=19.5.0&cookie_enabled=true&screen_width=1344&screen_height=756&browser_language=zh-CN&browser_platform=Win32&browser_name=Firefox&browser_version=118.0&browser_online=true&engine_name=Gecko&engine_version=109.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=&platform=PC&webid=7284189800734082615&msToken=B1N9FM825TkvFbayDsDvZxM8r5suLrsfQbC93TciS0O9Iii8iJpAPd__FM2rpLUJi5xtMencSXLeNn8xmOS9q7bP0CUsrt9oVTL08YXLPRzZm0dHKLc9PGRlyEk=`; + const dyApi = DY_INFO.replace("{}", douId); // xg参数 const xbParam = xBogus.sign( new URLSearchParams(new URL(dyApi).search).toString(), @@ -236,7 +237,7 @@ export class tools extends plugin { let tiktokVideoId = await getIdVideo(url); tiktokVideoId = tiktokVideoId.replace(/\//g, ""); // API链接 - const API_URL = `https://api16-normal-c-useast1a.tiktokv.com/aweme/v1/feed/?aweme_id=${ tiktokVideoId }`; + const API_URL = TIKTOK_INFO.replace("{}", tiktokVideoId); await fetch(API_URL, { headers: { "User-Agent": @@ -491,7 +492,7 @@ export class tools extends plugin { return true; } - // 小蓝鸟解析 + // 小蓝鸟解析:停止更新 // 例子:https://twitter.com/chonkyanimalx/status/1595834168000204800 async twitter(e) { // 配置参数及解析 @@ -499,65 +500,70 @@ export class tools extends plugin { const twitterUrl = reg.exec(e.msg); const id = twitterUrl[1]; // 判断是否是海外服务器,默认为false - const isProxy = !(await this.isOverseasServer()); - const httpAgent = new HttpsProxyAgent(this.myProxy); - const twitterClient = new TwitterApi(Buffer.from(TWITTER_BEARER_TOKEN, "base64").toString(), !isProxy ?? { httpAgent }); + const isOversea = !(await this.isOverseasServer()); - // 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(async resp => { - e.reply(`识别:小蓝鸟学习版,${ resp.data.text }`); - const downloadPath = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }`; - // 创建文件夹(如果没有过这个群) - if (!fs.existsSync(downloadPath)) { - mkdirsSync(downloadPath); + // 请求 + const params = { + "ids": 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"], + } + await fetch(TWITTER_TWEET_INFO.replace("{}", id), { + headers: { + "User-Agent": "v2TweetLookupJS", + "authorization": `Bearer ${Buffer.from(TWITTER_BEARER_TOKEN, "base64").toString()}` + }, + ...params, + agent: !isOversea ? '' : new HttpProxyAgent(this.myProxy), + }).then(async resp => { + logger.info(resp) + e.reply(`识别:小蓝鸟学习版,${ resp.data.text }`); + const downloadPath = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }`; + // 创建文件夹(如果没有过这个群) + if (!fs.existsSync(downloadPath)) { + mkdirsSync(downloadPath); + } + // 逐个遍历判断 + let task = []; + for (let item of resp.includes.media) { + if (item.type === "photo") { + // 图片 + task.push(this.downloadImg(item.url, downloadPath, "", true)); + } else if (item.type === "video") { + // 视频 + await this.downloadVideo(resp.includes.media[0].variants[0].url, true).then( + _ => { + e.reply(segment.video(`${ downloadPath }/temp.mp4`)); + }, + ); } - // 逐个遍历判断 - let task = []; - for (let item of resp.includes.media) { - if (item.type === "photo") { - // 图片 - task.push(this.downloadImg(item.url, downloadPath, "", true)); - } else if (item.type === "video") { - // 视频 - await this.downloadVideo(resp.includes.media[0].variants[0].url, true).then( - _ => { - e.reply(segment.video(`${ downloadPath }/temp.mp4`)); - }, - ); - } - } - // 如果没有图片直接返回走 - if (task.length === 0) { - return true; - } - // 下面是有图片的情况 - let images = []; - let path = []; - // 获取所有图片的promise - await Promise.all(task).then(resp => { - // console.log(resp) - resp.forEach(item => { - path.push(item); - images.push({ - message: segment.image(fs.readFileSync(item)), - nickname: this.e.sender.card || this.e.user_id, - user_id: this.e.user_id, - }); + } + // 如果没有图片直接返回走 + if (task.length === 0) { + return true; + } + // 下面是有图片的情况 + let images = []; + let path = []; + // 获取所有图片的promise + await Promise.all(task).then(resp => { + // console.log(resp) + resp.forEach(item => { + path.push(item); + images.push({ + message: segment.image(fs.readFileSync(item)), + nickname: this.e.sender.card || this.e.user_id, + user_id: this.e.user_id, }); }); - await e.reply(await Bot.makeForwardMsg(images)); - // 清理文件 - path.forEach(item => { - fs.unlinkSync(item); - }); }); + await e.reply(await Bot.makeForwardMsg(images)); + // 清理文件 + path.forEach(item => { + fs.unlinkSync(item); + }); + }); return true; } @@ -615,7 +621,7 @@ export class tools extends plugin { } const downloadPath = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }`; // 获取信息 - fetch(`https://www.xiaohongshu.com/explore/${ id }`, { + fetch(`${XHS_REQ_LINK}${ id }`, { headers: XHS_NO_WATERMARK_HEADER, }).then(async resp => { const xhsHtml = await resp.text(); @@ -951,8 +957,8 @@ export class tools extends plugin { // bestVideo = Array.from(videos).sort((a, b) => a.rate - b.rate)[videos.length - 1]; // 较为有性能的分辨率 - bestVideo = Array.from(videos).filter(item => item.scale.includes("720") || item.scale.includes("360"))[0]; - bestAudio = Array.from(audios).filter(item => item.format === 'm4a')[0]; + bestVideo = Array.from(videos).find(item => item.scale.includes("720") || item.scale.includes("360")); + bestAudio = Array.from(audios).find(item => item.format === 'm4a'); // logger.mark({ // bestVideo, // bestAudio @@ -969,7 +975,7 @@ export class tools extends plugin { let cmd = //`cd '${__dirname}' && (cd tmp > /dev/null || (mkdir tmp && cd tmp)) &&` + `yt-dlp ${ this.y2bCk !== undefined ? `--cookies ${ this.y2bCk }` : '' } ${url} -f ${ format.replace('x', '+') } ` + `-o '${ fullpath }/${ v }.%(ext)s' ${ isProxy ? `--proxy ${ this.proxyAddr }:${ this.proxyPort }` : '' } -k --write-info-json`; - logger.info(cmd) + logger.mark(cmd) try { await child_process.execSync(cmd); e.reply(segment.video(`${ fullpath }/${ v }.mp4`)) @@ -1147,6 +1153,11 @@ export class tools extends plugin { } } + /** + * 设置海外模式 + * @param e + * @returns {Promise} + */ async setOversea(e) { // 查看当前设置 let os; diff --git a/constants/bili.js b/constants/bili.js deleted file mode 100644 index 8e0c8d9..0000000 --- a/constants/bili.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * AI总结API - * https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/misc/sign/wbi.md - * @type {string} - */ -export const BILI_SUMMARY = "https://api.bilibili.com/x/web-interface/view/conclusion/get" - -/** - * 视频基本信息API - * https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/info.md - * @type {string} - */ -export const BILI_VIDEO_INFO = "http://api.bilibili.com/x/web-interface/view" - -/** - * 登录基本信息 - * https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/login/login_info.md#%E5%AF%BC%E8%88%AA%E6%A0%8F%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF - * @type {string} - */ -export const BILI_NAV = "https://api.bilibili.com/x/web-interface/nav" \ No newline at end of file diff --git a/constants/constant.js b/constants/constant.js index 105f92e..b89ebc7 100644 --- a/constants/constant.js +++ b/constants/constant.js @@ -69,4 +69,6 @@ export const DIVIDING_LINE = "\n------------------{}------------------" * 保存判断机子是否是海外服务器的key * @type {string} */ -export const REDIS_YUNZAI_ISOVERSEA = "Yz:rconsole:tools:oversea"; \ No newline at end of file +export const REDIS_YUNZAI_ISOVERSEA = "Yz:rconsole:tools:oversea"; + +export const TWITTER_BEARER_TOKEN = "" \ No newline at end of file diff --git a/constants/tools.js b/constants/tools.js new file mode 100644 index 0000000..d3026cf --- /dev/null +++ b/constants/tools.js @@ -0,0 +1,50 @@ +/** + * AI总结API + * https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/misc/sign/wbi.md + * @type {string} + */ +export const BILI_SUMMARY = "https://api.bilibili.com/x/web-interface/view/conclusion/get" + +/** + * 视频基本信息API + * https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/info.md + * @type {string} + */ +export const BILI_VIDEO_INFO = "http://api.bilibili.com/x/web-interface/view" + +/** + * 登录基本信息 + * https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/login/login_info.md#%E5%AF%BC%E8%88%AA%E6%A0%8F%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF + * @type {string} + */ +export const BILI_NAV = "https://api.bilibili.com/x/web-interface/nav" + +/** + * 视频请求链接CDN + * @type {string} + */ +export const XHS_VIDEO = "http://sns-video-bd.xhscdn.com/" + +/** + * dy API + * @type {string} + */ +export const DY_INFO = "https://www.douyin.com/aweme/v1/web/aweme/detail/?device_platform=webapp&aid=6383&channel=channel_pc_web&aweme_id={}&pc_client_type=1&version_code=190500&version_name=19.5.0&cookie_enabled=true&screen_width=1344&screen_height=756&browser_language=zh-CN&browser_platform=Win32&browser_name=Firefox&browser_version=118.0&browser_online=true&engine_name=Gecko&engine_version=109.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=&platform=PC&webid=7284189800734082615&msToken=B1N9FM825TkvFbayDsDvZxM8r5suLrsfQbC93TciS0O9Iii8iJpAPd__FM2rpLUJi5xtMencSXLeNn8xmOS9q7bP0CUsrt9oVTL08YXLPRzZm0dHKLc9PGRlyEk=" + +/** + * Tiktok API + * @type {string} + */ +export const TIKTOK_INFO = "https://api16-normal-c-useast1a.tiktokv.com/aweme/v1/feed/?aweme_id={}" + +/** + * X API + * @type {string} + */ +export const TWITTER_TWEET_INFO = "https://api.twitter.com/2/tweets?ids={}" + +/** + * XHS 的请求链接 + * @type {string} + */ +export const XHS_REQ_LINK = "https://www.xiaohongshu.com/explore/" \ No newline at end of file diff --git a/constants/xhs.js b/constants/xhs.js deleted file mode 100644 index 5a305c0..0000000 --- a/constants/xhs.js +++ /dev/null @@ -1,5 +0,0 @@ -/** - * 视频请求链接CDN - * @type {string} - */ -export const XHS_VIDEO = "http://sns-video-bd.xhscdn.com/" \ No newline at end of file diff --git a/utils/biliInfo.js b/utils/biliInfo.js index 482b3fd..535a87f 100644 --- a/utils/biliInfo.js +++ b/utils/biliInfo.js @@ -1,6 +1,6 @@ import fetch from "node-fetch"; import axios from "axios"; -import { BILI_VIDEO_INFO } from "../constants/bili.js"; +import { BILI_VIDEO_INFO } from "../constants/tools.js"; async function getVideoInfo(url) { // const baseVideoInfo = "http://api.bilibili.com/x/web-interface/view"; diff --git a/utils/biliWbi.js b/utils/biliWbi.js index a4303b5..71d148a 100644 --- a/utils/biliWbi.js +++ b/utils/biliWbi.js @@ -1,5 +1,5 @@ import md5 from 'md5' -import { BILI_NAV } from "../constants/bili.js"; +import { BILI_NAV } from "../constants/tools.js"; const mixinKeyEncTab = [ 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,