koishi-plugin-smmcat-nai-diffusion 0.0.1 → 0.0.2

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
@@ -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: "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",
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,50 @@ 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
+ return;
313
+ }
314
+ if (config.useMd) {
315
+ const md = `<qqbot-at-user id="${userId}" /> 画完了,请点击下方查看!
316
+
317
+ ${imgs.map((item) => {
318
+ return `[查看图片](${item})`;
319
+ }).join("\n")}`;
320
+ await Chat.send(session, md);
321
+ } else {
322
+ await Chat.send(session, imgs.map((item) => {
323
+ return import_koishi.h.image(item);
324
+ }).join("\n"));
325
+ }
326
+ use.clear(session);
327
+ } catch (error) {
328
+ use.clear(session);
329
+ }
330
+ });
331
+ ctx.command("转图 <prompt:text>").action(async ({ session }, prompt) => {
332
+ const { userId, guildId } = session;
333
+ if (!config.useGuildUser.includes(userId)) {
334
+ if (!(guildId && config.useGuildId.includes(guildId))) {
335
+ return `该群暂时不提供该功能...`;
336
+ }
337
+ }
338
+ const imgList = import_koishi.h.select(prompt, "img").map((i) => i.attrs.src);
339
+ const text = import_koishi.h.select(prompt, "text")[0]?.attrs.content || null;
340
+ console.log(imgList);
341
+ console.log(text);
342
+ if (!(imgList.length && text)) return "请传词条和参考图!";
343
+ if (use.isUse(session)) return `正在进行上一个绘画,请等待...`;
344
+ try {
345
+ use.start(session);
346
+ await Chat.send(session, `<qqbot-at-user id="${userId}" /> 稍等,正在给你画...`);
347
+ const imgs = await naiDiffusion.getDrawByPicAndEntry(text, imgList[0], async (err) => {
348
+ await session.send(err);
349
+ });
350
+ if (!(imgs && imgs.length)) {
351
+ await Chat.send(session, "生图失败...");
352
+ return;
353
+ }
220
354
  if (config.useMd) {
221
355
  const md = `<qqbot-at-user id="${userId}" /> 画完了,请点击下方查看!
222
356
 
@@ -240,5 +374,6 @@ __name(apply, "apply");
240
374
  0 && (module.exports = {
241
375
  Config,
242
376
  apply,
377
+ inject,
243
378
  name
244
379
  });
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.1",
4
+ "version": "0.0.2",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [