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

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