mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-13 23:59:19 +00:00
🎈 perf: V1.3.2 优化油管解析性能
1. 优化了寻找最佳解析分辨率的算法 2. 优化“魔法值”,增加后期可维护性 3. 说明 X 的不可维护性
This commit is contained in:
parent
9769dce7a4
commit
4046905c83
@ -113,6 +113,9 @@ chmod a+rx ~/.local/bin/yt-dlp
|
||||
|
||||
<img src="./img/douyin_cookie.webp" alt="小程序解析" width="50%" height="50%" />
|
||||
|
||||
### ✖️ 小蓝鸟问题
|
||||
**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),这是我开源这个插件的最大动力!
|
||||
|
137
apps/tools.js
137
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<boolean>}
|
||||
*/
|
||||
async setOversea(e) {
|
||||
// 查看当前设置
|
||||
let os;
|
||||
|
@ -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"
|
@ -69,4 +69,6 @@ export const DIVIDING_LINE = "\n------------------{}------------------"
|
||||
* 保存判断机子是否是海外服务器的key
|
||||
* @type {string}
|
||||
*/
|
||||
export const REDIS_YUNZAI_ISOVERSEA = "Yz:rconsole:tools:oversea";
|
||||
export const REDIS_YUNZAI_ISOVERSEA = "Yz:rconsole:tools:oversea";
|
||||
|
||||
export const TWITTER_BEARER_TOKEN = ""
|
50
constants/tools.js
Normal file
50
constants/tools.js
Normal file
@ -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/"
|
@ -1,5 +0,0 @@
|
||||
/**
|
||||
* 视频请求链接CDN
|
||||
* @type {string}
|
||||
*/
|
||||
export const XHS_VIDEO = "http://sns-video-bd.xhscdn.com/"
|
@ -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";
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user