koishi-plugin-smmcat-nai-diffusion 0.0.4 → 0.0.6

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 CHANGED
@@ -7,6 +7,9 @@ export interface Config {
7
7
  useGuildId: string[];
8
8
  useGuildUser: string[];
9
9
  negative_prompt: string;
10
+ gemimiBaseUrl: string;
11
+ gemimiToken: string;
12
+ gemimiType: string;
10
13
  }
11
14
  export declare const inject: string[];
12
15
  export declare const Config: Schema<Config>;
package/lib/index.js CHANGED
@@ -123,7 +123,10 @@ var Config = import_koishi.Schema.object({
123
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("默认反向词条"),
124
124
  token: import_koishi.Schema.string().default("").description("[tuercha](https://api.tuercha.com/register) 绘图站提供的令牌"),
125
125
  useGuildId: import_koishi.Schema.array(String).role("table").default([]).description("指定可用群"),
126
- useGuildUser: import_koishi.Schema.array(String).role("table").default([]).description("指定可用人(无视可用群规则)")
126
+ useGuildUser: import_koishi.Schema.array(String).role("table").default([]).description("指定可用人(无视可用群规则)"),
127
+ gemimiBaseUrl: import_koishi.Schema.string().default("https://api.futureppo.top").description("Gemimi 接口基地址(用于图生词,描述生词)"),
128
+ gemimiToken: import_koishi.Schema.string().default("").description("Gemimi 图生词提供的令牌(用于图生词,描述生词)"),
129
+ gemimiType: import_koishi.Schema.string().default("gemini-3-flash-preview").description("Gemimi 模型版本名(用于图生词,描述生词)")
127
130
  });
