Merge pull request #87 from devil233-ui/master

* **New Features**
  * Added a global image forwarding limit setting to control when images are merged into a forwarded message versus sent inline across platforms (Weibo, Bilibili dynamics/columns, MiYouShe, Xiaohongshu).
  * Expanded Bilibili support: recognizes m.bilibili.com links and additional dynamic URLs; improved display for multi-part videos with richer titles/descriptions.
  * Enhanced dynamic post handling: sends text first, then chooses between batched or inline images based on the threshold, with clear fallback messaging on failure.
* **Chores**
  * Added configuration option and UI control for the global image forwarding limit.
This commit is contained in:
RrOrange 2025-09-03 22:06:01 +08:00 committed by GitHub
commit 49de188740
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 76 additions and 34 deletions

View File

@ -149,7 +149,7 @@ export class tools extends plugin {
permission: 'master', permission: 'master',
}, },
{ {
reg: "(bilibili.com|b23.tv|bili2233.cn|t.bilibili.com|^BV[1-9a-zA-Z]{10}$)", reg: "(bilibili.com|b23.tv|bili2233.cn|m.bilibili.com|t.bilibili.com|^BV[1-9a-zA-Z]{10}$)",
fnc: "bili", fnc: "bili",
}, },
{ {
@ -316,6 +316,8 @@ export class tools extends plugin {
this.aiModel = this.toolsConfig.aiModel; this.aiModel = this.toolsConfig.aiModel;
// 强制使用海外服务器 // 强制使用海外服务器
this.forceOverseasServer = this.toolsConfig.forceOverseasServer; this.forceOverseasServer = this.toolsConfig.forceOverseasServer;
// 解析图片是否合并转发
this.globalImageLimit = this.toolsConfig.globalImageLimit;
} }
// 翻译插件 // 翻译插件
@ -921,7 +923,7 @@ export class tools extends plugin {
return true; return true;
} }
// 动态处理 // 动态处理
if (url.includes("t.bilibili.com") || url.includes("bilibili.com\/opus")) { if (url.includes("t.bilibili.com") || url.includes("bilibili.com\/opus") || url.includes("bilibili.com\/dynamic")){
if (_.isEmpty(this.biliSessData)) { if (_.isEmpty(this.biliSessData)) {
e.reply("检测到没有填写biliSessData无法解析动态"); e.reply("检测到没有填写biliSessData无法解析动态");
return true; return true;
@ -1243,18 +1245,30 @@ export class tools extends plugin {
const dynamicId = /[^/]+(?!.*\/)/.exec(url)[0]; const dynamicId = /[^/]+(?!.*\/)/.exec(url)[0];
getDynamic(dynamicId, session).then(async resp => { getDynamic(dynamicId, session).then(async resp => {
if (resp.dynamicSrc.length > 0 || resp.dynamicDesc) { if (resp.dynamicSrc.length > 0 || resp.dynamicDesc) {
e.reply(`${ this.identifyPrefix }识别:哔哩哔哩动态\n${ resp.dynamicDesc }`); // 先发送动态描述文本
let dynamicSrcMsg = []; if (resp.dynamicDesc) {
resp.dynamicSrc.forEach(item => { e.reply(`${this.identifyPrefix}识别:哔哩哔哩动态\n${resp.dynamicDesc}`);
dynamicSrcMsg.push({ }
message: segment.image(item),
nickname: e.sender.card || e.user_id, // 处理图片消息
user_id: e.user_id, if (resp.dynamicSrc.length > 0) {
}); if (resp.dynamicSrc.length > this.globalImageLimit) {
}); let dynamicSrcMsg = [];
await e.reply(await Bot.makeForwardMsg(dynamicSrcMsg)); resp.dynamicSrc.forEach(item => {
dynamicSrcMsg.push({
message: segment.image(item),
nickname: e.sender.card || e.user_id,
user_id: e.user_id,
});
});
await e.reply(await Bot.makeForwardMsg(dynamicSrcMsg));
} else {
const images = resp.dynamicSrc.map(item => segment.image(item));
await e.reply(images);
}
}
} else { } else {
e.reply(`识别:哔哩哔哩动态, 但是失败!`); await e.reply(`${this.identifyPrefix}识别:哔哩哔哩动态, 但是失败!`);
} }
}); });
return url; return url;
@ -1629,17 +1643,24 @@ export class tools extends plugin {
// 等待所有图片下载完成 // 等待所有图片下载完成
const paths = await Promise.all(imagePromises); const paths = await Promise.all(imagePromises);
// 直接构造 imagesData 数组
const imagesData = await Promise.all(paths.map(async (item) => {
return {
message: segment.image(await fs.promises.readFile(item)),
nickname: e.sender.card || e.user_id,
user_id: e.user_id,
};
}));
// 回复带有转发消息的图片数据 if (paths.length > this.globalImageLimit) {
e.reply(await Bot.makeForwardMsg(imagesData)); // 直接构造 imagesData 数组
const imagesData = await Promise.all(paths.map(async (item) => {
return {
message: segment.image(await fs.promises.readFile(item)),
nickname: e.sender.card || e.user_id,
user_id: e.user_id,
};
}));
// 回复带有转发消息的图片数据
e.reply(await Bot.makeForwardMsg(imagesData));
} else {
// 如果图片数量小于限制,直接发送图片
const images = await Promise.all(paths.map(async (item) => segment.image(await fs.promises.readFile(item))));
e.reply(images);
}
// 批量删除下载的文件 // 批量删除下载的文件
await Promise.all(paths.map(item => fs.promises.rm(item, { force: true }))); await Promise.all(paths.map(item => fs.promises.rm(item, { force: true })));
@ -2176,8 +2197,11 @@ export class tools extends plugin {
// 等待所有图片处理完 // 等待所有图片处理完
const images = await Promise.all(imagesPromise); const images = await Promise.all(imagesPromise);
// 回复合并的消息 // 大于判定数量则回复合并的消息
await e.reply(await Bot.makeForwardMsg(images)); if (images.length > this.globalImageLimit)
await e.reply(await Bot.makeForwardMsg(images));
else
await e.reply(images.map(item => item.message));
// 并行删除文件 // 并行删除文件
await Promise.all(images.map(({ filePath }) => checkAndRemoveFile(filePath))); await Promise.all(images.map(({ filePath }) => checkAndRemoveFile(filePath)));
@ -2393,15 +2417,20 @@ export class tools extends plugin {
const replyMsg = cover ? [segment.image(cover), normalMsg] : normalMsg; const replyMsg = cover ? [segment.image(cover), normalMsg] : normalMsg;
e.reply(replyMsg); e.reply(replyMsg);
// 图片 // 图片
if (images && images.length > 1) { if (images) {
const replyImages = images.map(item => { if (images.length > this.globalImageLimit) {
return { const replyImages = images.map(item => {
message: segment.image(item), return {
nickname: this.e.sender.card || this.e.user_id, message: segment.image(item),
user_id: this.e.user_id, nickname: this.e.sender.card || this.e.user_id,
}; user_id: this.e.user_id,
}); };
e.reply(Bot.makeForwardMsg(replyImages)); });
e.reply(Bot.makeForwardMsg(replyImages));
} else {
const imageSegments = images.map(item => segment.image(item));
e.reply(imageSegments);
}
} }
// 视频 // 视频
let vod_list = respJson.data.post?.vod_list; let vod_list = respJson.data.post?.vod_list;

View File

@ -1,5 +1,7 @@
globalBlackList: [] # 全局黑名单解析 globalBlackList: [] # 全局黑名单解析
globalImageLimit: 0 # 解析图片是否合并转发,默认合并
defaultPath: './data/rcmp4/' # 保存视频的位置 defaultPath: './data/rcmp4/' # 保存视频的位置
videoSizeLimit: 70 # 视频大小限制单位MB超过大小则转换成群文件上传 videoSizeLimit: 70 # 视频大小限制单位MB超过大小则转换成群文件上传
proxyAddr: '127.0.0.1' # 魔法地址 proxyAddr: '127.0.0.1' # 魔法地址

View File

@ -44,6 +44,17 @@ export function supportGuoba() {
options: globalWhitelist, options: globalWhitelist,
}, },
}, },
{
field: "globalImageLimit",
label: "解析图片是否合并转发",
bottomHelpMessage:
"超过配置的数字就会折叠。目前实现了此能的主要有米游社、b站动态专栏、微博、小红书",
component: "InputNumber",
required: false,
componentProps: {
placeholder: "请输入合并转发最大阈值",
},
},
{ {
field: "tools.proxyAddr", field: "tools.proxyAddr",
label: "魔法地址", label: "魔法地址",