This commit is contained in:
Jerry 2025-09-10 21:54:01 +08:00
parent 42e02fc381
commit b523fafdeb
15 changed files with 2100 additions and 4541 deletions

2
.gitignore vendored
View File

@ -7,7 +7,6 @@ node_modules/
*.log
.DS_Store
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
@ -20,7 +19,6 @@ package-lock.json
pnpm-lock.yaml
yarn.lock
.prettierrc.json
.vitepress
bun.lockb
.next
CLAUDE.md

7
.prettierrc Normal file
View File

@ -0,0 +1,7 @@
{
"singleQuote": true,
"semi": true,
"printWidth": 100,
"tabWidth": 2,
"trailingComma": "es5"
}

1371
apps/RCtools.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3,96 +3,37 @@
*
* @type {{: string, : string, : string, : string}}
*/
export const transMap = { : "zh", : "jp", : "wyw", : "en", : "ru", : "kr" };
export const transMap = { : 'zh', : 'jp', : 'wyw', : 'en', : 'ru', : 'kr' };
/**
* 用于腾讯交互式翻译的常量控制
*
* @type {{: string, : string, : string, : string, : string}}
*/
export const tencentTransMap = { : "zh", : "ja", : "ko", : "en", : "ru" };
/**
* 用于腾讯交互式翻译的常量控制
*
* @type {{: string, : string, : string, : string, : string}}
*/
export const googleTransMap = { : "zh-CN", : "jp", : "ko", : "en", : "ru" };
/**
* 以下为抖音/TikTok类型代码
*
* @type {{"0": string, "55": string, "2": string, "68": string, "58": string, "4": string, "61": string, "51": string, "150": string}}
*/
export const douyinTypeMap = {
2: "image",
4: "video",
68: "image",
0: "video",
51: "video",
55: "video",
58: "video",
61: "video",
150: "image",
};
export const tencentTransMap = { : 'zh', : 'ja', : 'ko', : 'en', : 'ru' };
/**
* 固定值 1w目前用于哔哩哔哩的数值渲染
* @type {number}
*/
export const TEN_THOUSAND = 10000;
/**
* #cat 指令的限制
* @type {number}
*/
export const CAT_LIMIT = 10;
/**
* 公共的 User-Agent
* @type {string}
*/
export const COMMON_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";
/**
* 无水印的头请求
* @type {{cookie: string, "User-Agent": string, accept: string}}
*/
export const XHS_NO_WATERMARK_HEADER = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'cookie': '',
'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 COMMON_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';
/**
* 分割线
* @type {string}
*/
export const DIVIDING_LINE = "\n━━━{}━━━"
export const DIVIDING_LINE = '\n━━━{}━━━';
/**
* 保存判断机子是否是海外服务器的key
* @type {string}
*/
export const REDIS_YUNZAI_ISOVERSEA = "Yz:rconsole:tools:oversea";
/**
* 缓存音乐搜索列表
* @type {string}
*/
export const REDIS_YUNZAI_SONGINFO = "Yz:rconsole:tools:songinfo";
/**
* 缓存网易云云盘列表
* @type {string}
*/
export const REDIS_YUNZAI_CLOUDSONGLIST = "Yz:rconsole:tools:cloudsonglist";
/**
* 某些功能的解析白名单
* @type {string}
*/
export const REDIS_YUNZAI_WHITELIST = "Yz:rconsole:tools:whitelist";
export const TWITTER_BEARER_TOKEN = "";
export const REDIS_YUNZAI_ISOVERSEA = 'Yz:rconsole:tools:oversea';
/**
* 哔哩哔哩简介默认长度限制
@ -100,53 +41,11 @@ export const TWITTER_BEARER_TOKEN = "";
*/
export const BILI_DEFAULT_INTRO_LEN_LIMIT = 50;
/**
* 总结的prompt
* @type {string}
*/
export const SUMMARY_PROMPT = `# Role: Web Content Summarization Assistant
## Profile
- author: R-plugin
- version: 1.0
- language: 中文
- description: 一个专门用于网页内容摘要的AI助手能够提取关键点总结文章并提供复杂主题的简洁概览
## Skills
1. 精通自然语言理解和摘要技术
2. 能够从各种网页内容格式文章博客报告中提取关键信息
3. 能够总结短篇和长篇内容
4. 适应不同的写作风格和语调
## Rules
1. 确保摘要捕捉到网页的主要思想和关键点
2. 摘要应简洁清晰准确避免不必要的细节
3. 根据原始内容的复杂性和长度调整摘要的长度和细节
4. 保持原始内容的上下文和意图不添加个人解释
## Workflows
1. 分析网页的结构和主要部分
2. 识别并提取内容中的关键点论点或信息
3. 首先生成一个标题格式约束为"标题: {title}"
4. 然后生成一个包含最重要细节的简洁摘要
5. 接下来生成一个"关键段落"标题内容包括你认为文章中一些关键信息点每个关键点前都带有一个表情符号
6. 接下来审查摘要的准确性和完整性不要在摘要审查中包含当前网页的URL
7. 最后输出内容保证为中文
## Init
在第一次对话中请直接输出以下您好我将联合R插件为您提供简洁明了的网页内容`
/**
* 图片翻译 prompt
* @type {string}
*/
export const IMAGE_TRANSLATION_PROMPT = `Begin each of the following with a triangle symbol (▲ U+25B2): First, a brief description of the image to be used as alt text. Do not describe or extract text in the description. Second, the text extracted from the image, with newlines where applicable. Un-obstruct text if it is covered by something, to make it readable. If there is no text in the image, only respond with the description. Do not include any other information. Example: ▲ Lines of code in a text editor.▲ const x = 5; const y = 10; const z = x + y; console.log(z); Finally, answer in Chinese.`
/**
* 帮助文档提示
* @type {string}
*/
export const HELP_DOC = "\n文档https://zhiyu1998.github.io/rconsole-plugin/"
export const HELP_DOC = '\n如果您对功能有任何问题欢迎参阅文档奥~\nhttps://docs.crystelf.top/';
/**
* 总结内容评估器的正则
@ -156,26 +55,32 @@ export const SUMMARY_CONTENT_ESTIMATOR_PATTERNS = [
{ reg: /(?:https?:\/\/)?mp\.weixin\.qq\.com\/[A-Za-z\d._?%&+\-=\/#]*/, name: '微信文章' },
{ reg: /(?:https?:\/\/)?arxiv.org\/[a-zA-Z\d._?%&+\-=\/#]*/, name: 'ArXiv论文' },
{ reg: /(?:https?:\/\/)?sspai.com\/[a-zA-Z\d._?%&+\-=\/#]*/, name: '少数派' },
{ reg: /(?:https?:\/\/)?www\.bilibili\.com\/read\/[A-Za-z\d._?%&+\-=\/#]*/, name: '哔哩哔哩专栏' },
{
reg: /(?:https?:\/\/)?www\.bilibili\.com\/read\/[A-Za-z\d._?%&+\-=\/#]*/,
name: '哔哩哔哩专栏',
},
{ reg: /(?:https?:\/\/)?www\.zhihu\.com\/question\/[A-Za-z\d._?%&+\-=\/#]*/, name: '知乎问题' },
{ reg: /(?:https?:\/\/)?(www\.)chinadaily.com.cn\/a\/[a-zA-Z0-9\d._?%&+\-=\/#]*/, name: 'ChinaDaily' },
{ reg: /(?:https?:\/\/)?(www\.)?github.com\/[a-zA-Z0-9\d._?%&+\-=\/#]*/, name: 'Github' }
{
reg: /(?:https?:\/\/)?(www\.)chinadaily.com.cn\/a\/[a-zA-Z0-9\d._?%&+\-=\/#]*/,
name: 'ChinaDaily',
},
{ reg: /(?:https?:\/\/)?(www\.)?github.com\/[a-zA-Z0-9\d._?%&+\-=\/#]*/, name: 'Github' },
];
const BILI_CDN_TEMPLATE = "upos-sz-mirror{}.bilivideo.com";
const BILI_CDN_TEMPLATE = 'upos-sz-mirror{}.bilivideo.com';
export const BILI_CDN_SELECT_LIST = Object.freeze([
{ label: '不使用', value: 0, sign: '' },
{ label: '腾讯CDN【推荐】', value: 1, sign: BILI_CDN_TEMPLATE.replace('{}', 'cos') },
{ label: '百度CDN', value: 2, sign: BILI_CDN_TEMPLATE.replace('{}', 'bd') },
{ label: '华为CDN', value: 3, sign: BILI_CDN_TEMPLATE.replace('{}', 'hw') },
{ label: '阿卡迈(海外)', value: 4, sign: BILI_CDN_TEMPLATE.replace('{}', 'akamai') },
{ label: 'HK-CDN', value: 5, sign: BILI_CDN_TEMPLATE.replace('{}', 'aliov') }
{ label: 'HK-CDN', value: 5, sign: BILI_CDN_TEMPLATE.replace('{}', 'aliov') },
]);
export const BILI_DOWNLOAD_METHOD = Object.freeze([
{ label: '稳定(原生)', value: 0 },
{ label: '性能Aria2', value: 1 },
{ label: '轻量axel/wget', value: 2 }
{ label: '轻量axel/wget', value: 2 },
]);
export const BILI_RESOLUTION_LIST = Object.freeze([
@ -206,12 +111,6 @@ export const NETEASECLOUD_QUALITY_LIST = Object.freeze([
{ label: '杜比全景声(不推荐)', value: 'dolby' },
{ label: '超清母带', value: 'jymaster' },
]);
/**
* 消息撤回时间
* @type {number}
*/
export const MESSAGE_RECALL_TIME = 60;
/**
* 针对 Aria2 Alex 的下载检测文件时间
* @type {number}
@ -222,4 +121,4 @@ export const DOWNLOAD_WAIT_DETECT_FILE_TIME = 3000;
* 短链接接口
* @type {string}
*/
export const SHORT_LINKS = "https://smolurl.com/api/links";
export const SHORT_LINKS = 'https://smolurl.com/api/links';

View File

@ -1,23 +1,21 @@
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": "贴吧",
}
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: '贴吧',
};

View File

@ -3,282 +3,149 @@
* 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";
export const BILI_SUMMARY = 'https://api.bilibili.com/x/web-interface/view/conclusion/get';
/**
* 视频流URL
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/videostream_url.md
* @type {string}
*/
export const BILI_PLAY_STREAM = "https://api.bilibili.com/x/player/wbi/playurl?cid={cid}&bvid={bvid}&qn={qn}&fnval=16";
export const BILI_PLAY_STREAM =
'https://api.bilibili.com/x/player/wbi/playurl?cid={cid}&bvid={bvid}&qn={qn}&fnval=16';
/**
* 动态信息
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/dynamic/get_dynamic_detail.md
* @type {string}
*/
export const BILI_DYNAMIC = "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?dynamic_id={}";
export const BILI_DYNAMIC =
'https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/get_dynamic_detail?dynamic_id={}';
/**
* BVID -> CID
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/33bde6f6afcac2ff8c6f7069f08ce84065a6cff6/docs/video/info.md?plain=1#L4352
* @type {string}
*/
export const BILI_BVID_TO_CID = "https://api.bilibili.com/x/player/pagelist?bvid={bvid}&jsonp=jsonp";
export const BILI_BVID_TO_CID =
'https://api.bilibili.com/x/player/pagelist?bvid={bvid}&jsonp=jsonp';
/**
* 视频基本信息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";
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";
/**
* 登录用户状态数双端
* https://github.com/SocialSisterYi/bilibili-API-collect?tab=readme-ov-file
* @type {string}
*/
export const BILI_NAV_STAT = "https://api.bilibili.com/x/web-interface/nav/stat";
export const BILI_NAV = 'https://api.bilibili.com/x/web-interface/nav';
/**
* 扫码登录的二维码生成
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/login/login_action/QR.md
* @type {string}
*/
export const BILI_SCAN_CODE_GENERATE = "https://passport.bilibili.com/x/passport-login/web/qrcode/generate";
export const BILI_SCAN_CODE_GENERATE =
'https://passport.bilibili.com/x/passport-login/web/qrcode/generate';
/**
* 扫码登录检测然后发送令牌数据
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/login/login_action/QR.md
* @type {string}
*/
export const BILI_SCAN_CODE_DETECT = "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key={}";
export const BILI_SCAN_CODE_DETECT =
'https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key={}';
/**
* 直播间信息获取
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/live/info.md
* @type {string}
*/
export const BILI_STREAM_INFO = "https://api.live.bilibili.com/room/v1/Room/get_info";
export const BILI_STREAM_INFO = 'https://api.live.bilibili.com/room/v1/Room/get_info';
/**
* 根据真实直播间号获取直播视频流
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/live/live_stream.md
* @type {string}
*/
export const BILI_STREAM_FLV = "https://api.live.bilibili.com/room/v1/Room/playUrl";
export const BILI_STREAM_FLV = 'https://api.live.bilibili.com/room/v1/Room/playUrl';
/**
* 获取视频在线人数_web端
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/online.md
* @type {string}
*/
export const BILI_ONLINE = "https://api.bilibili.com/x/player/online/total?bvid={0}&cid={1}";
export const BILI_ONLINE = 'https://api.bilibili.com/x/player/online/total?bvid={0}&cid={1}';
/**
* 剧集基本信息
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/bangumi/info.md
* @type {string}
*/
export const BILI_EP_INFO = "https://api.bilibili.com/pgc/view/web/season?ep_id={}";
export const BILI_EP_INFO = 'https://api.bilibili.com/pgc/view/web/season?ep_id={}';
/**
* 剧集基本信息
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/bangumi/info.md
* @type {string}
*/
export const BILI_SSID_INFO = "https://api.bilibili.com/pgc/web/season/section?season_id={}";
export const BILI_SSID_INFO = 'https://api.bilibili.com/pgc/web/season/section?season_id={}';
/**
* 专栏信息
* https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/article/info.md
* @type {string}
*/
export const BILI_ARTICLE_INFO = "https://api.bilibili.com/x/article/viewinfo?id={}";
export const BILI_ARTICLE_INFO = 'https://api.bilibili.com/x/article/viewinfo?id={}';
/**
* 米游社网页端获取文章
* https://github.com/UIGF-org/mihoyo-api-collect/blob/main/hoyolab/article/article.md#%E8%8E%B7%E5%8F%96%E5%AE%8C%E6%95%B4%E6%96%87%E7%AB%A0%E4%BF%A1%E6%81%AF
* @type {string}
*/
export const MIYOUSHE_ARTICLE = "https://bbs-api.miyoushe.com/post/wapi/getPostFull?post_id={}";
/**
* 视频请求链接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";
/**
* DY COMMENT API
* @type {string}
*/
export const DY_COMMENT = "https://www.douyin.com/aweme/v1/web/comment/list/?device_platform=webapp&aid=6383&channel=channel_pc_web&aweme_id={}&cursor=0&count=20&item_type=0&insert_ids=&whale_cut_token=&cut_version=1&rcFT=&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1920&screen_height=1080&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=124.0.0.0&browser_online=true&engine_name=Blink&engine_version=124.0.0.0&os_name=Windows&os_version=10&cpu_core_num=20&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7361743797237679616";
/**
* 今日头条 DY API
* @type {string}
*/
export const DY_TOUTIAO_INFO = "https://aweme.snssdk.com/aweme/v1/play/?video_id={}&ratio=1080p&line=0";
/**
* DY 直播信息
* @type {string}
*/
export const DY_LIVE_INFO = "https://live.douyin.com/webcast/room/web/enter/?device_platform=webapp&aid=6383&channel=channel_pc_web&pc_client_type=1&version_code=190500&version_name=19.5.0&cookie_enabled=true&screen_width=1920&screen_height=1080&browser_language=zh-CN&browser_platform=Win32&browser_name=Firefox&browser_version=124.0&browser_online=true&engine_name=Gecko&engine_version=122.0.0.0&os_name=Windows&os_version=10&cpu_core_num=12&device_memory=8&platform=PC&web_rid={}&room_id_str={}";
/**
* DY 直播信息 二类型
* @type {string}
*/
export const DY_LIVE_INFO_2 = "https://webcast.amemv.com/webcast/room/reflow/info/?type_id=0&live_id=1&sec_user_id=&version_code=99.99.99&app_id=1128&room_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/";
export const MIYOUSHE_ARTICLE = 'https://bbs-api.miyoushe.com/post/wapi/getPostFull?post_id={}';
/**
* 通用解析的请求链接
* @type {string}
*/
export const GENERAL_REQ_LINK = {
link: "http://47.99.158.118/video-crack/v2/parse?content={}",
sign: 1
link: 'http://47.99.158.118/video-crack/v2/parse?content={}',
sign: 1,
};
export const GENERAL_REQ_LINK_2 = {
link: "https://acid.jiuzige.com.cn/web/index/analysis?url={}",
sign: 2
link: 'https://acid.jiuzige.com.cn/web/index/analysis?url={}',
sign: 2,
};
export const GENERAL_REQ_LINK_3 = {
link: "https://picseed.com/v1/parser?auth_key=1E9DC25C-E75F-11EE-A0DD-0A5A298C6C2D&content={}",
sign: 3
link: 'https://picseed.com/v1/parser?auth_key=1E9DC25C-E75F-11EE-A0DD-0A5A298C6C2D&content={}',
sign: 3,
};
/**
* 获取网易云歌曲下载链接
* @type {string}
*/
export const NETEASE_SONG_DOWNLOAD = "https://neteasecloudmusicapi.vercel.app";
/**
* 获取网易云歌曲详情
* 致谢 NeteaseCloudMusicApihttps://gitlab.com/Binaryify/neteasecloudmusicapi
* @type {string}
*/
export const NETEASE_SONG_DETAIL = "https://neteasecloudmusicapi.vercel.app";
/**
* 国内网易云服务如果有大佬可以有闲置的服务器可以到群里赞助
* 致谢 NeteaseCloudMusicApihttps://gitlab.com/Binaryify/neteasecloudmusicapi
* @type {string}
*/
export const NETEASE_API_CN = 'http://118.89.80.17:3000';
/**
* 下载VIP的临时接口
* 备用https://api.lolimi.cn/API/wydg/api.php?msg={}&n=1
* 备用2: http://kilz.top/api/wangyi_music.php?msg={}&n=1
* @type {string}
*/
export const NETEASE_TEMP_API = "https://www.hhlqilongzhu.cn/api/dg_wyymusic.php?gm={}&n=1&type=json";
/**
* 下载VIP的临时接口2
* 备用https://www.hhlqilongzhu.cn/api/dg_qqmusic.php?gm={}&n=1&type=json
* @type {string}
*/
export const QQ_MUSIC_TEMP_API = "https://www.hhlqilongzhu.cn/api/dg_QQmusicflac.php?msg={}&n=1&type=json";
/**
* 下载VIP的临时接口3
* @type {string}
*/
export const QISHUI_MUSIC_TEMP_API = "https://api.cenguigui.cn/api/qishui/?msg={}&limit=1&type=json&n=1";
/**
* 单条微博的接口
* @type {string}
*/
export const WEIBO_SINGLE_INFO = "https://m.weibo.cn/statuses/show?id={}";
/**
* 微视接口
* @type {string}
*/
export const WEISHI_VIDEO_INFO = "https://h5.weishi.qq.com/webapp/json/weishi/WSH5GetPlayPage?feedid={}";
/**
* 番剧搜索链接
* @type {string}
*/
export const ANIME_SERIES_SEARCH_LINK = "https://ylu.cc/so.php?wd=";
export const ANIME_SERIES_SEARCH_LINK = 'https://ylu.cc/so.php?wd=';
/**
* 番剧搜索链接2
* @type {string}
*/
export const ANIME_SERIES_SEARCH_LINK2 = "https://yhdm.one/search?q=";
/**
* HIBI API
* @type {string}
*/
export const HIBI_API_SERVICE = "http://0d00.us.kg:8080/api";
export const ANIME_SERIES_SEARCH_LINK2 = 'https://yhdm.one/search?q=';
/**
* 临时 AI LLM爬虫
* @type {string}
*/
export const PearAPI_CRAWLER = "https://api.pearktrue.cn/api/llmreader/?url={}&type=json";
export const PearAPI_CRAWLER = 'https://api.pearktrue.cn/api/llmreader/?url={}&type=json';
/**
* 临时 AI 总结
* @type {string}
*/
export const PearAPI_DEEPSEEK = "https://api.pearktrue.cn/api/deepseek/";
/**
* TOOL_CALL 爬虫工具
* 用于Kimi模型Tool-Calling的爬虫工具
* 当Kimi模型判断需要从网页获取信息时会调用此工具
*/
export const CRAWL_TOOL = {
type: "function",
function: {
name: "crawl",
description: "根据网站地址URL获取网页内容。",
parameters: {
type: "object",
required: ["url"],
properties: {
url: {
type: "string",
description: "需要获取内容的网站地址URL通常情况下从搜索结果中可以获取网站的地址。"
}
}
}
}
};
export const PearAPI_DEEPSEEK = 'https://api.pearktrue.cn/api/deepseek/';

View File

@ -1,25 +1,31 @@
import _ from "lodash";
import path from "path";
import { BILI_CDN_SELECT_LIST, BILI_DOWNLOAD_METHOD, BILI_RESOLUTION_LIST, YOUTUBE_GRAPHICS_LIST, NETEASECLOUD_QUALITY_LIST } from "./constants/constant.js";
import { RESOLVE_CONTROLLER_NAME_ENUM } from "./constants/resolve.js";
import model from "./model/config.js";
import _ from 'lodash';
import path from 'path';
import {
BILI_CDN_SELECT_LIST,
BILI_DOWNLOAD_METHOD,
BILI_RESOLUTION_LIST,
NETEASECLOUD_QUALITY_LIST,
YOUTUBE_GRAPHICS_LIST,
} from './constants/constant.js';
import { RESOLVE_CONTROLLER_NAME_ENUM } from './constants/resolve.js';
import model from './model/config.js';
const pluginName = `rconsole-plugin`;
const _path = process.cwd() + `/plugins/${pluginName}`;
export function supportGuoba() {
let globalWhitelist = Object.values(RESOLVE_CONTROLLER_NAME_ENUM).map(value => ({ value }));
const globalWhitelistComponent = globalWhitelist.length === 0 ? 'GTags' : 'Select'
let globalWhitelist = Object.values(RESOLVE_CONTROLLER_NAME_ENUM).map((value) => ({ value }));
const globalWhitelistComponent = globalWhitelist.length === 0 ? 'GTags' : 'Select';
return {
pluginInfo: {
name: "R插件",
name: 'R插件',
title: pluginName,
author: "@zhiyu",
authorLink: "https://gitee.com/kyrzy0416",
link: "https://gitee.com/kyrzy0416/rconsole-plugin",
author: '@zhiyu',
authorLink: 'https://gitee.com/kyrzy0416',
link: 'https://gitee.com/kyrzy0416/rconsole-plugin',
isV3: true,
isV2: false,
description: "专门为朋友们写的Yunzai-Bot插件专注图片分享和生活的插件",
description: '专门为朋友们写的Yunzai-Bot插件专注图片分享和生活的插件',
// 是否显示在左侧菜单可选值auto、true、false
// 当为 auto 时,如果配置项大于等于 3 个,则显示在左侧菜单
showInMenu: 'auto',
@ -28,7 +34,7 @@ export function supportGuoba() {
icon: 'mdi:stove',
// 图标颜色,例:#FF0000 或 rgb(255, 0, 0)
iconColor: '#d19f56',
iconPath: path.join(_path, "resources/img/rank/logo.png"),
iconPath: path.join(_path, 'resources/img/rank/logo.png'),
},
configInfo: {
schemas: [
@ -45,435 +51,425 @@ export function supportGuoba() {
},
},
{
field: "globalImageLimit",
label: "解析图片是否合并转发",
field: 'globalImageLimit',
label: '解析图片是否合并转发',
bottomHelpMessage:
"超过配置的数字就会折叠。目前实现了此能的主要有米游社、b站动态专栏、微博、小红书",
component: "InputNumber",
'超过配置的数字就会折叠。目前实现了此能的主要有米游社、b站动态专栏、微博、小红书',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "请输入合并转发最大阈值",
placeholder: '请输入合并转发最大阈值',
},
},
{
field: "tools.proxyAddr",
label: "魔法地址",
bottomHelpMessage: "tiktok/小蓝鸟等要使用魔法时需要填写",
component: "Input",
field: 'tools.proxyAddr',
label: '魔法地址',
bottomHelpMessage: 'tiktok/小蓝鸟等要使用魔法时需要填写',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入魔法地址默认127.0.0.1",
placeholder: '请输入魔法地址默认127.0.0.1',
},
},
{
field: "tools.proxyPort",
label: "魔法端口",
bottomHelpMessage: "tiktok/小蓝鸟等要使用魔法时需要填写",
component: "Input",
field: 'tools.proxyPort',
label: '魔法端口',
bottomHelpMessage: 'tiktok/小蓝鸟等要使用魔法时需要填写',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入端口默认7890",
placeholder: '请输入端口默认7890',
},
},
{
field: "tools.forceOverseasServer",
label: "强制使用海外服务器",
bottomHelpMessage: "设置为开启时Twitter、TikTok等平台将强制不使用代理",
component: "Switch",
field: 'tools.forceOverseasServer',
label: '强制使用海外服务器',
bottomHelpMessage: '设置为开启时Twitter、TikTok等平台将强制不使用代理',
component: 'Switch',
required: false,
},
{
field: "tools.identifyPrefix",
label: "识别前缀",
bottomHelpMessage: "识别前缀,比如你识别哔哩哔哩,那么就有:✅ 识别:哔哩哔哩",
component: "Input",
field: 'tools.identifyPrefix',
label: '识别前缀',
bottomHelpMessage: '识别前缀,比如你识别哔哩哔哩,那么就有:✅ 识别:哔哩哔哩',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入识别前缀",
placeholder: '请输入识别前缀',
},
},
{
field: "tools.deeplApiUrls",
label: "DeeplX API地址集合",
bottomHelpMessage: "可以参考https://github.com/OwO-Network/DeepLX进行搭建也可以使用内置",
component: "Input",
required: false,
componentProps: {
placeholder: "请输入DeeplX API地址集合",
},
},
{
field: "tools.streamDuration",
label: "解析直播时长",
field: 'tools.deeplApiUrls',
label: 'DeeplX API地址集合',
bottomHelpMessage:
"解析直播目前涉及哔哩哔哩、抖音时长单位默认10秒建议时间为10~60不然也没人看",
component: "InputNumber",
'可以参考https://github.com/OwO-Network/DeepLX进行搭建也可以使用内置',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入最大解析直播时长",
placeholder: '请输入DeeplX API地址集合',
},
},
{
field: "tools.streamCompatibility",
label: "直播是否开启兼容模式",
field: 'tools.streamDuration',
label: '解析直播时长',
bottomHelpMessage:
"兼容模式NCQQ不用开其他ICQQ、LLO需要开启",
component: "Switch",
required: false,
},
{
field: "tools.defaultPath",
label: "视频暂存位置",
bottomHelpMessage:
"视频暂存位置(如果你对你系统我的文件非常了解可以修改,不然不建议)",
component: "Input",
'解析直播目前涉及哔哩哔哩、抖音时长单位默认10秒建议时间为10~60不然也没人看',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "请输入视频暂存位置",
placeholder: '请输入最大解析直播时长',
},
},
{
field: "tools.videoSizeLimit",
label: "视频大小限制",
bottomHelpMessage:
"视频大小限制单位MB超过大小则转换成群文件上传",
component: "InputNumber",
field: 'tools.streamCompatibility',
label: '直播是否开启兼容模式',
bottomHelpMessage: '兼容模式NCQQ不用开其他ICQQ、LLO需要开启',
component: 'Switch',
required: false,
},
{
field: 'tools.defaultPath',
label: '视频暂存位置',
bottomHelpMessage: '视频暂存位置(如果你对你系统我的文件非常了解可以修改,不然不建议)',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入视频大小限制",
placeholder: '请输入视频暂存位置',
},
},
{
field: "tools.biliSessData",
label: "哔哩哔哩SESSDATA",
bottomHelpMessage:
"如何获取具体参考我的文档说明https://gitee.com/kyrzy0416/rconsole-plugin#Q&A",
component: "Input",
field: 'tools.videoSizeLimit',
label: '视频大小限制',
bottomHelpMessage: '视频大小限制单位MB超过大小则转换成群文件上传',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "请输入哔哩哔哩SESSDATA",
placeholder: '请输入视频大小限制',
},
},
{
field: "tools.biliDuration",
label: "视频最大时长限制",
field: 'tools.biliSessData',
label: '哔哩哔哩SESSDATA',
bottomHelpMessage:
"超过时长无法解析单位保护服务器性能计算公式8分钟 x 60秒 = 480秒",
component: "InputNumber",
'如何获取具体参考我的文档说明https://gitee.com/kyrzy0416/rconsole-plugin#Q&A',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入哔哩哔哩的视频最大限制时长默认8分钟",
placeholder: '请输入哔哩哔哩SESSDATA',
},
},
{
field: "tools.biliIntroLenLimit",
label: "哔哩哔哩的简介长度限制",
field: 'tools.biliDuration',
label: '视频最大时长限制',
bottomHelpMessage:
"防止简介过长刷屏",
component: "InputNumber",
'超过时长无法解析单位保护服务器性能计算公式8分钟 x 60秒 = 480秒',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "请输入哔哩哔哩的简介长度限制默认50个字符填 0 或者 -1 可以不做任何限制,显示完整简介",
placeholder: '请输入哔哩哔哩的视频最大限制时长默认8分钟',
},
},
{
field: "tools.biliDisplayCover",
label: "是否显示封面",
bottomHelpMessage:
"默认显示,哔哩哔哩是否显示封面",
component: "Switch",
field: 'tools.biliIntroLenLimit',
label: '哔哩哔哩的简介长度限制',
bottomHelpMessage: '防止简介过长刷屏',
component: 'InputNumber',
required: false,
componentProps: {
placeholder:
'请输入哔哩哔哩的简介长度限制默认50个字符填 0 或者 -1 可以不做任何限制,显示完整简介',
},
},
{
field: 'tools.biliDisplayCover',
label: '是否显示封面',
bottomHelpMessage: '默认显示,哔哩哔哩是否显示封面',
component: 'Switch',
required: true,
},
{
field: "tools.biliDisplayInfo",
label: "是否显示相关信息",
field: 'tools.biliDisplayInfo',
label: '是否显示相关信息',
bottomHelpMessage:
"默认显示,哔哩哔哩是否显示相关信息(点赞、硬币、收藏、分享、播放数、弹幕数、评论数)",
component: "Switch",
'默认显示,哔哩哔哩是否显示相关信息(点赞、硬币、收藏、分享、播放数、弹幕数、评论数)',
component: 'Switch',
required: true,
},
{
field: "tools.biliDisplayIntro",
label: "是否显示简介",
bottomHelpMessage:
"默认显示,哔哩哔哩是否显示简介",
component: "Switch",
field: 'tools.biliDisplayIntro',
label: '是否显示简介',
bottomHelpMessage: '默认显示,哔哩哔哩是否显示简介',
component: 'Switch',
required: true,
},
{
field: "tools.biliDisplayOnline",
label: "是否显示在线人数",
bottomHelpMessage:
"默认显示,哔哩哔哩是否显示在线人数",
component: "Switch",
field: 'tools.biliDisplayOnline',
label: '是否显示在线人数',
bottomHelpMessage: '默认显示,哔哩哔哩是否显示在线人数',
component: 'Switch',
required: true,
},
{
field: "tools.biliDisplaySummary",
label: "是否显示总结",
bottomHelpMessage:
"默认不显示,哔哩哔哩是否显示总结",
component: "Switch",
field: 'tools.biliDisplaySummary',
label: '是否显示总结',
bottomHelpMessage: '默认不显示,哔哩哔哩是否显示总结',
component: 'Switch',
required: true,
},
{
field: "tools.biliUseBBDown",
label: "BBDown接管下载",
field: 'tools.biliUseBBDown',
label: 'BBDown接管下载',
bottomHelpMessage:
"【默认不开启,涉及范围只有哔哩哔哩,开启后默认最高画质发送】如果不爱折腾就使用默认下载方式,如果喜欢折腾就开启,开启后下载更强劲,并且一劳永逸!",
component: "Switch",
'【默认不开启,涉及范围只有哔哩哔哩,开启后默认最高画质发送】如果不爱折腾就使用默认下载方式,如果喜欢折腾就开启,开启后下载更强劲,并且一劳永逸!',
component: 'Switch',
required: false,
},
{
field: "tools.biliCDN",
label: "强制使用CDN",
bottomHelpMessage: "BBDown强制使用CDN【只影响开启后的BBDown一定程度可以影响BBDown速度】哔哩哔哩的CDN地址更换如果不需要默认不使用如果选择了其他的CDN将会使用",
component: "Select",
field: 'tools.biliCDN',
label: '强制使用CDN',
bottomHelpMessage:
'BBDown强制使用CDN【只影响开启后的BBDown一定程度可以影响BBDown速度】哔哩哔哩的CDN地址更换如果不需要默认不使用如果选择了其他的CDN将会使用',
component: 'Select',
componentProps: {
options: BILI_CDN_SELECT_LIST,
}
},
},
{
field: "tools.biliDownloadMethod",
label: "bili下载方式",
field: 'tools.biliDownloadMethod',
label: 'bili下载方式',
bottomHelpMessage:
"哔哩哔哩的下载方式默认使用原生稳定的下载方式如果你在乎内存可以使用轻量的wget和axel下载方式如果在乎性能可以使用Aria2下载",
component: "Select",
'哔哩哔哩的下载方式默认使用原生稳定的下载方式如果你在乎内存可以使用轻量的wget和axel下载方式如果在乎性能可以使用Aria2下载',
component: 'Select',
componentProps: {
options: BILI_DOWNLOAD_METHOD,
}
},
},
{
field: "tools.biliResolution",
label: "bili最高分辨率",
field: 'tools.biliResolution',
label: 'bili最高分辨率',
bottomHelpMessage:
"【开不开BBDown都同步】哔哩哔哩的最高分辨率默认为480p可以自行根据服务器进行调整",
component: "Select",
'【开不开BBDown都同步】哔哩哔哩的最高分辨率默认为480p可以自行根据服务器进行调整',
component: 'Select',
componentProps: {
options: BILI_RESOLUTION_LIST,
}
},
},
{
field: "tools.youtubeDuration",
label: "油管最大解析时长",
field: 'tools.youtubeDuration',
label: '油管最大解析时长',
bottomHelpMessage:
"超过时长不解析单位保护魔法的流量计算公式8分钟 x 60秒 = 480秒默认8分钟最好不超过30分钟",
component: "InputNumber",
'超过时长不解析单位保护魔法的流量计算公式8分钟 x 60秒 = 480秒默认8分钟最好不超过30分钟',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "请输入YouTuBe视频最大时长限制",
placeholder: '请输入YouTuBe视频最大时长限制',
},
},
{
field: "tools.youtubeClipTime",
label: "油管截取时长",
field: 'tools.youtubeClipTime',
label: '油管截取时长',
bottomHelpMessage:
"超过时长会截取指定时间单位保护魔法的流量计算公式3分钟 x 60秒 = 180秒默认不开启最好不超过5分钟,0表无限or不开启",
component: "InputNumber",
'超过时长会截取指定时间单位保护魔法的流量计算公式3分钟 x 60秒 = 180秒默认不开启最好不超过5分钟,0表无限or不开启',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "请输入截取时长",
placeholder: '请输入截取时长',
},
},
{
field: "tools.youtubeGraphicsOptions",
label: "油管最高分辨率",
field: 'tools.youtubeGraphicsOptions',
label: '油管最高分辨率',
bottomHelpMessage:
"油管下载的最高分辨率默认720p请根据自己魔法流量和服务器承载能力进行调整",
component: "Select",
'油管下载的最高分辨率默认720p请根据自己魔法流量和服务器承载能力进行调整',
component: 'Select',
componentProps: {
options: YOUTUBE_GRAPHICS_LIST,
}
},
},
{
field: "tools.youtubeCookiePath",
label: "油管Cookie文件路径",
field: 'tools.youtubeCookiePath',
label: '油管Cookie文件路径',
bottomHelpMessage:
"【!重要:这里填写的是路径,例如/path/to/cookies.txt】如果无法解析油管就填写这个Cookie",
component: "Input",
'【!重要:这里填写的是路径,例如/path/to/cookies.txt】如果无法解析油管就填写这个Cookie',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入Youtube Cookie所在的路径例如/path/to/cookies.txt",
placeholder: '请输入Youtube Cookie所在的路径例如/path/to/cookies.txt',
},
},
{
field: "tools.isSendVocal",
label: "网易云开启发送音频",
bottomHelpMessage:
"默认开启,识别音乐之后是否转化群语音发送,关闭将获得一定的性能提升",
component: "Switch",
field: 'tools.isSendVocal',
label: '网易云开启发送音频',
bottomHelpMessage: '默认开启,识别音乐之后是否转化群语音发送,关闭将获得一定的性能提升',
component: 'Switch',
required: false,
},
{
field: "tools.useNeteaseSongRequest",
label: "开启网易云点歌功能",
bottomHelpMessage:
"默认不开启建议搭配自建网易云API使用以获得最佳体验",
component: "Switch",
field: 'tools.useNeteaseSongRequest',
label: '开启网易云点歌功能',
bottomHelpMessage: '默认不开启建议搭配自建网易云API使用以获得最佳体验',
component: 'Switch',
required: false,
},
{
field: "tools.songRequestMaxList",
label: "点歌列表长度",
bottomHelpMessage:
"网易云点歌选择列表长度默认10",
component: "InputNumber",
field: 'tools.songRequestMaxList',
label: '点歌列表长度',
bottomHelpMessage: '网易云点歌选择列表长度默认10',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "填入长度",
placeholder: '填入长度',
},
},
{
field: "tools.useLocalNeteaseAPI",
label: "使用自建网易云API",
field: 'tools.useLocalNeteaseAPI',
label: '使用自建网易云API',
bottomHelpMessage:
"默认不开启有条件可以查看https://gitlab.com/Binaryify/neteasecloudmusicapi进行搭建",
component: "Switch",
'默认不开启有条件可以查看https://gitlab.com/Binaryify/neteasecloudmusicapi进行搭建',
component: 'Switch',
required: false,
},
{
field: "tools.neteaseCloudAPIServer",
label: "自建网易云API地址",
bottomHelpMessage:
"填入自建API地址http://localhost:3000",
component: "Input",
field: 'tools.neteaseCloudAPIServer',
label: '自建网易云API地址',
bottomHelpMessage: '填入自建API地址http://localhost:3000',
component: 'Input',
required: false,
componentProps: {
placeholder: "填入自建API地址",
placeholder: '填入自建API地址',
},
},
{
field: "tools.neteaseCookie",
label: "网易云Cookie",
field: 'tools.neteaseCookie',
label: '网易云Cookie',
bottomHelpMessage:
"可以发送 #RNQ / #rnq 快捷获取 或 者在网易云官网自己获取格式为MUSIC_U=xxx",
component: "Input",
'可以发送 #RNQ / #rnq 快捷获取 或 者在网易云官网自己获取格式为MUSIC_U=xxx',
component: 'Input',
required: false,
componentProps: {
placeholder: "使用vip账号登陆获取更高音质解析",
placeholder: '使用vip账号登陆获取更高音质解析',
},
},
{
field: "tools.neteaseCloudAudioQuality",
label: "网易云解析最高音质",
field: 'tools.neteaseCloudAudioQuality',
label: '网易云解析最高音质',
bottomHelpMessage:
"网易云解析最高音质(目前仅针对自建最新API服务器生效需vip账号ck默认极高杜比全景声由于编码特殊需要设备支持更高请根据登陆的账号和服务器承载能力进行选择)",
component: "Select",
'网易云解析最高音质(目前仅针对自建最新API服务器生效需vip账号ck默认极高杜比全景声由于编码特殊需要设备支持更高请根据登陆的账号和服务器承载能力进行选择)',
component: 'Select',
componentProps: {
options: NETEASECLOUD_QUALITY_LIST,
}
},
},
{
field: "tools.douyinCookie",
label: "抖音的Cookie",
field: 'tools.douyinCookie',
label: '抖音的Cookie',
bottomHelpMessage:
"登陆https://www.douyin.com/ - F12 - 自己替换一下odin_tt=xxx;passport_fe_beating_status=xxx;sid_guard=xxx;uid_tt=xxx;uid_tt_ss=xxx;sid_tt=xxx;sessionid=xxx;sessionid_ss=xxx;sid_ucp_v1=xxx;ssid_ucp_v1=xxx;passport_assist_user=xxx;ttwid=xxx;",
component: "Input",
'登陆https://www.douyin.com/ - F12 - 自己替换一下odin_tt=xxx;passport_fe_beating_status=xxx;sid_guard=xxx;uid_tt=xxx;uid_tt_ss=xxx;sid_tt=xxx;sessionid=xxx;sessionid_ss=xxx;sid_ucp_v1=xxx;ssid_ucp_v1=xxx;passport_assist_user=xxx;ttwid=xxx;',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入抖音的Cookie",
placeholder: '请输入抖音的Cookie',
},
},
{
field: "tools.douyinCompression",
label: "抖音是否使用压缩格式",
component: "Switch",
field: 'tools.douyinCompression',
label: '抖音是否使用压缩格式',
component: 'Switch',
required: false,
},
{
field: "tools.douyinComments",
label: "抖音是否开启评论",
component: "Switch",
field: 'tools.douyinComments',
label: '抖音是否开启评论',
component: 'Switch',
required: false,
},
{
field: "tools.xiaohongshuCookie",
label: "小红书的Cookie",
bottomHelpMessage:
"2024-8-2后反馈必须使用ck不然无法解析",
component: "Input",
field: 'tools.xiaohongshuCookie',
label: '小红书的Cookie',
bottomHelpMessage: '2024-8-2后反馈必须使用ck不然无法解析',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入小红书的Cookie",
placeholder: '请输入小红书的Cookie',
},
},
{
field: "tools.queueConcurrency",
label: "(高级)队列长度",
field: 'tools.queueConcurrency',
label: '(高级)队列长度',
bottomHelpMessage:
"【目前只涉及哔哩哔哩的下载功能】允许队列下载个数根据服务器性能设置可以并发下载的个数如果你的服务器比较强劲就选择4~12较弱就一个一个下载选择1",
component: "InputNumber",
'【目前只涉及哔哩哔哩的下载功能】允许队列下载个数根据服务器性能设置可以并发下载的个数如果你的服务器比较强劲就选择4~12较弱就一个一个下载选择1',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "如果你的服务器比较强劲就写4~12比如4就是可以4个人同时下载较弱就一个一个下载写1",
placeholder:
'如果你的服务器比较强劲就写4~12比如4就是可以4个人同时下载较弱就一个一个下载写1',
},
},
{
field: "tools.videoDownloadConcurrency",
label: "(高级)下载并发个数",
field: 'tools.videoDownloadConcurrency',
label: '(高级)下载并发个数',
bottomHelpMessage:
"【涉及哔哩哔哩、抖音、YouTuBe、tiktok】下载并发个数与【允许多用户下载个数】不同这个功能影响下载速度。默认是1表示不使用使用根据服务器性能进行选择如果不确定是否可以用1即可高性能服务器随意4~12都可以看CPU的实力",
component: "InputNumber",
'【涉及哔哩哔哩、抖音、YouTuBe、tiktok】下载并发个数与【允许多用户下载个数】不同这个功能影响下载速度。默认是1表示不使用使用根据服务器性能进行选择如果不确定是否可以用1即可高性能服务器随意4~12都可以看CPU的实力',
component: 'InputNumber',
required: false,
componentProps: {
placeholder: "不确定用1即可高性能服务器随意4~12都可以看CPU的实力",
placeholder: '不确定用1即可高性能服务器随意4~12都可以看CPU的实力',
},
},
{
field: "tools.aiBaseURL",
label: "AI接口地址",
field: 'tools.aiBaseURL',
label: 'AI接口地址',
bottomHelpMessage:
"支持Kimi、OpenAI、Claude等例如官方的可以填写https://api.moonshot.cn如果是本机可以填写http://localhost:8000",
component: "Input",
'支持Kimi、OpenAI、Claude等例如官方的可以填写https://api.moonshot.cn如果是本机可以填写http://localhost:8000',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入AI接口地址",
placeholder: '请输入AI接口地址',
},
},
{
field: "tools.aiApiKey",
label: "AI的key",
field: 'tools.aiApiKey',
label: 'AI的key',
bottomHelpMessage:
"服务商提供的api key如果是官方的就是sk-....如果是本机的就是ey...推荐使用ey因为sk没有联网功能",
component: "Input",
'服务商提供的api key如果是官方的就是sk-....如果是本机的就是ey...推荐使用ey因为sk没有联网功能',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入AI的key",
placeholder: '请输入AI的key',
},
},
{
field: "tools.aiModel",
label: "AI的模型",
bottomHelpMessage:
"默认使用的是moonshot-v1-8k也可以自定义模型只要能联网就能使用",
component: "Input",
field: 'tools.aiModel',
label: 'AI的模型',
bottomHelpMessage: '默认使用的是moonshot-v1-8k也可以自定义模型只要能联网就能使用',
component: 'Input',
required: false,
componentProps: {
placeholder: "请输入AI的模型例如moonshot-v1-8k使用kimi则不用填写",
placeholder: '请输入AI的模型例如moonshot-v1-8k使用kimi则不用填写',
},
},
}
],
getConfigData() {
const toolsData = {
tools: model.getConfig("tools"),
tools: model.getConfig('RCtools'),
};
return toolsData;
},
setConfigData(data, { Result }) {
let config = {};
let cfg = model.getConfig("tools");
let cfg = model.getConfig('RCtools');
for (let [key, value] of Object.entries(data)) {
// 特殊处理这个,需要全覆盖
if (key === "tools.globalBlackList") {
_.set(cfg, "globalBlackList", value);
if (key === 'tools.globalBlackList') {
_.set(cfg, 'globalBlackList', value);
}
_.set(config, key, value);
}
// 合并配置项
config = _.merge({}, cfg, config.tools);
// 保存
model.saveAllConfig("tools", config);
return Result.ok({}, "保存成功~");
model.saveAllConfig('RCtools', config);
return Result.ok({}, '保存成功~');
},
},
};