128
131
  function apply(ctx, config) {
129
132
  ctx.on("ready", () => {
@@ -175,7 +178,7 @@ function apply(ctx, config) {
175
178
  async getDrawByPicAndEntry(text, imgUrl, fn) {
176
179
  const base64Img = await naiDiffusion.imageUrlToBase64(imgUrl);
177
180
  if (base64Img.err) {
178
- await fn(base64Img.err);
181
+ fn && await fn(base64Img.err);
179
182
  return null;
180
183
  }
181
184
  const drawParams = {
@@ -221,18 +224,130 @@ function apply(ctx, config) {
221
224
  }
222
225
  return imgList;
223
226
  } catch (error) {
227
+ fn && await fn("请求失败");
224
228
  console.log(error.response);
225
229
  return null;
226
230
  }
227
231
  },
232
+ /** 通图片和提示词生成词条 */
233
+ async getEntryByGemimiForPicAndText(imgUrl, morePrompt, fn) {
234
+ try {
235
+ const imgInfo = await naiDiffusion.imageUrlToBase64(imgUrl, true);
236
+ if (imgInfo.err) {
237
+ throw new Error(imgInfo.err);
238
+ }
239
+ const body = {
240
+ model: config.gemimiType,
241
+ messages: [
242
+ {
243
+ role: "user",
244
+ content: [
245
+ {
246
+ type: "text",
247
+ text: "我需要你通过图生成 nai-diffusion-4-5-full 的词条,只需要发送词条信息即可,并以逗号结尾"
248
+ },
249
+ {
250
+ type: "image_url",
251
+ image_url: {
252
+ url: imgInfo.base64
253
+ }
254
+ }
255
+ ]
256
+ }
257
+ ],
258
+ "temperature": 0.7,
259
+ "max_tokens": 1024
260
+ };
261
+ const res = await ctx.http.post(config.gemimiBaseUrl + "/v1/chat/completions", body, {
262
+ headers: {
263
+ Authorization: config.gemimiToken
264
+ }
265
+ });
266
+ if (!Array.isArray(res.choices)) {
267
+ fn && await fn("未得到任何提示词");
268
+ return null;
269
+ }
270
+ if (!res.choices[0]?.message?.content) {
271
+ fn && await fn("未得到任何提示词");
272
+ return null;
273
+ }
274
+ if (naiDiffusion.containsForbiddenChars(res.choices[0].message.content)) {
275
+ fn && await fn("Gemimi接口返回的数据词条有误");
276
+ return null;
277
+ }
278
+ const text = res.choices[0].message.content + (morePrompt ? morePrompt.split(",").map((item) => {
279
+ if (item.trim()) {
280
+ const tag = item.trim().replace(/ /g, "_");
281
+ return `(${tag}:1.5)`;
282
+ } else {
283
+ return null;
284
+ }
285
+ }).filter((i) => i).join(", ") : "");
286
+ config.deBug && console.log(text);
287
+ return text;
288
+ } catch (error) {
289
+ console.log(error.response?.data || error);
290
+ fn && await fn("请求失败,请等待一会再请求 gemimi");
291
+ return null;
292
+ }
293
+ },
294
+ /** 通图片和提示词生成词条 */
295
+ async getEntryByGemimiForText(prompt, fn) {
296
+ try {
297
+ const body = {
298
+ model: config.gemimiType,
299
+ messages: [
300
+ {
301
+ role: "user",
302
+ content: [
303
+ {
304
+ type: "text",
305
+ text: "我需要你通过我的描述生成 nai-diffusion-4-5-full 的对应词条,只需要发送词条信息即可,最终以逗号结尾"
306
+ },
307
+ {
308
+ type: "text",
309
+ text: prompt
310
+ }
311
+ ]
312
+ }
313
+ ],
314
+ "temperature": 0.7,
315
+ "max_tokens": 1024
316
+ };
317
+ const res = await ctx.http.post(config.gemimiBaseUrl + "/v1/chat/completions", body, {
318
+ headers: {
319
+ Authorization: config.gemimiToken
320
+ }
321
+ });
322
+ if (!Array.isArray(res.choices)) {
323
+ fn && await fn("未得到任何提示词");
324
+ return null;
325
+ }
326
+ if (!res.choices[0]?.message?.content) {
327
+ fn && await fn("未得到任何提示词");
328
+ return null;
329
+ }
330
+ if (naiDiffusion.containsForbiddenChars(res.choices[0].message.content)) {
331
+ fn && await fn("gemimi接口返回的数据词条有误");
332
+ return null;
333
+ }
334
+ const text = res.choices[0].message.content;
335
+ config.deBug && console.log(text);
336
+ return text;
337
+ } catch (error) {
338
+ console.log(error.response?.data || error);
339
+ fn && await fn("请求失败,请等待一会再请求 gemimi");
340
+ return null;
341
+ }
342
+ },
228
343
  /** 图片网络地址转 base64 */
229
- async imageUrlToBase64(url) {
344
+ async imageUrlToBase64(url, ignoreSize = false) {
230
345
  if (!url) return { err: "请传入图片", base64: ``, size: [0, 0] };
231
346
  const useImg = await ctx.canvas.loadImage(url);
232
347
  const h2 = useImg.naturalHeight || useImg.height || 0;
233
348
  const w = useImg.naturalWidth || useImg.width || 0;
234
- console.log(h2, w);
235
- if (!(h2 % 64 == 0 && w % 64 == 0)) {
349
+ config.deBug && console.log("图片宽高为:", h2, w);
350
+ if (!ignoreSize && !(h2 % 64 == 0 && w % 64 == 0)) {
236
351
  return {
237
352
  base64: ``,
238
353
  size: [w, h2],
@@ -329,6 +444,102 @@ ${imgs.map((item) => {
329
444
  use.clear(session);
330
445
  }
331
446
  });
447
+ if (config.gemimiToken) {
448
+ ctx.command("参考生图 <prompt:text>").action(async ({ session }, prompt) => {
449
+ const { userId, guildId } = session;
450
+ if (!config.useGuildUser.includes(userId)) {
451
+ if (!(guildId && config.useGuildId.includes(guildId))) {
452
+ return `该群暂时不提供该功能...`;
453
+ }
454
+ }
455
+ const imgList = import_koishi.h.select(prompt, "img").map((i) => i.attrs.src);
456
+ const text = import_koishi.h.select(prompt, "text")[0]?.attrs.content || null;
457
+ if (!imgList.length) return "请传参考图!";
458
+ if (use.isUse(session)) return `正在进行上一个绘画,请等待...`;
459
+ if (prompt && naiDiffusion.containsForbiddenChars(prompt)) return `输入的词条包含问题,请检查!`;
460
+ try {
461
+ use.start(session);
462
+ await Chat.send(session, `<qqbot-at-user id="${userId}" /> 稍等,Gemimi酱 正通过图片信息和文本获取词条...`);
463
+ const prompt2 = await naiDiffusion.getEntryByGemimiForPicAndText(imgList[0], text, async (err) => {
464
+ await session.send(err);
465
+ });
466
+ if (!prompt2) return use.clear(session);
467
+ if (config.useMd) {
468
+ await Chat.send(session, `<qqbot-at-user id="${userId}" /> 获取词条成功,正在根据词条信息给你画...`);
469
+ } else {
470
+ await Chat.send(session, `获取词条成功,正在根据词条信息给你画...`);
471
+ }
472
+ const imgs = await naiDiffusion.getDrawByEntry(prompt2);
473
+ if (!(imgs && imgs.length)) {
474
+ await Chat.send(session, "生图失败...");
475
+ use.clear(session);
476
+ return;
477
+ }
478
+ if (config.useMd) {
479
+ const md = `<qqbot-at-user id="${userId}" /> 画完了,请点击下方查看!
480
+
481
+ ${imgs.map((item) => {
482
+ return `[查看图片](${item})`;
483
+ }).join("\n")}`;
484
+ await Chat.send(session, md);
485
+ } else {
486
+ await Chat.send(session, imgs.map((item) => {
487
+ return import_koishi.h.image(item);
488
+ }).join("\n"));
489
+ }
490
+ use.clear(session);
491
+ } catch (error) {
492
+ console.log(error);
493
+ use.clear(session);
494
+ }
495
+ });
496
+ ctx.command("描述生图 <prompt:text>").action(async ({ session }, prompt) => {
497
+ const { userId, guildId } = session;
498
+ if (!config.useGuildUser.includes(userId)) {
499
+ if (!(guildId && config.useGuildId.includes(guildId))) {
500
+ return `该群暂时不提供该功能...`;
501
+ }
502
+ }
503
+ const text = import_koishi.h.select(prompt, "text")[0]?.attrs.content || null;
504
+ if (!text) return "请传描述!";
505
+ if (use.isUse(session)) return `正在进行上一个绘画,请等待...`;
506
+ try {
507
+ use.start(session);
508
+ await Chat.send(session, `<qqbot-at-user id="${userId}" /> 稍等,Gemimi酱 正通过描述去获取词条...`);
509
+ const prompt2 = await naiDiffusion.getEntryByGemimiForText(text, async (err) => {
510
+ await session.send(err);
511
+ });
512
+ if (!prompt2) return use.clear(session);
513
+ if (config.useMd) {
514
+ await Chat.send(session, `<qqbot-at-user id="${userId}" /> 获取词条成功,正在根据词条信息给你画...`);
515
+ } else {
516
+ await Chat.send(session, `获取词条成功,正在根据词条信息给你画...`);
517
+ }
518
+ const imgs = await naiDiffusion.getDrawByEntry(prompt2);
519
+ if (!(imgs && imgs.length)) {
520
+ await Chat.send(session, "生图失败...");
521
+ use.clear(session);
522
+ return;
523
+ }
524
+ if (config.useMd) {
525
+ const md = `<qqbot-at-user id="${userId}" /> 画完了,请点击下方查看!
526
+
527
+ ${imgs.map((item) => {
528
+ return `[查看图片](${item})`;
529
+ }).join("\n")}`;
530
+ await Chat.send(session, md);
531
+ } else {
532
+ await Chat.send(session, imgs.map((item) => {
533
+ return import_koishi.h.image(item);
534
+ }).join("\n"));
535
+ }
536
+ use.clear(session);
537
+ } catch (error) {
538
+ console.log(error);
539
+ use.clear(session);
540
+ }
541
+ });
542
+ }
332
543
  ctx.command("转图 <prompt:text>").action(async ({ session }, prompt) => {
333
544
  const { userId, guildId } = session;
334
545
  if (!config.useGuildUser.includes(userId)) {
@@ -344,7 +555,11 @@ ${imgs.map((item) => {
344
555
  if (use.isUse(session)) return `正在进行上一个绘画,请等待...`;
345
556
  try {
346
557
  use.start(session);
347
- await Chat.send(session, `<qqbot-at-user id="${userId}" /> 稍等,正在给你画...`);
558
+ if (config.useMd) {
559
+ await Chat.send(session, `<qqbot-at-user id="${userId}" /> 稍等,Nai酱 正在给你画...`);
560
+ } else {
561
+ await Chat.send(session, `稍等,正在给你画...`);
562
+ }
348
563
  const imgs = await naiDiffusion.getDrawByPicAndEntry(text, imgList[0], async (err) => {
349
564
  await session.send(err);
350
565
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-smmcat-nai-diffusion",
3
3
  "description": "来自 tuercha.com 公益站的绘图服务",
4
- "version": "0.0.4",
4
+ "version": "0.0.6",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [