koishi-plugin-smmcat-nai-diffusion 0.0.1 → 0.0.3
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.d.ts +8 -0
- package/lib/index.js +138 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -6,6 +6,14 @@ export interface Config {
|
|
|
6
6
|
useMd: boolean;
|
|
7
7
|
useGuildId: string[];
|
|
8
8
|
useGuildUser: string[];
|
|
9
|
+
negative_prompt: string;
|
|
9
10
|
}
|
|
11
|
+
export declare const inject: string[];
|
|
10
12
|
export declare const Config: Schema<Config>;
|
|
13
|
+
export type CanvasData = {
|
|
14
|
+
naturalHeight: number;
|
|
15
|
+
height: number;
|
|
16
|
+
naturalWidth: number;
|
|
17
|
+
width: number;
|
|
18
|
+
};
|
|
11
19
|
export declare function apply(ctx: Context, config: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
Config: () => Config,
|
|
24
24
|
apply: () => apply,
|
|
25
|
+
inject: () => inject,
|
|
25
26
|
name: () => name
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(src_exports);
|
|
@@ -115,9 +116,11 @@ var Chat = {
|
|
|
115
116
|
|
|
116
117
|
// src/index.ts
|
|
117
118
|
var name = "smmcat-nai-diffusion";
|
|
119
|
+
var inject = ["canvas"];
|
|
118
120
|
var Config = import_koishi.Schema.object({
|
|
119
121
|
deBug: import_koishi.Schema.boolean().default(false).description("获取更多日志消息"),
|
|
120
122
|
useMd: import_koishi.Schema.boolean().default(false).description("使用md发送消息"),
|
|
123
|
+
negative_prompt: import_koishi.Schema.string().default("lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry, ugly, deformed, poorly drawn hands, poorly drawn face, mutation, deformed, bad proportions, gross proportions, long neck, missing arms, missing legs, extra arms, extra legs, fused fingers, too many fingers, unclear eyes, bad body, out of focus, chromatic aberration").description("默认反向词条"),
|
|
121
124
|
token: import_koishi.Schema.string().default("").description("[tuercha](https://api.tuercha.com/register) 绘图站提供的令牌"),
|
|
122
125
|
useGuildId: import_koishi.Schema.array(String).role("table").default([]).description("指定可用群"),
|
|
123
126
|
useGuildUser: import_koishi.Schema.array(String).role("table").default([]).description("指定可用人(无视可用群规则)")
|
|
@@ -138,7 +141,7 @@ function apply(ctx, config) {
|
|
|
138
141
|
role: "user",
|
|
139
142
|
content: JSON.stringify({
|
|
140
143
|
prompt: text,
|
|
141
|
-
negative_prompt:
|
|
144
|
+
negative_prompt: config.negative_prompt,
|
|
142
145
|
size: size[Math.floor(Math.random() * size.length)],
|
|
143
146
|
steps: 23
|
|
144
147
|
})
|
|
@@ -168,6 +171,93 @@ function apply(ctx, config) {
|
|
|
168
171
|
return null;
|
|
169
172
|
}
|
|
170
173
|
},
|
|
174
|
+
/** 通过参考图和词条绘制图像 */
|
|
175
|
+
async getDrawByPicAndEntry(text, imgUrl, fn) {
|
|
176
|
+
const base64Img = await naiDiffusion.imageUrlToBase64(imgUrl);
|
|
177
|
+
if (base64Img.err) {
|
|
178
|
+
await fn(base64Img.err);
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
const drawParams = {
|
|
182
|
+
prompt: text,
|
|
183
|
+
negative_prompt: config.negative_prompt,
|
|
184
|
+
size: base64Img.size,
|
|
185
|
+
steps: 23,
|
|
186
|
+
scale: 5,
|
|
187
|
+
sampler: "k_euler_ancestral",
|
|
188
|
+
image_format: "png",
|
|
189
|
+
i2i: {
|
|
190
|
+
image: base64Img.base64.replace(/^data:image\/\w+;base64,/, ""),
|
|
191
|
+
strength: 0.7,
|
|
192
|
+
noise: 0.1
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
try {
|
|
196
|
+
const body = {
|
|
197
|
+
model: "nai-diffusion-4-5-full",
|
|
198
|
+
messages: [
|
|
199
|
+
{
|
|
200
|
+
role: "user",
|
|
201
|
+
content: JSON.stringify(drawParams)
|
|
202
|
+
}
|
|
203
|
+
],
|
|
204
|
+
stream: false,
|
|
205
|
+
max_tokens: 1e5
|
|
206
|
+
};
|
|
207
|
+
const res = await ctx.http.post("https://api.tuercha.com/v1/chat/completions", body, {
|
|
208
|
+
headers: {
|
|
209
|
+
Authorization: "Bearer " + config.token
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
const imgList = [];
|
|
213
|
+
if (Array.isArray(res.choices)) {
|
|
214
|
+
for (const data of res.choices) {
|
|
215
|
+
const base64 = naiDiffusion.extractBase64(data.message.content || "");
|
|
216
|
+
if (base64) {
|
|
217
|
+
const imgUrl2 = await naiDiffusion.base64ToWebUrl(base64);
|
|
218
|
+
imgUrl2 && imgList.push(imgUrl2);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return imgList;
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.log(error.response);
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
/** 图片网络地址转 base64 */
|
|
229
|
+
async imageUrlToBase64(url) {
|
|
230
|
+
if (!url) return { err: "请传入图片", base64: ``, size: [0, 0] };
|
|
231
|
+
const useImg = await ctx.canvas.loadImage(url);
|
|
232
|
+
const h2 = useImg.naturalHeight || useImg.height || 0;
|
|
233
|
+
const w = useImg.naturalWidth || useImg.width || 0;
|
|
234
|
+
console.log(h2, w);
|
|
235
|
+
if (!(h2 % 64 == 0 && w % 64 == 0)) {
|
|
236
|
+
return {
|
|
237
|
+
base64: ``,
|
|
238
|
+
size: [w, h2],
|
|
239
|
+
err: "尺寸不符合要求"
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
const response = await ctx.http.get(url, {
|
|
244
|
+
responseType: "arraybuffer"
|
|
245
|
+
});
|
|
246
|
+
const base64 = Buffer.from(response).toString("base64");
|
|
247
|
+
return {
|
|
248
|
+
base64: `data:image/png;base64,${base64}`,
|
|
249
|
+
size: [w, h2],
|
|
250
|
+
err: null
|
|
251
|
+
};
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.error("图片转 base64 失败:", error);
|
|
254
|
+
return {
|
|
255
|
+
base64: ``,
|
|
256
|
+
size: [w, h2],
|
|
257
|
+
err: error.message
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
},
|
|
171
261
|
/** 输入的内容是否存在中文 */
|
|
172
262
|
containsForbiddenChars(str) {
|
|
173
263
|
return /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\uff00-\uffef\u3000\u3001-\u303f]/u.test(str);
|
|
@@ -217,6 +307,52 @@ function apply(ctx, config) {
|
|
|
217
307
|
use.start(session);
|
|
218
308
|
await Chat.send(session, `<qqbot-at-user id="${userId}" /> 稍等,正在给你画...`);
|
|
219
309
|
const imgs = await naiDiffusion.getDrawByEntry(prompt);
|
|
310
|
+
if (!(imgs && imgs.length)) {
|
|
311
|
+
await Chat.send(session, "生图失败...");
|
|
312
|
+
use.start(session);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (config.useMd) {
|
|
316
|
+
const md = `<qqbot-at-user id="${userId}" /> 画完了,请点击下方查看!
|
|
317
|
+
|
|
318
|
+
${imgs.map((item) => {
|
|
319
|
+
return `[查看图片](${item})`;
|
|
320
|
+
}).join("\n")}`;
|
|
321
|
+
await Chat.send(session, md);
|
|
322
|
+
} else {
|
|
323
|
+
await Chat.send(session, imgs.map((item) => {
|
|
324
|
+
return import_koishi.h.image(item);
|
|
325
|
+
}).join("\n"));
|
|
326
|
+
}
|
|
327
|
+
use.clear(session);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
use.clear(session);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
ctx.command("转图 <prompt:text>").action(async ({ session }, prompt) => {
|
|
333
|
+
const { userId, guildId } = session;
|
|
334
|
+
if (!config.useGuildUser.includes(userId)) {
|
|
335
|
+
if (!(guildId && config.useGuildId.includes(guildId))) {
|
|
336
|
+
return `该群暂时不提供该功能...`;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const imgList = import_koishi.h.select(prompt, "img").map((i) => i.attrs.src);
|
|
340
|
+
const text = import_koishi.h.select(prompt, "text")[0]?.attrs.content || null;
|
|
341
|
+
console.log(imgList);
|
|
342
|
+
console.log(text);
|
|
343
|
+
if (!(imgList.length && text)) return "请传词条和参考图!";
|
|
344
|
+
if (use.isUse(session)) return `正在进行上一个绘画,请等待...`;
|
|
345
|
+
try {
|
|
346
|
+
use.start(session);
|
|
347
|
+
await Chat.send(session, `<qqbot-at-user id="${userId}" /> 稍等,正在给你画...`);
|
|
348
|
+
const imgs = await naiDiffusion.getDrawByPicAndEntry(text, imgList[0], async (err) => {
|
|
349
|
+
await session.send(err);
|
|
350
|
+
});
|
|
351
|
+
if (!(imgs && imgs.length)) {
|
|
352
|
+
await Chat.send(session, "生图失败...");
|
|
353
|
+
use.start(session);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
220
356
|
if (config.useMd) {
|
|
221
357
|
const md = `<qqbot-at-user id="${userId}" /> 画完了,请点击下方查看!
|
|
222
358
|
|
|
@@ -240,5 +376,6 @@ __name(apply, "apply");
|
|
|
240
376
|
0 && (module.exports = {
|
|
241
377
|
Config,
|
|
242
378
|
apply,
|
|
379
|
+
inject,
|
|
243
380
|
name
|
|
244
381
|
});
|