mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 08:09:19 +00:00
🌟 feat: V1.3.0 新增油管解析
1. 新增油管解析 2. 修复tiktok在海外服务器无法解析问题 3. 更换翻译引擎为全局引擎,并初次使用在油管解析中
This commit is contained in:
parent
ef75e7c12c
commit
083b4ea613
20
README.md
20
README.md
@ -38,7 +38,7 @@ utils -- 工具类
|
|||||||
git clone https://gitee.com/kyrzy0416/rconsole-plugin.git ./plugins/rconsole-plugin/
|
git clone https://gitee.com/kyrzy0416/rconsole-plugin.git ./plugins/rconsole-plugin/
|
||||||
```
|
```
|
||||||
|
|
||||||
2.【必要】在`Yunzai-Bot`目录下安装axios(0.27.2)、魔法工具(tunnel)、哔哩哔哩总结(chatgpt-api)依赖
|
2.【必要】在`Yunzai-Bot`目录下安装axios(0.27.2)、魔法工具(tunnel)
|
||||||
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@ -53,6 +53,19 @@ sudo apt-get install ffmpeg
|
|||||||
# 其他linux参考(群友推荐):https://gitee.com/baihu433/ffmpeg
|
# 其他linux参考(群友推荐):https://gitee.com/baihu433/ffmpeg
|
||||||
# Windows 参考:https://www.jianshu.com/p/5015a477de3c
|
# Windows 参考:https://www.jianshu.com/p/5015a477de3c
|
||||||
````
|
````
|
||||||
|
油管解析需要 yt-dlp 的依赖才能完成解析(三选一):
|
||||||
|
```shell
|
||||||
|
# 三选一
|
||||||
|
# ubuntu (国内 or 国外,且安装了snap)
|
||||||
|
snap install yt-dlp
|
||||||
|
# debian 海外
|
||||||
|
curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o ~/.local/bin/yt-dlp
|
||||||
|
chmod a+rx ~/.local/bin/yt-dlp
|
||||||
|
# debian 国内
|
||||||
|
curl -L https://ghproxy.net/https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o ~/.local/bin/yt-dlp
|
||||||
|
chmod a+rx ~/.local/bin/yt-dlp
|
||||||
|
```
|
||||||
|
|
||||||
4. 【可选】小程序解析适配了:
|
4. 【可选】小程序解析适配了:
|
||||||
* 喵崽:[Yoimiya / Miao-Yunzai](https://gitee.com/yoimiya-kokomi/Miao-Yunzai)
|
* 喵崽:[Yoimiya / Miao-Yunzai](https://gitee.com/yoimiya-kokomi/Miao-Yunzai)
|
||||||
* TRSS:[时雨◎星空 / Yunzai](https://gitee.com/TimeRainStarSky/Yunzai)
|
* TRSS:[时雨◎星空 / Yunzai](https://gitee.com/TimeRainStarSky/Yunzai)
|
||||||
@ -118,7 +131,7 @@ sudo apt-get install ffmpeg
|
|||||||

|

|
||||||
|
|
||||||
## 📝 计划功能
|
## 📝 计划功能
|
||||||
- [ ] YouTube解析(这个可能要🕊一久)
|
- [x] YouTube解析(这个可能要🕊一久)
|
||||||
- [ ] Instagram解析修复
|
- [ ] Instagram解析修复
|
||||||
- [ ] 单张图片解析
|
- [ ] 单张图片解析
|
||||||
- [ ] 视频解析
|
- [ ] 视频解析
|
||||||
@ -142,6 +155,9 @@ sudo apt-get install ffmpeg
|
|||||||
* [一杯凉](https://gitee.com/yibeiliang) 提供小程序解析冲突解决方案
|
* [一杯凉](https://gitee.com/yibeiliang) 提供小程序解析冲突解决方案
|
||||||
* [x0rz4](https://gitee.com/x0rz4) 提供依赖掉包解决方案
|
* [x0rz4](https://gitee.com/x0rz4) 提供依赖掉包解决方案
|
||||||
|
|
||||||
|
感谢以下框架的开源:
|
||||||
|
YouTube解析参考了:[yt-dlp:A youtube-dl fork with additional features and fixes](https://github.com/yt-dlp/yt-dlp)
|
||||||
|
|
||||||
## ☕ 请我喝一杯瑞幸咖啡
|
## ☕ 请我喝一杯瑞幸咖啡
|
||||||
如果你觉得插件能帮助到你增进好友关系,那么你可以在有条件的情况下[请我喝一杯瑞幸咖啡](https://afdian.net/a/zhiyu1998),这是我开源这个插件的最大动力!
|
如果你觉得插件能帮助到你增进好友关系,那么你可以在有条件的情况下[请我喝一杯瑞幸咖啡](https://afdian.net/a/zhiyu1998),这是我开源这个插件的最大动力!
|
||||||
感谢以下朋友的支持!(排名不分多少)
|
感谢以下朋友的支持!(排名不分多少)
|
||||||
|
161
apps/tools.js
161
apps/tools.js
@ -12,9 +12,10 @@ import { parseUrl, parseM3u8, downloadM3u8Videos, mergeAcFileToMp4 } from "../ut
|
|||||||
import {
|
import {
|
||||||
transMap,
|
transMap,
|
||||||
douyinTypeMap,
|
douyinTypeMap,
|
||||||
RESTRICTION_DESCRIPTION, XHS_NO_WATERMARK_HEADER,
|
DIVIDING_LINE,
|
||||||
|
XHS_NO_WATERMARK_HEADER, REDIS_YUNZAI_ISOVERSEA,
|
||||||
} from "../constants/constant.js";
|
} from "../constants/constant.js";
|
||||||
import { formatBiliInfo, getIdVideo, secondsToTime } from "../utils/common.js";
|
import {containsChinese, formatBiliInfo, getIdVideo, secondsToTime} from "../utils/common.js";
|
||||||
import config from "../model/index.js";
|
import config from "../model/index.js";
|
||||||
import Translate from "../utils/trans-strategy.js";
|
import Translate from "../utils/trans-strategy.js";
|
||||||
import * as xBogus from "../utils/x-bogus.cjs";
|
import * as xBogus from "../utils/x-bogus.cjs";
|
||||||
@ -26,6 +27,8 @@ import TokenBucket from "../utils/token-bucket.js";
|
|||||||
import { getWbi } from "../utils/biliWbi.js";
|
import { getWbi } from "../utils/biliWbi.js";
|
||||||
import { BILI_SUMMARY } from "../constants/bili.js";
|
import { BILI_SUMMARY } from "../constants/bili.js";
|
||||||
import { XHS_VIDEO } from "../constants/xhs.js";
|
import { XHS_VIDEO } from "../constants/xhs.js";
|
||||||
|
import child_process from 'node:child_process'
|
||||||
|
import { getAudio, getVideo } from "../utils/y2b.js";
|
||||||
|
|
||||||
export class tools extends plugin {
|
export class tools extends plugin {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -80,6 +83,11 @@ export class tools extends plugin {
|
|||||||
fnc: "clearTrash",
|
fnc: "clearTrash",
|
||||||
permission: "master",
|
permission: "master",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
reg: "^#设置海外解析$",
|
||||||
|
fnc: "setOversea",
|
||||||
|
permission: "master",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
reg: "(h5app.kuwo.cn)",
|
reg: "(h5app.kuwo.cn)",
|
||||||
fnc: "bodianMusic",
|
fnc: "bodianMusic",
|
||||||
@ -88,6 +96,10 @@ export class tools extends plugin {
|
|||||||
reg: "(kuaishou.com)",
|
reg: "(kuaishou.com)",
|
||||||
fnc: "kuaishou",
|
fnc: "kuaishou",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
reg: "(youtube.com)",
|
||||||
|
fnc: "y2b"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
// 配置文件
|
// 配置文件
|
||||||
@ -104,6 +116,12 @@ export class tools extends plugin {
|
|||||||
this.biliDuration = this.toolsConfig.biliDuration;
|
this.biliDuration = this.toolsConfig.biliDuration;
|
||||||
// 加载抖音Cookie
|
// 加载抖音Cookie
|
||||||
this.douyinCookie = this.toolsConfig.douyinCookie;
|
this.douyinCookie = this.toolsConfig.douyinCookie;
|
||||||
|
// 翻译引擎
|
||||||
|
this.translateEngine = new Translate({
|
||||||
|
translateAppId: this.toolsConfig.translateAppId,
|
||||||
|
translateSecret: this.toolsConfig.translateSecret,
|
||||||
|
proxy: this.myProxy,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 翻译插件
|
// 翻译插件
|
||||||
@ -118,13 +136,8 @@ export class tools extends plugin {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const place = msg.slice(1 + language[1].length)
|
const place = msg.slice(1 + language[1].length)
|
||||||
const translateEngine = new Translate({
|
|
||||||
translateAppId: this.toolsConfig.translateAppId,
|
|
||||||
translateSecret: this.toolsConfig.translateSecret,
|
|
||||||
proxy: this.myProxy,
|
|
||||||
});
|
|
||||||
// 如果没有百度那就Google
|
// 如果没有百度那就Google
|
||||||
const translateResult = await translateEngine.translate(place, language[1]);
|
const translateResult = await this.translateEngine.translate(place, language[1]);
|
||||||
e.reply(translateResult.trim(), true);
|
e.reply(translateResult.trim(), true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -216,6 +229,8 @@ export class tools extends plugin {
|
|||||||
const urlShortRex = /(http:|https:)\/\/vt.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
const urlShortRex = /(http:|https:)\/\/vt.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
||||||
const urlShortRex2 = /(http:|https:)\/\/vm.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
const urlShortRex2 = /(http:|https:)\/\/vm.tiktok.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
||||||
let url = e.msg.trim();
|
let url = e.msg.trim();
|
||||||
|
// 判断是否是海外服务器
|
||||||
|
const isOversea = await this.isOverseasServer();
|
||||||
// 短号处理
|
// 短号处理
|
||||||
if (url.includes("vt.tiktok")) {
|
if (url.includes("vt.tiktok")) {
|
||||||
const temp_url = urlShortRex.exec(url)[0];
|
const temp_url = urlShortRex.exec(url)[0];
|
||||||
@ -223,7 +238,7 @@ export class tools extends plugin {
|
|||||||
redirect: "follow",
|
redirect: "follow",
|
||||||
follow: 10,
|
follow: 10,
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
agent: new HttpProxyAgent(this.myProxy),
|
agent: isOversea ? '' : new HttpProxyAgent(this.myProxy),
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
url = resp.url;
|
url = resp.url;
|
||||||
});
|
});
|
||||||
@ -234,7 +249,7 @@ export class tools extends plugin {
|
|||||||
redirect: "follow",
|
redirect: "follow",
|
||||||
follow: 10,
|
follow: 10,
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
agent: new HttpProxyAgent(this.myProxy),
|
agent: isOversea ? '' : new HttpProxyAgent(this.myProxy),
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
url = resp.url;
|
url = resp.url;
|
||||||
});
|
});
|
||||||
@ -255,13 +270,13 @@ export class tools extends plugin {
|
|||||||
// redirect: "follow",
|
// redirect: "follow",
|
||||||
follow: 10,
|
follow: 10,
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
agent: new HttpsProxyAgent(this.myProxy),
|
agent: isOversea ? '' : new HttpProxyAgent(this.myProxy),
|
||||||
})
|
})
|
||||||
.then(async resp => {
|
.then(async resp => {
|
||||||
const respJson = await resp.json();
|
const respJson = await resp.json();
|
||||||
const data = respJson.aweme_list[0];
|
const data = respJson.aweme_list[0];
|
||||||
e.reply(`识别:tiktok, ${ data.desc }`);
|
e.reply(`识别:tiktok, ${ data.desc }`);
|
||||||
this.downloadVideo(data.video.play_addr.url_list[0], true).then(video => {
|
this.downloadVideo(data.video.play_addr.url_list[0], !isOversea).then(video => {
|
||||||
e.reply(
|
e.reply(
|
||||||
segment.video(
|
segment.video(
|
||||||
`${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp.mp4`,
|
`${ this.defaultPath }${ this.e.group_id || this.e.user_id }/temp.mp4`,
|
||||||
@ -343,7 +358,7 @@ export class tools extends plugin {
|
|||||||
biliInfo.unshift(segment.image(pic))
|
biliInfo.unshift(segment.image(pic))
|
||||||
// 限制视频解析
|
// 限制视频解析
|
||||||
const durationInMinutes = (curDuration / 60).toFixed(0);
|
const durationInMinutes = (curDuration / 60).toFixed(0);
|
||||||
biliInfo.push(`${ RESTRICTION_DESCRIPTION }\n当前视频时长约:${ durationInMinutes }分钟,\n大于管理员设置的最大时长 ${ this.biliDuration / 60 } 分钟!`)
|
biliInfo.push(`${ DIVIDING_LINE.replace('{}', '限制说明') }\n当前视频时长约:${ durationInMinutes }分钟,\n大于管理员设置的最大时长 ${ this.biliDuration / 60 } 分钟!`)
|
||||||
summary && biliInfo.push(`\n${ summary }`);
|
summary && biliInfo.push(`\n${ summary }`);
|
||||||
e.reply(biliInfo);
|
e.reply(biliInfo);
|
||||||
return true;
|
return true;
|
||||||
@ -889,6 +904,102 @@ export class tools extends plugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* youtube解析
|
||||||
|
* @param e
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async y2b(e) {
|
||||||
|
const urlRex = /(?:https?:\/\/)?www\.youtube\.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
||||||
|
let url = urlRex.exec(e.msg)[0];
|
||||||
|
// 获取url查询参数
|
||||||
|
const query = querystring.parse(url.split("?")[1]);
|
||||||
|
let p = query?.p || '0';
|
||||||
|
let v = query?.v;
|
||||||
|
// 判断是否是海外服务器,默认为false
|
||||||
|
const isProxy = !(await this.isOverseasServer());
|
||||||
|
|
||||||
|
let audios = [], videos = [];
|
||||||
|
let bestAudio = {}, bestVideo = {};
|
||||||
|
|
||||||
|
let rs = { title: '', thumbnail: '', formats: [] };
|
||||||
|
try {
|
||||||
|
let cmd = `yt-dlp --print-json --skip-download ${this.y2bCk !== undefined ? `--cookies ${this.y2bCk}` : ''} '${url}' ${isProxy ? '--proxy http://127.0.0.1:7890' : ''} 2> /dev/null`
|
||||||
|
console.log('解析视频, 命令:', cmd);
|
||||||
|
rs = child_process.execSync(cmd).toString();
|
||||||
|
try {
|
||||||
|
rs = JSON.parse(rs);
|
||||||
|
} catch (error) {
|
||||||
|
let cmd = `yt-dlp --print-json --skip-download ${this.y2bCk !== undefined ? `--cookies ${this.y2bCk}` : ''} '${url}?p=1' ${isProxy ? '--proxy http://127.0.0.1:7890' : ''} 2> /dev/null`;
|
||||||
|
logger.mark('尝试分P, 命令:', cmd);
|
||||||
|
rs = child_process.execSync(cmd).toString();
|
||||||
|
rs = JSON.parse(rs);
|
||||||
|
p = '1';
|
||||||
|
// url = `${msg.url}?p=1`;
|
||||||
|
}
|
||||||
|
if (!containsChinese(rs.title)) {
|
||||||
|
// 启用翻译引擎翻译不是中文的标题
|
||||||
|
const transedTitle = await this.translateEngine.translate(rs.title, '中');
|
||||||
|
// const transedDescription = await this.translateEngine.translate(rs.description, '中');
|
||||||
|
e.reply(`识别:油管,
|
||||||
|
${rs.title.trim()}\n
|
||||||
|
${DIVIDING_LINE.replace("{}", "R插件翻译引擎服务")}\n
|
||||||
|
${transedTitle}\n
|
||||||
|
${rs.description}
|
||||||
|
`);
|
||||||
|
} else {
|
||||||
|
e.reply(`识别:油管,${rs.title}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error.toString());
|
||||||
|
e.reply("解析失败")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化
|
||||||
|
rs.formats.forEach(it => {
|
||||||
|
let length = (it.filesize_approx ? '≈' : '') + ((it.filesize || it.filesize_approx || 0) / 1024 / 1024).toFixed(2);
|
||||||
|
if (it.audio_ext != 'none') {
|
||||||
|
audios.push(getAudio(it.format_id, it.ext, (it.abr || 0).toFixed(0), it.format_note || it.format || '', length));
|
||||||
|
} else if (it.video_ext != 'none') {
|
||||||
|
videos.push(getVideo(it.format_id, it.ext, it.resolution, it.height, (it.vbr || 0).toFixed(0), it.format_note || it.format || '', length));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 寻找最佳的分辨率
|
||||||
|
// bestAudio = Array.from(audios).sort((a, b) => a.rate - b.rate)[audios.length - 1];
|
||||||
|
// bestVideo = Array.from(videos).sort((a, b) => a.rate - b.rate)[videos.length - 1];
|
||||||
|
|
||||||
|
// 较为有性能的分辨率
|
||||||
|
logger.info(videos)
|
||||||
|
bestVideo = Array.from(videos).filter(item => item.scale.includes("720"))[0];
|
||||||
|
bestAudio = Array.from(audios).filter(item => item.format === 'm4a')[0];
|
||||||
|
logger.info({
|
||||||
|
bestVideo,
|
||||||
|
bestAudio
|
||||||
|
})
|
||||||
|
|
||||||
|
// 格式化yt-dlp的请求
|
||||||
|
const format = `${bestVideo.id}x${bestAudio.id}`
|
||||||
|
// 下载地址格式化
|
||||||
|
const path = `${v}${ p ? `/p${p}` : '' }`;
|
||||||
|
const fullpath = `${ this.defaultPath }${ this.e.group_id || this.e.user_id }/${path}`;
|
||||||
|
// yt-dlp下载
|
||||||
|
let cmd = //`cd '${__dirname}' && (cd tmp > /dev/null || (mkdir tmp && cd tmp)) &&` +
|
||||||
|
`yt-dlp ${this.y2bCk !== undefined ? `--cookies ${this.y2bCk}` : ''} https://youtu.be/${v} -f ${format.replace('x', '+')} ` +
|
||||||
|
`-o '${fullpath}/${v}.%(ext)s' ${isProxy ? '--proxy http://127.0.0.1:7890' : ''} -k --write-info-json`;
|
||||||
|
try {
|
||||||
|
await child_process.execSync(cmd);
|
||||||
|
e.reply(segment.video(`${fullpath}/${v}.mp4`))
|
||||||
|
// 清理文件
|
||||||
|
await deleteFolderRecursive(fullpath);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error.toString());
|
||||||
|
e.reply("y2b下载失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 哔哩哔哩下载
|
* 哔哩哔哩下载
|
||||||
* @param title
|
* @param title
|
||||||
@ -1054,15 +1165,33 @@ export class tools extends plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setOversea(e) {
|
||||||
|
// 查看当前设置
|
||||||
|
let os;
|
||||||
|
if ((await redis.exists(REDIS_YUNZAI_ISOVERSEA))) {
|
||||||
|
os = JSON.parse(await redis.get(REDIS_YUNZAI_ISOVERSEA)).os;
|
||||||
|
}
|
||||||
|
// 设置
|
||||||
|
os = ~os
|
||||||
|
await redis.set(
|
||||||
|
REDIS_YUNZAI_ISOVERSEA,
|
||||||
|
JSON.stringify({
|
||||||
|
os: os,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
e.reply(`当前服务器:${os ? '海外服务器' : '国内服务器'}`)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断是否是海外服务器
|
* 判断是否是海外服务器
|
||||||
* @return {Promise<Boolean>}
|
* @return {Promise<Boolean>}
|
||||||
*/
|
*/
|
||||||
async isOverseasServer() {
|
async isOverseasServer() {
|
||||||
const isOS = "Yz:rconsole:tools:oversea";
|
|
||||||
// 如果第一次使用没有值就设置
|
// 如果第一次使用没有值就设置
|
||||||
if (!(await redis.exists(isOS))) {
|
if (!(await redis.exists(REDIS_YUNZAI_ISOVERSEA))) {
|
||||||
await redis.set(
|
await redis.set(
|
||||||
|
REDIS_YUNZAI_ISOVERSEA,
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
os: false,
|
os: false,
|
||||||
}),
|
}),
|
||||||
@ -1070,7 +1199,7 @@ export class tools extends plugin {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// 如果有就取出来
|
// 如果有就取出来
|
||||||
return JSON.parse(redis.get(isOS)).os;
|
return JSON.parse((await redis.get(REDIS_YUNZAI_ISOVERSEA))).os;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,6 +41,9 @@
|
|||||||
- icon: bilimusic
|
- icon: bilimusic
|
||||||
title: "bili音乐+链接"
|
title: "bili音乐+链接"
|
||||||
desc: 哔哩哔哩音乐分享实时下载
|
desc: 哔哩哔哩音乐分享实时下载
|
||||||
|
- icon: youtube
|
||||||
|
title: "youtube.com"
|
||||||
|
desc: 油管学习版分享实时下载
|
||||||
- icon: 推特
|
- icon: 推特
|
||||||
title: "小蓝鸟"
|
title: "小蓝鸟"
|
||||||
desc: 推特学习版分享实时下载
|
desc: 推特学习版分享实时下载
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
- {
|
- {
|
||||||
version: 1.2.3,
|
version: 1.3.0,
|
||||||
data:
|
data:
|
||||||
[
|
[
|
||||||
|
新增<span class="cmd">油管解析</span>功能,
|
||||||
新增<span class="cmd">小红书无水印下载</span>功能,
|
新增<span class="cmd">小红书无水印下载</span>功能,
|
||||||
新增<span class="cmd">哔哩哔哩官方AI总结</span>功能,
|
新增<span class="cmd">哔哩哔哩官方AI总结</span>功能,
|
||||||
新增<span class="cmd">哔哩哔哩音乐提取</span>功能,
|
|
||||||
新增<span class="cmd">快手解析</span>功能,
|
新增<span class="cmd">快手解析</span>功能,
|
||||||
支持<span class="cmd">锅巴</span>插件,方便查看和修改配置,
|
支持<span class="cmd">锅巴</span>插件,方便查看和修改配置,
|
||||||
添加<span class="cmd">#R帮助</span>获取插件帮助,
|
添加<span class="cmd">#R帮助</span>获取插件帮助,
|
||||||
|
@ -59,4 +59,10 @@ export const XHS_NO_WATERMARK_HEADER = {
|
|||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4098.3 Safari/537.36',
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4098.3 Safari/537.36',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RESTRICTION_DESCRIPTION = "\n-----------------------限制说明-----------------------"
|
/**
|
||||||
|
* 分割线
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const DIVIDING_LINE = "\n-----------------------{}-----------------------"
|
||||||
|
|
||||||
|
export const REDIS_YUNZAI_ISOVERSEA = "Yz:rconsole:tools:oversea";
|
BIN
resources/img/icon/youtube.png
Normal file
BIN
resources/img/icon/youtube.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
@ -9,7 +9,7 @@ import {TEN_THOUSAND} from "../constants/constant.js";
|
|||||||
/**
|
/**
|
||||||
* 请求模板
|
* 请求模板
|
||||||
*/
|
*/
|
||||||
class jFeatch {
|
export class jFetch {
|
||||||
async get(url) {
|
async get(url) {
|
||||||
const r = await fetch(url);
|
const r = await fetch(url);
|
||||||
return await r.json();
|
return await r.json();
|
||||||
@ -26,7 +26,7 @@ class jFeatch {
|
|||||||
* @param time cron
|
* @param time cron
|
||||||
* @param isAutoPush 是否推送(开关)
|
* @param isAutoPush 是否推送(开关)
|
||||||
*/
|
*/
|
||||||
function autoTask(func, time, groupList, isAutoPush = false) {
|
export function autoTask(func, time, groupList, isAutoPush = false) {
|
||||||
if (isAutoPush) {
|
if (isAutoPush) {
|
||||||
schedule.scheduleJob(time, () => {
|
schedule.scheduleJob(time, () => {
|
||||||
// 正常传输
|
// 正常传输
|
||||||
@ -55,7 +55,7 @@ function autoTask(func, time, groupList, isAutoPush = false) {
|
|||||||
* @param delay
|
* @param delay
|
||||||
* @returns {Promise<unknown>}
|
* @returns {Promise<unknown>}
|
||||||
*/
|
*/
|
||||||
function retry(func, maxRetries = 3, delay = 1000) {
|
export function retry(func, maxRetries = 3, delay = 1000) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const attempt = (remainingTries) => {
|
const attempt = (remainingTries) => {
|
||||||
func()
|
func()
|
||||||
@ -79,7 +79,7 @@ function retry(func, maxRetries = 3, delay = 1000) {
|
|||||||
* @param filename
|
* @param filename
|
||||||
* @returns {Promise<unknown>}
|
* @returns {Promise<unknown>}
|
||||||
*/
|
*/
|
||||||
function downloadPDF (url, filename) {
|
export function downloadPDF (url, filename) {
|
||||||
return axios({
|
return axios({
|
||||||
url: url,
|
url: url,
|
||||||
responseType: "stream",
|
responseType: "stream",
|
||||||
@ -102,7 +102,7 @@ function downloadPDF (url, filename) {
|
|||||||
* @param url
|
* @param url
|
||||||
* @returns {Promise<string|string|null>}
|
* @returns {Promise<string|string|null>}
|
||||||
*/
|
*/
|
||||||
async function getIdVideo(url) {
|
export async function getIdVideo(url) {
|
||||||
const matching = url.includes("/video/");
|
const matching = url.includes("/video/");
|
||||||
if (!matching) {
|
if (!matching) {
|
||||||
this.e.reply("没找到,正在获取随机视频!");
|
this.e.reply("没找到,正在获取随机视频!");
|
||||||
@ -112,7 +112,7 @@ async function getIdVideo(url) {
|
|||||||
return idVideo.length > 19 ? idVideo.substring(0, idVideo.indexOf("?")) : idVideo;
|
return idVideo.length > 19 ? idVideo.substring(0, idVideo.indexOf("?")) : idVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateRandomStr(randomlength = 16){
|
export function generateRandomStr(randomlength = 16){
|
||||||
const base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789='
|
const base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789='
|
||||||
let random_str = ''
|
let random_str = ''
|
||||||
for (let i = 0; i < randomlength; i++) {
|
for (let i = 0; i < randomlength; i++) {
|
||||||
@ -128,7 +128,7 @@ function generateRandomStr(randomlength = 16){
|
|||||||
* @param redirect 是否要重定向
|
* @param redirect 是否要重定向
|
||||||
* @returns {Promise<unknown>}
|
* @returns {Promise<unknown>}
|
||||||
*/
|
*/
|
||||||
async function downloadMp3(mp3Url, path, redirect = "manual") {
|
export async function downloadMp3(mp3Url, path, redirect = "manual") {
|
||||||
return fetch(mp3Url, {
|
return fetch(mp3Url, {
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent":
|
"User-Agent":
|
||||||
@ -178,7 +178,7 @@ const dataProcessing = data => {
|
|||||||
* @param data
|
* @param data
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
function formatBiliInfo(data) {
|
export function formatBiliInfo(data) {
|
||||||
return Object.keys(data).map(key => `${key}:${dataProcessing(data[key])}`).join(' | ');
|
return Object.keys(data).map(key => `${key}:${dataProcessing(data[key])}`).join(' | ');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ function formatBiliInfo(data) {
|
|||||||
* @param seconds
|
* @param seconds
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
function secondsToTime(seconds) {
|
export function secondsToTime(seconds) {
|
||||||
const pad = (num, size) => num.toString().padStart(size, '0');
|
const pad = (num, size) => num.toString().padStart(size, '0');
|
||||||
|
|
||||||
let hours = Math.floor(seconds / 3600);
|
let hours = Math.floor(seconds / 3600);
|
||||||
@ -201,4 +201,29 @@ function secondsToTime(seconds) {
|
|||||||
return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(secs, 2)}`;
|
return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(secs, 2)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { jFeatch, autoTask, retry, getIdVideo, generateRandomStr, downloadMp3, dataProcessing, formatBiliInfo, secondsToTime };
|
/**
|
||||||
|
* 判断字符串是否是中文(全局判断)
|
||||||
|
* @param str
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isChinese(str) {
|
||||||
|
return /^[\u4e00-\u9fff]+$/.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断字符串是否包含中文
|
||||||
|
* @param str
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function containsChinese(str) {
|
||||||
|
return /[\u4e00-\u9fff]/.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断字符串是否包含中文 && 检测标点符号
|
||||||
|
* @param str
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function containsChineseOrPunctuation(str) {
|
||||||
|
return /[\u4e00-\u9fff\uff00-\uffef]/.test(str);
|
||||||
|
}
|
||||||
|
27
utils/y2b.js
Normal file
27
utils/y2b.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* y2b 音频信息
|
||||||
|
* @param id
|
||||||
|
* @param format
|
||||||
|
* @param rate
|
||||||
|
* @param info
|
||||||
|
* @param size
|
||||||
|
* @returns {{size: (string|*), rate: (string|*), format, id, info}}
|
||||||
|
*/
|
||||||
|
export function getAudio(id, format, rate, info, size) {
|
||||||
|
return { id, format, rate: rate == 0 ? '未知' : rate, info, size: size == 0 ? '未知' : size };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* y2b 视频信息
|
||||||
|
* @param id
|
||||||
|
* @param format
|
||||||
|
* @param scale
|
||||||
|
* @param frame
|
||||||
|
* @param rate
|
||||||
|
* @param info
|
||||||
|
* @param size
|
||||||
|
* @returns {{size: (string|*), rate: (string|*), format, scale, id, frame, info}}
|
||||||
|
*/
|
||||||
|
export function getVideo(id, format, scale, frame, rate, info, size) {
|
||||||
|
return { id, format, scale, frame, rate: rate == 0 ? '未知' : rate, info, size: size == 0 ? '未知' : size };
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user