View File

@ -1,24 +1,29 @@
import fs from "node:fs";
import path from "path";
import config from "./model/config.js";
import fs from 'node:fs';
import path from 'path';
import config from './model/config.js';
if (!global.segment) {
global.segment = (await import("oicq")).segment
global.segment = (await import('oicq')).segment;
}
// 加载版本号
const versionData = config.getConfig("version");
const versionData = config.getConfig('version');
// 加载名称
const packageJsonPath = path.join('./plugins', 'rconsole-plugin', 'package.json');
const packageJsonPath = path.join('./plugins', 'rc-plugin', 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
const pluginName = packageJson.name;
// 初始化输出
logger.info(logger.yellow(`R插件${versionData[0].version}初始化欢迎加入【R插件和它的朋友们】秋秋群575663150`));
logger.info(
logger.yellow(
`R插件${versionData[0].version}初始化欢迎加入【R插件和它的朋友们】秋秋群575663150`
)
);
const files = fs.readdirSync(`./plugins/${pluginName}/apps`).filter(file => file.endsWith(".js"));
const files = fs.readdirSync(`./plugins/${pluginName}/apps`).filter((file) => file.endsWith('.js'));
let ret = [];
files.forEach(file => {
files.forEach((file) => {
ret.push(import(`./apps/${file}`));
});
@ -26,9 +31,9 @@ ret = await Promise.allSettled(ret);
let apps = {};
for (let i in files) {
let name = files[i].replace(".js", "");
let name = files[i].replace('.js', '');
if (ret[i].status !== "fulfilled") {
if (ret[i].status !== 'fulfilled') {
logger.error(`[rc-plugin] 载入插件错误:${logger.red(name)}`);
logger.error(ret[i].reason);
continue;

View File

@ -1,22 +1,22 @@
import path from 'path';
import fs from "fs";
import fs from 'fs';
export default class Base {
static pluginName = (() => {
const packageJsonPath = path.join('./plugins', 'rconsole-plugin', 'package.json');
const packageJsonPath = path.join('./plugins', 'rc-plugin', 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
return packageJson.name;
})();
constructor(e = {}) {
this.e = e
this.userId = e?.user_id
this.model = Base.pluginName
this._path = process.cwd().replace(/\\/g, '/')
this.e = e;
this.userId = e?.user_id;
this.model = Base.pluginName;
this._path = process.cwd().replace(/\\/g, '/');
}
get prefix() {
return `Yz:${Base.pluginName}:${this.model}:`
return `Yz:${Base.pluginName}:${this.model}:`;
}
/**
@ -30,7 +30,7 @@ export default class Base {
saveId: this.userId,
tplFile: `./plugins/${Base.pluginName}/resources/html/${this.model}/${this.model}.html`,
/** 绝对路径 */
pluResPath: `${this._path}/plugins/${Base.pluginName}/resources/`
}
pluResPath: `${this._path}/plugins/${Base.pluginName}/resources/`,
};
}
}

View File

@ -1,12 +1,15 @@
{
"name": "rconsole-plugin",
"description": "R-Plugin",
"name": "rc-plugin",
"description": "rebuild-ver",
"type": "module",
"dependencies": {
"axios": "^1.3.4",
"form-data": "^4.0.1",
"node-id3": "^0.2.6",
"qrcode": "^1.5.3",
"p-queue": "^8.0.1"
"p-queue": "^8.0.1",
"qrcode": "^1.5.3"
},
"devDependencies": {
"prettier": "^3.6.2"
}
}

View File

@ -1,23 +0,0 @@
export function formatTime(timestamp) {
const totalSeconds = Math.floor(timestamp / 1000); // 转换为秒
const minutes = Math.floor(totalSeconds / 60); // 分钟
const seconds = totalSeconds % 60; // 秒钟
// 补零格式化
const formattedMinutes = String(minutes).padStart(2, '0');
const formattedSeconds = String(seconds).padStart(2, '0');
return `${formattedMinutes}:${formattedSeconds}`;
}
export function toGBorTB(Bytes) {
const GB = 1024 ** 3;
let sizeInGB = Bytes / GB;
let unit = "GB";
if (sizeInGB > 1024) {
sizeInGB /= 1024;
unit = "TB";
}
sizeInGB = sizeInGB % 1 === 0 ? sizeInGB.toString() : sizeInGB.toFixed(2);
return sizeInGB + unit;
}

View File

@ -51,38 +51,3 @@ export async function redisExistAndGetKey(key) {
}
return null;
}
/**
* 在某个 key 的末尾插入一个对象
* @param key
* @param obj
* @returns {Promise<void>}
* @example
* await redisExistAndInsertObject('myKey', { newKey: 'newValue' });
*/
export async function redisExistAndInsertObject(key, obj) {
let objs = await redisExistAndGetKey(key);
if (objs) {
objs = { ...objs, ...obj };
await redisSetKey(key, objs);
} else {
await redisSetKey(key, obj);
}
}
/**
* 更新Redis中某个对象的值
* @param key
* @param updateKey
* @param updateObj
* @returns {Promise<void>}
* @example
* await redisExistAndUpdateObject('myKey', 'updateKey', { foo: 'bar' });
*/
export async function redisExistAndUpdateObject(key, updateKey, updateObj) {
let objs = await redisExistAndGetKey(key);
if (Object.keys(objs).includes(updateKey)) {
objs[updateKey] = updateObj;
await redisSetKey(key, objs);
}
}

View File

@ -55,28 +55,3 @@ export async function saveTDL(url, isOversea, proxyAddr) {
})
})
}
/**
* 上传文件到飞机收藏夹
* @param filePath
* @param isOversea
* @param proxyAddr
* @returns {Promise<void>}
*/
export async function uploadTDL(filePath, isOversea, proxyAddr) {
return new Promise((resolve, reject) => {
const proxyStr = isOversea ? `` : `--proxy ${ proxyAddr }`;
const command = `tdl up -p ${ filePath } ${ proxyStr }`;
exec(command, (error, stdout, stderr) => {
if (error) {
reject(`[R插件][TDL上传]执行出错: ${ error.message }`);
return;
}
if (stderr) {
reject(`[R插件][TDL上传]错误信息: ${ stderr }`);
return;
}
resolve(stdout);
})
})
}

