koishi-plugin-imgdraw-selfuse 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +89 -5
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -121,8 +121,19 @@ async function apply(ctx, cfg) {
|
|
|
121
121
|
apiIdx.val++;
|
|
122
122
|
return api;
|
|
123
123
|
}
|
|
124
|
+
// ==================== 修复:增强 HTML/XML 清理 ====================
|
|
124
125
|
function cleanHtmlTags(str) {
|
|
125
|
-
|
|
126
|
+
if (!str)
|
|
127
|
+
return '';
|
|
128
|
+
// 1. 清理标准 HTML 标签
|
|
129
|
+
let cleaned = str.replace(/<<[^>]+>/g, ' ');
|
|
130
|
+
// 2. 清理 QQ XML 图片标签(如 <img src="..." file="..."/>)
|
|
131
|
+
cleaned = cleaned.replace(/<<img\s+[^>]+\/>/gi, ' ');
|
|
132
|
+
// 3. 清理其他 XML 标签
|
|
133
|
+
cleaned = cleaned.replace(/<<[^>]+>/g, ' ');
|
|
134
|
+
// 4. 清理多余空格和换行
|
|
135
|
+
cleaned = cleaned.replace(/\s+/g, ' ').trim();
|
|
136
|
+
return cleaned;
|
|
126
137
|
}
|
|
127
138
|
// 增强图片提取函数
|
|
128
139
|
function getImageUrlFromContent(text) {
|
|
@@ -440,6 +451,49 @@ async function apply(ctx, cfg) {
|
|
|
440
451
|
deleteAllCachedFiles(imageUrls);
|
|
441
452
|
}
|
|
442
453
|
}
|
|
454
|
+
// ==================== 新增:处理带图片的合并消息 ====================
|
|
455
|
+
async function processImg2ImgWithImages(session, prompt, images) {
|
|
456
|
+
const assets = ctx.assets;
|
|
457
|
+
if (!assets) {
|
|
458
|
+
await safeSend(session, cfg.messages.needAssets);
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
// 上传所有图片
|
|
462
|
+
const uploadResults = await Promise.allSettled(images.map(img => assets.upload(img.attrs.src, 'ref_image.jpg')));
|
|
463
|
+
const imageUrls = [];
|
|
464
|
+
for (const res of uploadResults) {
|
|
465
|
+
if (res.status === 'fulfilled' && /^https?:\/\//.test(res.value)) {
|
|
466
|
+
imageUrls.push(res.value);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (imageUrls.length === 0) {
|
|
470
|
+
await safeSend(session, cfg.messages.needAssets);
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
// 限制图片数量
|
|
474
|
+
const finalUrls = imageUrls.slice(0, cfg.maxImages);
|
|
475
|
+
if (finalUrls.length < imageUrls.length) {
|
|
476
|
+
logger.warn(`图片数量超过限制,已截取前 ${cfg.maxImages} 张`);
|
|
477
|
+
}
|
|
478
|
+
// 构建 prompt
|
|
479
|
+
const finalPrompt = cfg.img2imgPrompt
|
|
480
|
+
.replace('{url}', finalUrls.join(', '))
|
|
481
|
+
.replace('{prompt}', prompt);
|
|
482
|
+
await safeSend(session, cfg.messages.generating);
|
|
483
|
+
await generateWithMultipleImages(session, finalPrompt, finalUrls, cfg.img2imgModel || cfg.model);
|
|
484
|
+
}
|
|
485
|
+
// ==================== 新增:从 session.elements 提取纯文本 ====================
|
|
486
|
+
function extractTextFromElements(elements) {
|
|
487
|
+
if (!elements || !Array.isArray(elements))
|
|
488
|
+
return '';
|
|
489
|
+
const textParts = [];
|
|
490
|
+
for (const el of elements) {
|
|
491
|
+
if (el.type === 'text') {
|
|
492
|
+
textParts.push(el.attrs?.content || el.attrs?.text || '');
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return cleanHtmlTags(textParts.join(' '));
|
|
496
|
+
}
|
|
443
497
|
// ==================== 命令注册 ====================
|
|
444
498
|
const cmd = ctx.command(`${cfg.command} <raw:text>`, 'draw');
|
|
445
499
|
cfg.aliases.forEach((alias) => cmd.alias(alias));
|
|
@@ -464,8 +518,10 @@ async function apply(ctx, cfg) {
|
|
|
464
518
|
await safeSend(session, cfg.messages.fail);
|
|
465
519
|
}
|
|
466
520
|
});
|
|
521
|
+
// ==================== 修改:图生图命令支持合并消息 ====================
|
|
467
522
|
const imgCmd = ctx.command(`${cfg.img2imgCommand} <raw:text>`, 'imgdraw');
|
|
468
523
|
cfg.img2imgAliases.forEach((alias) => imgCmd.alias(alias));
|
|
524
|
+
// 修改 action 以支持检测消息中的图片
|
|
469
525
|
imgCmd.action(async ({ session }, raw) => {
|
|
470
526
|
try {
|
|
471
527
|
if (!session)
|
|
@@ -474,12 +530,39 @@ async function apply(ctx, cfg) {
|
|
|
474
530
|
return safeSend(session, cfg.messages.blacklisted);
|
|
475
531
|
if (!cfg.enableImg2Img)
|
|
476
532
|
return safeSend(session, cfg.messages.img2imgDisabled);
|
|
533
|
+
// ==================== 修复:从 elements 提取纯文本,避免 XML 污染 ====================
|
|
534
|
+
let prompt = '';
|
|
535
|
+
if (session.elements && session.elements.length > 0) {
|
|
536
|
+
// 有 elements,从中提取纯文本(排除图片等)
|
|
537
|
+
prompt = extractTextFromElements(session.elements);
|
|
538
|
+
if (debug)
|
|
539
|
+
logger.info('从 elements 提取的 prompt:', prompt);
|
|
540
|
+
}
|
|
541
|
+
// 如果 elements 没有文本,回退到 raw
|
|
542
|
+
if (!prompt && raw) {
|
|
543
|
+
prompt = cleanHtmlTags(raw);
|
|
544
|
+
}
|
|
545
|
+
// 检查消息中是否包含图片(QQ 合并消息)
|
|
546
|
+
const messageImages = session.elements ? koishi_1.h.select(session.elements, 'img') : [];
|
|
547
|
+
if (messageImages.length > 0) {
|
|
548
|
+
// 合并消息:同时包含文字和图片,直接处理
|
|
549
|
+
if (debug)
|
|
550
|
+
logger.info(`检测到合并消息,包含 ${messageImages.length} 张图片,prompt: "${prompt}"`);
|
|
551
|
+
if (!prompt) {
|
|
552
|
+
// 如果没有文字 prompt,使用默认提示
|
|
553
|
+
await processImg2ImgWithImages(session, '请根据图片内容进行编辑', messageImages);
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
await processImg2ImgWithImages(session, prompt, messageImages);
|
|
557
|
+
}
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
// 传统模式:只发送了文字,进入等待图片状态
|
|
561
|
+
if (!prompt)
|
|
562
|
+
return safeSend(session, cfg.messages.empty);
|
|
477
563
|
const assets = ctx.assets;
|
|
478
564
|
if (!assets)
|
|
479
565
|
return safeSend(session, cfg.messages.needAssets);
|
|
480
|
-
const prompt = cleanHtmlTags(raw || '');
|
|
481
|
-
if (!prompt)
|
|
482
|
-
return safeSend(session, cfg.messages.empty);
|
|
483
566
|
const key = `${session.guildId || 'private'}-${session.userId}`;
|
|
484
567
|
if (waitingMap.has(key)) {
|
|
485
568
|
return safeSend(session, cfg.messages.alreadyWaiting);
|
|
@@ -505,7 +588,7 @@ async function apply(ctx, cfg) {
|
|
|
505
588
|
await safeSend(session, cfg.messages.fail);
|
|
506
589
|
}
|
|
507
590
|
});
|
|
508
|
-
//
|
|
591
|
+
// ==================== 修改:消息监听支持追加图片 ====================
|
|
509
592
|
ctx.on('message', async (session) => {
|
|
510
593
|
try {
|
|
511
594
|
if (!session.elements)
|
|
@@ -514,6 +597,7 @@ async function apply(ctx, cfg) {
|
|
|
514
597
|
return;
|
|
515
598
|
const key = `${session.guildId || 'private'}-${session.userId}`;
|
|
516
599
|
const task = waitingMap.get(key);
|
|
600
|
+
// 如果没有等待任务,检查是否是新的合并消息(已在上面的 imgCmd action 中处理)
|
|
517
601
|
if (!task)
|
|
518
602
|
return;
|
|
519
603
|
const imgs = koishi_1.h.select(session.elements, 'img');
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-imgdraw-selfuse",
|
|
3
|
-
"description": "修改自ai-image
|
|
4
|
-
"version": "0.0.
|
|
3
|
+
"description": "修改自ai-image的画图插件,支持openai兼容api,增加base64转换以适配GPTimg2,支持发送合并消息图生图",
|
|
4
|
+
"version": "0.0.7",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|