mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 08:09:19 +00:00
✨feat: 添加全局控制解析
This commit is contained in:
parent
ea3c4ab85d
commit
6cb29f8012
@ -1,6 +1,6 @@
|
|||||||
import config from "../model/config.js";
|
|
||||||
import schedule from 'node-schedule';
|
import schedule from 'node-schedule';
|
||||||
import { REDIS_YUNZAI_ISOVERSEA, REDIS_YUNZAI_WHITELIST } from "../constants/constant.js";
|
import { REDIS_YUNZAI_ISOVERSEA, REDIS_YUNZAI_WHITELIST } from "../constants/constant.js";
|
||||||
|
import config from "../model/config.js";
|
||||||
import { deleteFolderRecursive, readCurrentDir } from "../utils/file.js";
|
import { deleteFolderRecursive, readCurrentDir } from "../utils/file.js";
|
||||||
import { redisExistAndGetKey, redisGetKey, redisSetKey } from "../utils/redis-util.js";
|
import { redisExistAndGetKey, redisGetKey, redisSetKey } from "../utils/redis-util.js";
|
||||||
|
|
||||||
|
118
apps/tools.js
118
apps/tools.js
@ -27,6 +27,7 @@ import {
|
|||||||
TWITTER_BEARER_TOKEN,
|
TWITTER_BEARER_TOKEN,
|
||||||
XHS_NO_WATERMARK_HEADER
|
XHS_NO_WATERMARK_HEADER
|
||||||
} from "../constants/constant.js";
|
} from "../constants/constant.js";
|
||||||
|
import { REDIS_YUNZAI_RESOLVE_CONTROLLER, RESOLVE_CONTROLLER_NAME_ENUM } from "../constants/resolve.js";
|
||||||
import {
|
import {
|
||||||
ANIME_SERIES_SEARCH_LINK,
|
ANIME_SERIES_SEARCH_LINK,
|
||||||
ANIME_SERIES_SEARCH_LINK2,
|
ANIME_SERIES_SEARCH_LINK2,
|
||||||
@ -99,7 +100,7 @@ import { contentEstimator } from "../utils/link-share-summary-util.js";
|
|||||||
import { deepSeekChat, llmRead } from "../utils/llm-util.js";
|
import { deepSeekChat, llmRead } from "../utils/llm-util.js";
|
||||||
import { getDS } from "../utils/mihoyo.js";
|
import { getDS } from "../utils/mihoyo.js";
|
||||||
import { OpenaiBuilder } from "../utils/openai-builder.js";
|
import { OpenaiBuilder } from "../utils/openai-builder.js";
|
||||||
import { redisExistKey, redisGetKey, redisSetKey } from "../utils/redis-util.js";
|
import { redisExistAndGetKey, redisExistKey, redisGetKey, redisSetKey } from "../utils/redis-util.js";
|
||||||
import { saveTDL, startTDL } from "../utils/tdl-util.js";
|
import { saveTDL, startTDL } from "../utils/tdl-util.js";
|
||||||
import { genVerifyFp } from "../utils/tiktok.js";
|
import { genVerifyFp } from "../utils/tiktok.js";
|
||||||
import Translate from "../utils/trans-strategy.js";
|
import Translate from "../utils/trans-strategy.js";
|
||||||
@ -341,6 +342,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 抖音解析
|
// 抖音解析
|
||||||
async douyin(e) {
|
async douyin(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.douyin))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.douyin } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const urlRex = /(http:\/\/|https:\/\/)(v|live).douyin.com\/[A-Za-z\d._?%&+\-=\/#]*/;
|
const urlRex = /(http:\/\/|https:\/\/)(v|live).douyin.com\/[A-Za-z\d._?%&+\-=\/#]*/;
|
||||||
// 检测无效链接,例如:v.douyin.com
|
// 检测无效链接,例如:v.douyin.com
|
||||||
if (!urlRex.test(e.msg)) {
|
if (!urlRex.test(e.msg)) {
|
||||||
@ -610,6 +616,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// tiktok解析
|
// tiktok解析
|
||||||
async tiktok(e) {
|
async tiktok(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.tiktok))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.tiktok } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// 判断海外
|
// 判断海外
|
||||||
const isOversea = await this.isOverseasServer();
|
const isOversea = await this.isOverseasServer();
|
||||||
// 如果不是海外用户且没有梯子直接返回
|
// 如果不是海外用户且没有梯子直接返回
|
||||||
@ -712,6 +723,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// B 站解析
|
// B 站解析
|
||||||
async bili(e) {
|
async bili(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.bili))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.bili } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const urlRex = /(?:https?:\/\/)?www\.bilibili\.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
const urlRex = /(?:https?:\/\/)?www\.bilibili\.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
||||||
const bShortRex = /(http:|https:)\/\/b23.tv\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
const bShortRex = /(http:|https:)\/\/b23.tv\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
||||||
let url = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim().replaceAll("\\", "");
|
let url = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim().replaceAll("\\", "");
|
||||||
@ -1232,6 +1248,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 使用现有api解析小蓝鸟
|
// 使用现有api解析小蓝鸟
|
||||||
async twitter_x(e) {
|
async twitter_x(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.twitter_x))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.twitter_x } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!(await this.isTrustUser(e.user_id))) {
|
if (!(await this.isTrustUser(e.user_id))) {
|
||||||
e.reply("你没有权限使用此命令");
|
e.reply("你没有权限使用此命令");
|
||||||
return;
|
return;
|
||||||
@ -1297,6 +1318,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// acfun解析
|
// acfun解析
|
||||||
async acfun(e) {
|
async acfun(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.acfun))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.acfun } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const path = `${ this.getCurDownloadPath(e) }/temp/`;
|
const path = `${ this.getCurDownloadPath(e) }/temp/`;
|
||||||
await mkdirIfNotExists(path);
|
await mkdirIfNotExists(path);
|
||||||
|
|
||||||
@ -1324,6 +1350,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 小红书解析
|
// 小红书解析
|
||||||
async xhs(e) {
|
async xhs(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.xhs))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.xhs } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// 正则说明:匹配手机链接、匹配小程序、匹配PC链接
|
// 正则说明:匹配手机链接、匹配小程序、匹配PC链接
|
||||||
let msgUrl =
|
let msgUrl =
|
||||||
/(http:|https:)\/\/(xhslink|xiaohongshu).com\/[A-Za-z\d._?%&+\-=\/#@]*/.exec(
|
/(http:|https:)\/\/(xhslink|xiaohongshu).com\/[A-Za-z\d._?%&+\-=\/#@]*/.exec(
|
||||||
@ -1447,6 +1478,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 波点音乐解析
|
// 波点音乐解析
|
||||||
async bodianMusic(e) {
|
async bodianMusic(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.bodianMusic))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.bodianMusic } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// 音频例子:https://h5app.kuwo.cn/m/bodian/playMusic.html?uid=3216773&musicId=192015898&opusId=&extendType=together
|
// 音频例子:https://h5app.kuwo.cn/m/bodian/playMusic.html?uid=3216773&musicId=192015898&opusId=&extendType=together
|
||||||
// 视频例子:https://h5app.kuwo.cn/m/bodian/play.html?uid=3216773&mvId=118987&opusId=770096&extendType=together
|
// 视频例子:https://h5app.kuwo.cn/m/bodian/play.html?uid=3216773&mvId=118987&opusId=770096&extendType=together
|
||||||
const id =
|
const id =
|
||||||
@ -1644,6 +1680,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 网易云解析
|
// 网易云解析
|
||||||
async netease(e) {
|
async netease(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.netease))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.netease } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let message =
|
let message =
|
||||||
e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim();
|
e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim();
|
||||||
// 处理短号,此时会变成y.music.163.com
|
// 处理短号,此时会变成y.music.163.com
|
||||||
@ -1901,6 +1942,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 微博解析
|
// 微博解析
|
||||||
async weibo(e) {
|
async weibo(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.weibo))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.weibo } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let weiboId;
|
let weiboId;
|
||||||
const weiboUrl = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim().replaceAll("\\", "");
|
const weiboUrl = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim().replaceAll("\\", "");
|
||||||
// 对已知情况进行判断
|
// 对已知情况进行判断
|
||||||
@ -1994,6 +2040,11 @@ export class tools extends plugin {
|
|||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async general(e) {
|
async general(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.general))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.general } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const adapter = await GeneralLinkAdapter.create(e.msg);
|
const adapter = await GeneralLinkAdapter.create(e.msg);
|
||||||
e.reply(`${ this.identifyPrefix }识别:${ adapter.name }${ adapter.desc ? `, ${ adapter.desc }` : '' }`);
|
e.reply(`${ this.identifyPrefix }识别:${ adapter.name }${ adapter.desc ? `, ${ adapter.desc }` : '' }`);
|
||||||
@ -2026,6 +2077,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 油管解析
|
// 油管解析
|
||||||
async sy2b(e) {
|
async sy2b(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.sy2b))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.sy2b } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const timeRange = ytbFormatTime(this.youtubeClipTime);
|
const timeRange = ytbFormatTime(this.youtubeClipTime);
|
||||||
const isOversea = await this.isOverseasServer();
|
const isOversea = await this.isOverseasServer();
|
||||||
if (!isOversea && !(await testProxy(this.proxyAddr, this.proxyPort))) {
|
if (!isOversea && !(await testProxy(this.proxyAddr, this.proxyPort))) {
|
||||||
@ -2098,6 +2154,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 米游社
|
// 米游社
|
||||||
async miyoushe(e) {
|
async miyoushe(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.miyoushe))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.miyoushe } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let url = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim();
|
let url = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim();
|
||||||
let msg = /(?:https?:\/\/)?(m|www)\.miyoushe\.com\/[A-Za-z\d._?%&+\-=\/#]*/.exec(url)?.[0];
|
let msg = /(?:https?:\/\/)?(m|www)\.miyoushe\.com\/[A-Za-z\d._?%&+\-=\/#]*/.exec(url)?.[0];
|
||||||
const id = /\/(\d+)$/.exec(msg)?.[0].replace("\/", "");
|
const id = /\/(\d+)$/.exec(msg)?.[0].replace("\/", "");
|
||||||
@ -2169,6 +2230,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 微视
|
// 微视
|
||||||
async weishi(e) {
|
async weishi(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.weishi))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.weishi } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let url = e.msg;
|
let url = e.msg;
|
||||||
const urlRegex = /https?:\/\/video\.weishi\.qq\.com\/\S+/g;
|
const urlRegex = /https?:\/\/video\.weishi\.qq\.com\/\S+/g;
|
||||||
// 执行匹配
|
// 执行匹配
|
||||||
@ -2216,6 +2282,11 @@ export class tools extends plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async zuiyou(e) {
|
async zuiyou(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.zuiyou))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.zuiyou } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// #最右#分享一条有趣的内容给你,不好看算我输。请戳链接>>https://share.xiaochuankeji.cn/hybrid/share/post?pid=365367131&zy_to=applink&share_count=1&m=dc114ccc8e55492642f6a702b510c1f6&d=9e18ca2dace030af656baea96321e0ea353fe5c46097a7f3962b93f995641e962796dd5faa231feea5531ac65547045f&app=zuiyou&recommend=r0&name=n0&title_type=t0
|
// #最右#分享一条有趣的内容给你,不好看算我输。请戳链接>>https://share.xiaochuankeji.cn/hybrid/share/post?pid=365367131&zy_to=applink&share_count=1&m=dc114ccc8e55492642f6a702b510c1f6&d=9e18ca2dace030af656baea96321e0ea353fe5c46097a7f3962b93f995641e962796dd5faa231feea5531ac65547045f&app=zuiyou&recommend=r0&name=n0&title_type=t0
|
||||||
let msg = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim();
|
let msg = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim();
|
||||||
const url = /(?:https?:\/\/)?(share|share.xiaochuankeji)\.cn\/[A-Za-z\d._?%&+\-=\/#]*/.exec(msg)[0];
|
const url = /(?:https?:\/\/)?(share|share.xiaochuankeji)\.cn\/[A-Za-z\d._?%&+\-=\/#]*/.exec(msg)[0];
|
||||||
@ -2279,6 +2350,11 @@ export class tools extends plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async freyr(e) {
|
async freyr(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.freyr))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.freyr } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// https://music.apple.com/cn/album/hectopascal-from-yagate-kimi-ni-naru-piano-arrangement/1468323115?i=1468323724
|
// https://music.apple.com/cn/album/hectopascal-from-yagate-kimi-ni-naru-piano-arrangement/1468323115?i=1468323724
|
||||||
// 过滤参数
|
// 过滤参数
|
||||||
const message = e.msg.replace("&ls", "");
|
const message = e.msg.replace("&ls", "");
|
||||||
@ -2415,6 +2491,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// q q m u s i c 解析
|
// q q m u s i c 解析
|
||||||
async qqMusic(e) {
|
async qqMusic(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.qqMusic))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.qqMusic } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// case1: Taylor Swift/Bleachers《Anti-Hero (Feat. Bleachers) (Explicit)》 https://c6.y.qq.com/base/fcgi-bin/u?__=lg19lFgQerbo @QQ音乐
|
// case1: Taylor Swift/Bleachers《Anti-Hero (Feat. Bleachers) (Explicit)》 https://c6.y.qq.com/base/fcgi-bin/u?__=lg19lFgQerbo @QQ音乐
|
||||||
/** case 2:
|
/** case 2:
|
||||||
* {"app":"com.tencent.structmsg","config":{"ctime":1722497864,"forward":1,"token":"987908ab4a1c566d3645ef0ca52a162a","type":"normal"},"extra":{"app_type":1,"appid":100497308,"uin":542716863},"meta":{"news":{"action":"","android_pkg_name":"","app_type":1,"appid":100497308,"ctime":1722497864,"desc":"Taylor Swift/Bleachers","jumpUrl":"https://i.y.qq.com/v8/playsong.html?hosteuin=7KvA7i6sNeCi&sharefrom=gedan&from_id=1674373010&from_idtype=10014&from_name=(7rpl)&songid=382775503&songmid=&type=0&platform=1&appsongtype=1&_wv=1&source=qq&appshare=iphone&media_mid=000dKYJS3KCzpu&ADTAG=qfshare","preview":"https://pic.ugcimg.cn/1070bf5a6962b75263eee1404953c9b2/jpg1","source_icon":"https://p.qpic.cn/qqconnect/0/app_100497308_1626060999/100?max-age=2592000&t=0","source_url":"","tag":"QQ音乐","title":"Anti-Hero (Feat. Bleachers) (E…","uin":542716863}},"prompt":"[分享]Anti-Hero (Feat. Bleachers) (E…","ver":"0.0.0.1","view":"news"}
|
* {"app":"com.tencent.structmsg","config":{"ctime":1722497864,"forward":1,"token":"987908ab4a1c566d3645ef0ca52a162a","type":"normal"},"extra":{"app_type":1,"appid":100497308,"uin":542716863},"meta":{"news":{"action":"","android_pkg_name":"","app_type":1,"appid":100497308,"ctime":1722497864,"desc":"Taylor Swift/Bleachers","jumpUrl":"https://i.y.qq.com/v8/playsong.html?hosteuin=7KvA7i6sNeCi&sharefrom=gedan&from_id=1674373010&from_idtype=10014&from_name=(7rpl)&songid=382775503&songmid=&type=0&platform=1&appsongtype=1&_wv=1&source=qq&appshare=iphone&media_mid=000dKYJS3KCzpu&ADTAG=qfshare","preview":"https://pic.ugcimg.cn/1070bf5a6962b75263eee1404953c9b2/jpg1","source_icon":"https://p.qpic.cn/qqconnect/0/app_100497308_1626060999/100?max-age=2592000&t=0","source_url":"","tag":"QQ音乐","title":"Anti-Hero (Feat. Bleachers) (E…","uin":542716863}},"prompt":"[分享]Anti-Hero (Feat. Bleachers) (E…","ver":"0.0.0.1","view":"news"}
|
||||||
@ -2461,6 +2542,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 汽水音乐
|
// 汽水音乐
|
||||||
async qishuiMusic(e) {
|
async qishuiMusic(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.qishuiMusic))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.qishuiMusic } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const normalRegex = /^(.*?)\s*https?:\/\//;
|
const normalRegex = /^(.*?)\s*https?:\/\//;
|
||||||
const musicInfo = normalRegex.exec(e.msg)?.[1].trim().replace("@汽水音乐", "");
|
const musicInfo = normalRegex.exec(e.msg)?.[1].trim().replace("@汽水音乐", "");
|
||||||
logger.info(`[R插件][qishuiMusic] 识别音乐为:${ musicInfo }`);
|
logger.info(`[R插件][qishuiMusic] 识别音乐为:${ musicInfo }`);
|
||||||
@ -2483,6 +2569,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 小飞机下载
|
// 小飞机下载
|
||||||
async aircraft(e) {
|
async aircraft(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.aircraft))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.aircraft } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (!(await this.isTrustUser(e.user_id))) {
|
if (!(await this.isTrustUser(e.user_id))) {
|
||||||
e.reply("你没有权限使用此命令");
|
e.reply("你没有权限使用此命令");
|
||||||
return;
|
return;
|
||||||
@ -2539,6 +2630,11 @@ export class tools extends plugin {
|
|||||||
|
|
||||||
// 贴吧
|
// 贴吧
|
||||||
async tieba(e) {
|
async tieba(e) {
|
||||||
|
// 切面判断是否需要解析
|
||||||
|
if (!(await this.isEnableResolve(RESOLVE_CONTROLLER_NAME_ENUM.tieba))) {
|
||||||
|
logger.info(`[R插件][全局解析控制] ${ RESOLVE_CONTROLLER_NAME_ENUM.tieba } 已拦截`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// 提取链接和ID
|
// 提取链接和ID
|
||||||
const msg = /https:\/\/tieba\.baidu\.com\/p\/[A-Za-z0-9]+/.exec(e.msg)?.[0];
|
const msg = /https:\/\/tieba\.baidu\.com\/p\/[A-Za-z0-9]+/.exec(e.msg)?.[0];
|
||||||
const id = /\/p\/([A-Za-z0-9]+)/.exec(msg)?.[1];
|
const id = /\/p\/([A-Za-z0-9]+)/.exec(msg)?.[1];
|
||||||
@ -3022,6 +3118,26 @@ export class tools extends plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否启用解析
|
||||||
|
* @param resolveName
|
||||||
|
* @returns {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async isEnableResolve(resolveName) {
|
||||||
|
const controller = await redisExistAndGetKey(REDIS_YUNZAI_RESOLVE_CONTROLLER);
|
||||||
|
// 如果不存在说明用户没有启动过webui,那么直接放行
|
||||||
|
if (controller == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const foundItem = controller.find(item => item.label === resolveName);
|
||||||
|
// 未知解析,可能是写错,放行
|
||||||
|
if (!foundItem) {
|
||||||
|
logger.warn(`[R插件][启用解析] 未知解析,可能存在写错`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return foundItem.value === 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断是否是海外服务器
|
* 判断是否是海外服务器
|
||||||
* @return {Promise<Boolean>}
|
* @return {Promise<Boolean>}
|
||||||
|
23
constants/resolve.js
Normal file
23
constants/resolve.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
export const REDIS_YUNZAI_RESOLVE_CONTROLLER = "Yz:rconsole:resolve:controller"
|
||||||
|
|
||||||
|
export const RESOLVE_CONTROLLER_NAME_ENUM = {
|
||||||
|
"douyin": "抖音",
|
||||||
|
"bili": "哔哩哔哩",
|
||||||
|
"tiktok": "TikTok",
|
||||||
|
"twitter_x": "Twitter",
|
||||||
|
"acfun": "Acfun",
|
||||||
|
"xhs": "小红书",
|
||||||
|
"bodianMusic": "波点",
|
||||||
|
"general": "通用(包含快手等)",
|
||||||
|
"sy2b": "YouTube",
|
||||||
|
"miyoushe": "米游社",
|
||||||
|
"netease": "网易云音乐",
|
||||||
|
"weibo": "微博",
|
||||||
|
"weishi": "微视",
|
||||||
|
"zuiyou": "最右",
|
||||||
|
"freyr": "AM+Spotify",
|
||||||
|
"qqMusic": "扣扣音乐",
|
||||||
|
"qishuiMusic": "汽水音乐",
|
||||||
|
"aircraft": "小飞机",
|
||||||
|
"tieba": "贴吧",
|
||||||
|
}
|
49
server/app/r/api/resolveControl/route.js
Normal file
49
server/app/r/api/resolveControl/route.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { REDIS_RESOLVE_CONTROLLER } from "../../../../constants/redis.js";
|
||||||
|
import { GLOBAL_RESOLE_CONTROLLER } from "../../../../constants/resolve.js";
|
||||||
|
import { redis } from "../../../../utils/redis.js";
|
||||||
|
|
||||||
|
export async function GET(req, res) {
|
||||||
|
let resolveList = await redis.get(REDIS_RESOLVE_CONTROLLER);
|
||||||
|
if (resolveList == null) {
|
||||||
|
// Redis中不存在就初始化进去
|
||||||
|
await redis.set(REDIS_RESOLVE_CONTROLLER, JSON.stringify(GLOBAL_RESOLE_CONTROLLER));
|
||||||
|
return new Response(JSON.stringify(GLOBAL_RESOLE_CONTROLLER), {
|
||||||
|
status: 200,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(resolveList, {
|
||||||
|
status: 200,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(req) {
|
||||||
|
try {
|
||||||
|
const data = await req.json();
|
||||||
|
const { selectedTags } = data;
|
||||||
|
|
||||||
|
// 获取所有可能的标签
|
||||||
|
const allTags = GLOBAL_RESOLE_CONTROLLER.map(item => item.label);
|
||||||
|
|
||||||
|
// 更新控制器状态
|
||||||
|
const updatedController = GLOBAL_RESOLE_CONTROLLER.map(item => ({
|
||||||
|
...item,
|
||||||
|
value: selectedTags.includes(item.label) ? 1 : 0
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 保存到Redis
|
||||||
|
await redis.set(REDIS_RESOLVE_CONTROLLER, JSON.stringify(updatedController));
|
||||||
|
|
||||||
|
return new Response(JSON.stringify({ success: true }), {
|
||||||
|
status: 200,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return new Response(JSON.stringify({ success: false, error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ import { exec } from 'child_process';
|
|||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import { REDIS_UPDATE_PATH, REDIS_UPDATE_STATUS } from "../../../../constants/redis.js";
|
||||||
import { redis } from "../../../../utils/redis.js";
|
import { redis } from "../../../../utils/redis.js";
|
||||||
|
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
@ -20,7 +21,7 @@ function handleGitError(error, stderr) {
|
|||||||
if (error.message.includes('Timed out')) {
|
if (error.message.includes('Timed out')) {
|
||||||
return '连接超时,请检查网络后重试';
|
return '连接超时,请检查网络后重试';
|
||||||
}
|
}
|
||||||
if (error.message.includes('Could not resolve host')) {
|
if (error.message.includes('Could not resolveControl host')) {
|
||||||
return '无法解析主机地址,请检查网络';
|
return '无法解析主机地址,请检查网络';
|
||||||
}
|
}
|
||||||
if (error.message.includes('Permission denied')) {
|
if (error.message.includes('Permission denied')) {
|
||||||
@ -60,8 +61,8 @@ async function cleanupUpdate(tempDir) {
|
|||||||
// 清理临时文件
|
// 清理临时文件
|
||||||
await fs.rm(tempDir, { recursive: true, force: true });
|
await fs.rm(tempDir, { recursive: true, force: true });
|
||||||
// 清理Redis中的更新状态
|
// 清理Redis中的更新状态
|
||||||
await redis.del('rconsole:update:status');
|
await redis.del(REDIS_UPDATE_STATUS);
|
||||||
await redis.del('rconsole:update:paths');
|
await redis.del(REDIS_UPDATE_PATH);
|
||||||
console.log('清理完成');
|
console.log('清理完成');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('清理失败:', error);
|
console.error('清理失败:', error);
|
||||||
@ -77,7 +78,7 @@ export async function GET(req) {
|
|||||||
|
|
||||||
// 如果是检查请求
|
// 如果是检查请求
|
||||||
if (isCheck) {
|
if (isCheck) {
|
||||||
const updateStatus = await redis.get('rconsole:update:status');
|
const updateStatus = await redis.get(REDIS_UPDATE_STATUS);
|
||||||
return new Response(JSON.stringify({
|
return new Response(JSON.stringify({
|
||||||
needsRestore: updateStatus === 'restoring'
|
needsRestore: updateStatus === 'restoring'
|
||||||
}), {
|
}), {
|
||||||
@ -87,8 +88,8 @@ export async function GET(req) {
|
|||||||
|
|
||||||
// 如果是恢复请求
|
// 如果是恢复请求
|
||||||
if (isRestore) {
|
if (isRestore) {
|
||||||
const updateStatus = await redis.get('rconsole:update:status');
|
const updateStatus = await redis.get(REDIS_UPDATE_STATUS);
|
||||||
const paths = JSON.parse(await redis.get('rconsole:update:paths') || '{}');
|
const paths = JSON.parse(await redis.get(REDIS_UPDATE_PATH) || '{}');
|
||||||
|
|
||||||
if (updateStatus === 'restoring' && paths.tempDir && paths.configDir) {
|
if (updateStatus === 'restoring' && paths.tempDir && paths.configDir) {
|
||||||
try {
|
try {
|
||||||
@ -123,10 +124,10 @@ export async function GET(req) {
|
|||||||
const configDir = path.join(projectRoot, 'config');
|
const configDir = path.join(projectRoot, 'config');
|
||||||
|
|
||||||
// 检查是否有未完成的更新
|
// 检查是否有未完成的更新
|
||||||
const updateStatus = await redis.get('rconsole:update:status');
|
const updateStatus = await redis.get(REDIS_UPDATE_STATUS);
|
||||||
if (updateStatus === 'restoring') {
|
if (updateStatus === 'restoring') {
|
||||||
// 如果有未完成的更新,尝试恢复
|
// 如果有未完成的更新,尝试恢复
|
||||||
const paths = JSON.parse(await redis.get('rconsole:update:paths') || '{}');
|
const paths = JSON.parse(await redis.get(REDIS_UPDATE_PATH) || '{}');
|
||||||
if (paths.tempDir && paths.configDir) {
|
if (paths.tempDir && paths.configDir) {
|
||||||
try {
|
try {
|
||||||
await copyConfig(paths.tempDir, paths.configDir);
|
await copyConfig(paths.tempDir, paths.configDir);
|
||||||
@ -140,11 +141,11 @@ export async function GET(req) {
|
|||||||
console.log('开始新的更新流程');
|
console.log('开始新的更新流程');
|
||||||
|
|
||||||
// 保存路径信息到Redis
|
// 保存路径信息到Redis
|
||||||
await redis.set('rconsole:update:paths', JSON.stringify({
|
await redis.set(REDIS_UPDATE_PATH, JSON.stringify({
|
||||||
tempDir,
|
tempDir,
|
||||||
configDir
|
configDir
|
||||||
}));
|
}));
|
||||||
await redis.set('rconsole:update:status', 'started');
|
await redis.set(REDIS_UPDATE_STATUS, 'started');
|
||||||
|
|
||||||
// 确保临时目录存在
|
// 确保临时目录存在
|
||||||
await ensureDirectory(tempDir);
|
await ensureDirectory(tempDir);
|
||||||
@ -156,7 +157,7 @@ export async function GET(req) {
|
|||||||
await copyConfig(configDir, tempDir);
|
await copyConfig(configDir, tempDir);
|
||||||
configBackedUp = true;
|
configBackedUp = true;
|
||||||
console.log('配置文件备份成功');
|
console.log('配置文件备份成功');
|
||||||
await redis.set('rconsole:update:status', 'backed_up');
|
await redis.set(REDIS_UPDATE_STATUS, 'backed_up');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('无配置文件需要备份或备份失败:', error.message);
|
console.log('无配置文件需要备份或备份失败:', error.message);
|
||||||
}
|
}
|
||||||
@ -169,7 +170,7 @@ export async function GET(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 标记状态为需要恢复
|
// 标记状态为需要恢复
|
||||||
await redis.set('rconsole:update:status', 'restoring');
|
await redis.set(REDIS_UPDATE_STATUS, 'restoring');
|
||||||
|
|
||||||
console.log('执行git pull...');
|
console.log('执行git pull...');
|
||||||
const { stdout } = await execAsync(`git -C "${projectRoot}" pull --no-rebase`);
|
const { stdout } = await execAsync(`git -C "${projectRoot}" pull --no-rebase`);
|
||||||
@ -225,7 +226,7 @@ export async function GET(req) {
|
|||||||
console.error('更新过程出错:', error);
|
console.error('更新过程出错:', error);
|
||||||
|
|
||||||
// 确保清理所有临时状态
|
// 确保清理所有临时状态
|
||||||
const paths = JSON.parse(await redis.get('rconsole:update:paths') || '{}');
|
const paths = JSON.parse(await redis.get(REDIS_UPDATE_PATH) || '{}');
|
||||||
if (paths.tempDir) {
|
if (paths.tempDir) {
|
||||||
await cleanupUpdate(paths.tempDir);
|
await cleanupUpdate(paths.tempDir);
|
||||||
}
|
}
|
||||||
@ -237,4 +238,4 @@ export async function GET(req) {
|
|||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
server/components/TagSelector.jsx
Normal file
65
server/components/TagSelector.jsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
const TagSelector = ({ options = [], initialTags = [], onChange }) => {
|
||||||
|
const [selectedTags, setSelectedTags] = useState(initialTags);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedTags(initialTags);
|
||||||
|
}, [initialTags]);
|
||||||
|
|
||||||
|
const addTag = (tag) => {
|
||||||
|
if (!selectedTags.includes(tag)) {
|
||||||
|
const updatedTags = [...selectedTags, tag];
|
||||||
|
setSelectedTags(updatedTags);
|
||||||
|
if (onChange) onChange(updatedTags);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeTag = (tag) => {
|
||||||
|
const updatedTags = selectedTags.filter((t) => t !== tag);
|
||||||
|
setSelectedTags(updatedTags);
|
||||||
|
if (onChange) onChange(updatedTags);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||||
|
<div className="flex flex-wrap gap-2 mb-4 border p-2 rounded">
|
||||||
|
{selectedTags.length > 0 ? (
|
||||||
|
selectedTags.map((tag, index) => (
|
||||||
|
<span
|
||||||
|
key={index}
|
||||||
|
className="badge badge-secondary gap-2 cursor-pointer"
|
||||||
|
onClick={() => removeTag(tag)}
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</span>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-500">暂无标签,请选择一个选项。</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<select
|
||||||
|
className="select select-bordered w-full"
|
||||||
|
onChange={(e) => {
|
||||||
|
if (e.target.value) {
|
||||||
|
addTag(e.target.value);
|
||||||
|
e.target.value = "";
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<option value="" disabled>
|
||||||
|
选择一个选项
|
||||||
|
</option>
|
||||||
|
{options.filter(option => !selectedTags.includes(option)).map((option, index) => (
|
||||||
|
<option key={index} value={option}>
|
||||||
|
{option}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TagSelector;
|
@ -1,8 +1,8 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
|
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
|
||||||
|
import { ConfigInput, ConfigSelect, ConfigToggle } from '../common/ConfigItem';
|
||||||
|
import TagSelector from "../TagSelector.jsx";
|
||||||
import Toast from "../toast.jsx";
|
import Toast from "../toast.jsx";
|
||||||
import { ConfigToggle, ConfigInput, ConfigSelect } from '../common/ConfigItem';
|
|
||||||
import { AI_MODEL_LIST } from "../../../constants/constant.js";
|
|
||||||
|
|
||||||
// 定义配置项
|
// 定义配置项
|
||||||
const GENERIC_CONFIG = {
|
const GENERIC_CONFIG = {
|
||||||
@ -146,6 +146,8 @@ const DEFAULT_CONFIG = Object.values(GENERIC_CONFIG).reduce((acc, group) => {
|
|||||||
export default function Generic() {
|
export default function Generic() {
|
||||||
const [config, setConfig] = useState(DEFAULT_CONFIG);
|
const [config, setConfig] = useState(DEFAULT_CONFIG);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [resolveOptions, setResolveOptions] = useState([]);
|
||||||
|
const [selectedResolveTags, setSelectedResolveTags] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadConfig = async () => {
|
const loadConfig = async () => {
|
||||||
@ -161,6 +163,25 @@ export default function Generic() {
|
|||||||
loadConfig();
|
loadConfig();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 获取解析控制器配置
|
||||||
|
const fetchResolveControl = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/r/api/resolveControl');
|
||||||
|
const data = await response.json();
|
||||||
|
const enabledTags = data
|
||||||
|
.filter(item => item.value === 1)
|
||||||
|
.map(item => item.label);
|
||||||
|
setSelectedResolveTags(enabledTags);
|
||||||
|
setResolveOptions(data.map(item => item.label));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取解析控制器配置失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchResolveControl();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
@ -182,6 +203,24 @@ export default function Generic() {
|
|||||||
setConfig(prev => ({ ...prev, [key]: value }));
|
setConfig(prev => ({ ...prev, [key]: value }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleResolveTagsChange = async (tags) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/r/api/resolveControl', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ selectedTags: tags }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
setSelectedResolveTags(tags);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新解析控制器配置失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 渲染输入框组
|
// 渲染输入框组
|
||||||
const renderInputGroup = (inputs, title) => (
|
const renderInputGroup = (inputs, title) => (
|
||||||
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||||
@ -218,6 +257,14 @@ export default function Generic() {
|
|||||||
{/* 基础配置 */}
|
{/* 基础配置 */}
|
||||||
{renderInputGroup(GENERIC_CONFIG.basicInputs)}
|
{renderInputGroup(GENERIC_CONFIG.basicInputs)}
|
||||||
|
|
||||||
|
{/* 解析控制 */}
|
||||||
|
<h4 className="font-semibold mt-6 mb-4">全局解析控制</h4>
|
||||||
|
<TagSelector
|
||||||
|
options={resolveOptions}
|
||||||
|
initialTags={selectedResolveTags}
|
||||||
|
onChange={handleResolveTagsChange}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* 代理配置 */}
|
{/* 代理配置 */}
|
||||||
<h4 className="font-semibold mt-6 mb-4">代理设置</h4>
|
<h4 className="font-semibold mt-6 mb-4">代理设置</h4>
|
||||||
{renderInputGroup(GENERIC_CONFIG.proxyInputs)}
|
{renderInputGroup(GENERIC_CONFIG.proxyInputs)}
|
||||||
|
@ -80,7 +80,7 @@ export function BotConfig() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button
|
<button
|
||||||
className={`btn btn-primary ${updating ? 'loading' : ''}`}
|
className={`btn btn-ghost ${updating ? 'loading' : ''}`}
|
||||||
onClick={() => handleUpdate(false)}
|
onClick={() => handleUpdate(false)}
|
||||||
disabled={updating}>
|
disabled={updating}>
|
||||||
普通更新
|
普通更新
|
||||||
|
5
server/constants/redis.js
Normal file
5
server/constants/redis.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export const REDIS_UPDATE_STATUS = "Yz:rconsole:update:status"
|
||||||
|
|
||||||
|
export const REDIS_UPDATE_PATH = "Yz:rconsole:update:paths"
|
||||||
|
|
||||||
|
export const REDIS_RESOLVE_CONTROLLER = "Yz:rconsole:resolve:controller"
|
78
server/constants/resolve.js
Normal file
78
server/constants/resolve.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
export const GLOBAL_RESOLE_CONTROLLER = [
|
||||||
|
{
|
||||||
|
label: "哔哩哔哩",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "抖音",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "TikTok",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "YouTube",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Acfun",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "小红书",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "波点",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "网易云音乐",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "通用(包含快手等)",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Twitter",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "米游社",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "微博",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "微视",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "zuiyou",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "AM+Spotify",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "扣扣音乐",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "汽水音乐",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "小飞机",
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "贴吧",
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
@ -116,7 +116,7 @@ async function downloadM3u8Videos(m3u8FullUrls, outputFolderName) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
/** 写入下载链接列表文件 */
|
/** 写入下载链接列表文件 */
|
||||||
// fs.writeFileSync(path.resolve(outPath, "urls.txt"), str下载参数文件);
|
// fs.writeFileSync(path.resolveControl(outPath, "urls.txt"), str下载参数文件);
|
||||||
return Promise.all(strDownloadParamFiles);
|
return Promise.all(strDownloadParamFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user