View File

@ -1,4 +1,4 @@
import { exec } from "child_process";
import { exec } from 'child_process';
/**
* 构建梯子参数
@ -7,7 +7,7 @@ import { exec } from "child_process";
* @returns {string|string}
*/
function constructProxyParam(isOversea, proxy) {
return isOversea ? "" : `--proxy ${proxy}`;
return isOversea ? '' : `--proxy ${proxy}`;
}
/**
@ -18,7 +18,7 @@ function constructProxyParam(isOversea, proxy) {
* @returns {string}
*/
function constructCookiePath(url, cookiePath) {
return (cookiePath !== "" && url.includes("youtu")) ? `--cookies ${ cookiePath }` : "";
return cookiePath !== '' && url.includes('youtu') ? `--cookies ${cookiePath}` : '';
}
/**
@ -27,10 +27,9 @@ function constructCookiePath(url, cookiePath) {
* @returns {string}
*/
function constructEncodingParam(url) {
return "--encoding UTF-8"; // 始终为标题获取使用 UTF-8 编码
return '--encoding UTF-8'; // 始终为标题获取使用 UTF-8 编码
}
/**
* 获取时长
* @param url
@ -39,14 +38,16 @@ function constructEncodingParam(url) {
* @param cookiePath
* @returns string
*/
export function ytDlpGetDuration(url, isOversea, proxy, cookiePath = "") {
export function ytDlpGetDuration(url, isOversea, proxy, cookiePath = '') {
return new Promise((resolve, reject) => {
// 构造 cookie 参数
const cookieParam = constructCookiePath(url, cookiePath);
const command = `yt-dlp --get-duration --skip-download ${cookieParam} ${constructProxyParam(isOversea, proxy)} "${url}"`;
exec(command, (error, stdout, stderr) => {
if (error) {
logger.error(`[R插件][yt-dlp审计] Error executing ytDlpGetDuration: ${error}. Stderr: ${stderr}`);
logger.error(
`[R插件][yt-dlp审计] Error executing ytDlpGetDuration: ${error}. Stderr: ${stderr}`
);
reject(error);
} else {
resolve(stdout.trim());
@ -63,7 +64,7 @@ export function ytDlpGetDuration(url, isOversea, proxy, cookiePath = "") {
* @param cookiePath
* @returns string
*/
export function ytDlpGetTilt(url, isOversea, proxy, cookiePath = "") {
export async function ytDlpGetTilt(url, isOversea, proxy, cookiePath = '') {
return new Promise((resolve, reject) => {
// 构造 cookie 参数
const cookieParam = constructCookiePath(url, cookiePath);
@ -72,7 +73,9 @@ export function ytDlpGetTilt(url, isOversea, proxy, cookiePath = "") {
const command = `yt-dlp --get-title --skip-download ${cookieParam} ${constructProxyParam(isOversea, proxy)} "${url}" ${encodingParam}`;
exec(command, (error, stdout, stderr) => {
if (error) {
logger.error(`[R插件][yt-dlp审计] Error executing ytDlpGetTilt: ${error}. Stderr: ${stderr}`);
logger.error(
`[R插件][yt-dlp审计] Error executing ytDlpGetTilt: ${error}. Stderr: ${stderr}`
);
reject(error);
} else {
resolve(stdout.trim());
@ -90,15 +93,24 @@ export function ytDlpGetTilt(url, isOversea, proxy, cookiePath = "") {
* @param cookiePath
* @param thumbnailFilenamePrefix 缩略图文件名前缀 (不含扩展名)
*/
export function ytDlpGetThumbnail(path, url, isOversea, proxy, cookiePath = "", thumbnailFilenamePrefix = "thumbnail") {
export function ytDlpGetThumbnail(
path,
url,
isOversea,
proxy,
cookiePath = '',
thumbnailFilenamePrefix = 'thumbnail'
) {
return new Promise((resolve, reject) => {
const cookieParam = constructCookiePath(url, cookiePath);
const finalThumbnailName = thumbnailFilenamePrefix || "thumbnail";
const finalThumbnailName = thumbnailFilenamePrefix || 'thumbnail';
const command = `yt-dlp --write-thumbnail --convert-thumbnails png --skip-download ${cookieParam} ${constructProxyParam(isOversea, proxy)} "${url}" -P "${path}" -o "${finalThumbnailName}.%(ext)s"`;
exec(command, (error, stdout, stderr) => {
if (error) {
logger.error(`[R插件][yt-dlp审计] Error executing ytDlpGetThumbnail: ${error}. Stderr: ${stderr}`);
logger.error(
`[R插件][yt-dlp审计] Error executing ytDlpGetThumbnail: ${error}. Stderr: ${stderr}`
);
return reject(error);
}
// 从yt-dlp的输出中提取文件名
@ -111,7 +123,9 @@ export function ytDlpGetThumbnail(path, url, isOversea, proxy, cookiePath = "",
resolve(thumbnailFilename);
} else {
// 兜底方案:如果无法从输出中解析,则按原逻辑拼接
logger.warn("[R插件][yt-dlp审计] Could not parse thumbnail filename from stdout. Falling back to default.");
logger.warn(
'[R插件][yt-dlp审计] Could not parse thumbnail filename from stdout. Falling back to default.'
);
// 尝试查找文件因为yt-dlp可能没有输出我们期望的格式
const expectedPngPath = `${finalThumbnailName}.png`;
resolve(expectedPngPath);
@ -134,21 +148,34 @@ export function ytDlpGetThumbnail(path, url, isOversea, proxy, cookiePath = "",
* @param outputFilename 输出文件名 (不含扩展名)
* @param cookiePath Cookie所在位置
*/
export async function ytDlpHelper(path, url, isOversea, proxy, maxThreads, outputFilename, merge = false, graphics, timeRange, cookiePath = "") {
export async function ytDlpHelper(
path,
url,
isOversea,
proxy,
maxThreads,
outputFilename,
merge = false,
graphics,
timeRange,
cookiePath = ''
) {
return new Promise((resolve, reject) => {
let command = "";
let command = '';
// 构造 cookie 参数
const cookieParam = constructCookiePath(url, cookiePath);
// 确保 outputFilename 不为空,提供一个默认值以防万一
const finalOutputFilename = outputFilename || "temp_download";
const finalOutputFilename = outputFilename || 'temp_download';
if (url.includes("music")) {
if (url.includes('music')) {
// 这里是 YouTube Music的处理逻辑
// e.g yt-dlp -x --audio-format mp3 https://youtu.be/5wEtefq9VzM -o test.mp3
command = `yt-dlp -x --audio-format flac -f ba ${cookieParam} ${constructProxyParam(isOversea, proxy)} -P "${path}" -o "${finalOutputFilename}.flac" "${url}"`;
} else {
// 正常情况下的处理逻辑
const fParam = url.includes("youtu") ? `--download-sections "*${timeRange}" -f "bv${graphics}[ext=mp4]+ba[ext=m4a]" ` : "";
const fParam = url.includes('youtu')
? `--download-sections "*${timeRange}" -f "bv${graphics}[ext=mp4]+ba[ext=m4a]" `
: '';
command = `yt-dlp -N ${maxThreads} ${fParam} --concurrent-fragments ${maxThreads} ${cookieParam} ${constructProxyParam(isOversea, proxy)} -P "${path}" -o "${finalOutputFilename}.%(ext)s" "${url}"`;
}