koishi-plugin-starfx-bot 0.5.1 → 0.6.0

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
@@ -1,7 +1,8 @@
1
- import { Context, h, Schema, Session } from 'koishi';
1
+ import { Context, h, Logger, Schema, Session } from 'koishi';
2
2
  export declare const name = "starfx-bot";
3
3
  export declare let baseDir: string;
4
4
  export declare let assetsDir: string;
5
+ export declare const starfxLogger: Logger;
5
6
  export interface Config {
6
7
  openLock: boolean;
7
8
  openSold: boolean;
@@ -10,6 +11,7 @@ export interface Config {
10
11
  atNotSayOther: boolean;
11
12
  atNotSayProperty: number;
12
13
  atNotSayOtherProperty: number;
14
+ record: boolean;
13
15
  replyBot: string;
14
16
  iLoveYou: boolean;
15
17
  }
@@ -17,6 +19,7 @@ export declare const Config: Schema<Schemastery.ObjectS<{
17
19
  openLock: Schema<boolean, boolean>;
18
20
  openSold: Schema<boolean, boolean>;
19
21
  bangdreamBorder: Schema<boolean, boolean>;
22
+ record: Schema<boolean, boolean>;
20
23
  atNotSay: Schema<boolean, boolean>;
21
24
  atNotSayProperty: Schema<number, number>;
22
25
  atNotSayOther: Schema<boolean, boolean>;
@@ -27,6 +30,7 @@ export declare const Config: Schema<Schemastery.ObjectS<{
27
30
  openLock: boolean;
28
31
  openSold: boolean;
29
32
  bangdreamBorder: boolean;
33
+ record: boolean;
30
34
  atNotSay: boolean;
31
35
  atNotSayProperty: number;
32
36
  atNotSayOther: boolean;
@@ -36,7 +40,15 @@ export declare const Config: Schema<Schemastery.ObjectS<{
36
40
  } & import("cosmokit").Dict>;
37
41
  export declare const usage = "<h5>StarFreedomX\u7684\u81EA\u7528\u63D2\u4EF6 \u653E\u4E86\u4E00\u4E9B\u5C0F\u529F\u80FD</h5>\n ";
38
42
  export declare function apply(ctx: Context, cfg: Config): void;
39
- export declare function getImageSrc(session: Session, param: string): Promise<string>;
43
+ export declare function addRecord(ctx: Context, gid: string, avatarUrl: string): Promise<string>;
44
+ export declare function getRecord(gid: string): Promise<string>;
45
+ export declare function getImageSrc(session: Session, param: string, option?: {
46
+ number?: boolean;
47
+ img?: boolean;
48
+ at?: boolean;
49
+ noParam?: boolean;
50
+ quote?: boolean;
51
+ }): Promise<string>;
40
52
  export declare function handleBanGDreamConfig(ctx: Context, options: any): Promise<{
41
53
  color: string;
42
54
  band: string;
package/lib/index.js CHANGED
@@ -41,14 +41,17 @@ var require_zh_CN = __commonJS({
41
41
  var src_exports = {};
42
42
  __export(src_exports, {
43
43
  Config: () => Config,
44
+ addRecord: () => addRecord,
44
45
  apply: () => apply,
45
46
  assetsDir: () => assetsDir,
46
47
  baseDir: () => baseDir,
47
48
  drawLock: () => drawLock,
48
49
  drawSold: () => drawSold,
49
50
  getImageSrc: () => getImageSrc,
51
+ getRecord: () => getRecord,
50
52
  handleBanGDreamConfig: () => handleBanGDreamConfig,
51
53
  name: () => name,
54
+ starfxLogger: () => starfxLogger,
52
55
  usage: () => usage
53
56
  });
54
57
  module.exports = __toCommonJS(src_exports);
@@ -56,14 +59,17 @@ var import_koishi = require("koishi");
56
59
  var import_sharp = __toESM(require("sharp"));
57
60
  var fs = __toESM(require("fs"));
58
61
  var import_jimp = require("jimp");
62
+ var import_node_path = __toESM(require("node:path"));
59
63
  var name = "starfx-bot";
60
64
  var baseDir;
61
65
  var assetsDir;
66
+ var starfxLogger = new import_koishi.Logger("starfx-bot");
62
67
  var Config = import_koishi.Schema.intersect([
63
68
  import_koishi.Schema.object({
64
69
  openLock: import_koishi.Schema.boolean().default(true).description("开启明日方舟封印功能"),
65
70
  openSold: import_koishi.Schema.boolean().default(true).description('开启闲鱼"卖掉了"功能'),
66
71
  bangdreamBorder: import_koishi.Schema.boolean().default(true).description("开启BanG Dream!边框功能"),
72
+ record: import_koishi.Schema.boolean().default(true).description("开启群语录功能"),
67
73
  atNotSay: import_koishi.Schema.boolean().default(true).description("开启‘艾特我又不说话’功能"),
68
74
  atNotSayProperty: import_koishi.Schema.number().role("slider").min(0).max(1).step(0.01).default(0.5).description("'艾特我又不说话'回复概率"),
69
75
  atNotSayOther: import_koishi.Schema.boolean().default(true).description("开启‘艾特他又不说话’功能"),
@@ -98,11 +104,36 @@ function apply(ctx, cfg) {
98
104
  return import_koishi.h.image(imageBase64);
99
105
  });
100
106
  }
107
+ if (cfg.record) {
108
+ ctx.command("投稿 [param]").action(async ({ session }, param) => {
109
+ const imageSrc = await getImageSrc(
110
+ session,
111
+ param,
112
+ {
113
+ img: true,
114
+ at: false,
115
+ quote: true,
116
+ noParam: false,
117
+ number: false
118
+ }
119
+ );
120
+ if (!imageSrc) {
121
+ return "请发送带图片的指令消息或引用图片消息进行投稿";
122
+ }
123
+ return await addRecord(ctx, session.gid.replace(":", "_"), imageSrc);
124
+ });
125
+ }
101
126
  ctx.middleware(async (session, next) => {
102
127
  const elements = session.elements;
103
128
  await atNotSayReply(cfg, session, elements);
104
129
  await replyBot(cfg, session, elements);
105
130
  await iLoveYou(cfg, session, elements);
131
+ if (cfg.record && session.content?.startsWith("语录")) {
132
+ const filepath = await getRecord(session.gid.replace(":", "_"));
133
+ starfxLogger.info(`send record: ${filepath}`);
134
+ if (!filepath) return "暂无语录呢";
135
+ return import_koishi.h.image(filepath);
136
+ }
106
137
  return next();
107
138
  });
108
139
  function initAssets() {
@@ -121,27 +152,80 @@ function apply(ctx, cfg) {
121
152
  __name(initAssets, "initAssets");
122
153
  }
123
154
  __name(apply, "apply");
124
- async function getImageSrc(session, param) {
125
- if (param?.length && param?.length === String(Number(param))?.length) {
155
+ async function addRecord(ctx, gid, avatarUrl) {
156
+ const recordDir = `${assetsDir}/record/${gid}`;
157
+ const avatarBuffer = await ctx.http.get(avatarUrl, { responseType: "arraybuffer" });
158
+ saveImage(avatarBuffer, recordDir);
159
+ return "添加成功!";
160
+ }
161
+ __name(addRecord, "addRecord");
162
+ async function getRecord(gid) {
163
+ const recordDir = `${assetsDir}/record/${gid}`;
164
+ const files = fs.readdirSync(recordDir);
165
+ return files?.length ? import_node_path.default.join(recordDir, import_koishi.Random.pick(files)) : null;
166
+ }
167
+ __name(getRecord, "getRecord");
168
+ function getTodayPrefix() {
169
+ const now = /* @__PURE__ */ new Date();
170
+ const yyyy = now.getFullYear();
171
+ const mm = String(now.getMonth() + 1).padStart(2, "0");
172
+ const dd = String(now.getDate()).padStart(2, "0");
173
+ return `${yyyy}${mm}${dd}`;
174
+ }
175
+ __name(getTodayPrefix, "getTodayPrefix");
176
+ function getNextSequenceNumber(directory, prefix) {
177
+ const files = fs.existsSync(directory) ? fs.readdirSync(directory) : [];
178
+ const regex = new RegExp(`^${prefix}-(\\d+)\\.jpg$`);
179
+ let maxNum = 0;
180
+ files.forEach((file) => {
181
+ const match = file.match(regex);
182
+ if (match) {
183
+ const num = parseInt(match[1], 10);
184
+ if (num > maxNum) {
185
+ maxNum = num;
186
+ }
187
+ }
188
+ });
189
+ return maxNum + 1;
190
+ }
191
+ __name(getNextSequenceNumber, "getNextSequenceNumber");
192
+ function saveImage(arrayBuffer, directory) {
193
+ const prefix = getTodayPrefix();
194
+ const seq = getNextSequenceNumber(directory, prefix);
195
+ const filename = `${prefix}-${seq}.jpg`;
196
+ const filepath = import_node_path.default.join(directory, filename);
197
+ if (!fs.existsSync(directory)) {
198
+ fs.mkdirSync(directory, { recursive: true });
199
+ }
200
+ const buffer = Buffer.from(arrayBuffer);
201
+ fs.writeFileSync(filepath, buffer);
202
+ console.log(`已保存图片:${filepath}`);
203
+ }
204
+ __name(saveImage, "saveImage");
205
+ async function getImageSrc(session, param, option) {
206
+ const number = option?.number ?? true, img = option?.img ?? true, at = option?.at ?? true, noParam = option?.noParam ?? true, quote = option?.quote ?? true;
207
+ if (number && param?.length && param?.length === String(Number(param))?.length) {
126
208
  return `https://q1.qlogo.cn/g?b=qq&nk=${param}&s=640`;
127
- } else if (!param?.length) {
209
+ } else if (noParam && !param?.length) {
128
210
  return `https://q1.qlogo.cn/g?b=qq&nk=${session.userId}&s=640`;
129
211
  }
130
212
  const elementArray = session.elements;
131
213
  for (const element of elementArray) {
132
- if (element?.type === "img") {
214
+ if (img && element?.type === "img") {
133
215
  return element?.attrs?.src;
134
- } else if (element?.type === "at" && element?.attrs?.id) {
216
+ } else if (at && element?.type === "at" && element?.attrs?.id) {
135
217
  return `https://q1.qlogo.cn/g?b=qq&nk=${element.attrs.id}&s=640`;
136
218
  }
137
219
  }
138
- const quoteElementArray = session?.quote?.elements;
139
- if (quoteElementArray?.length) {
140
- for (const element of quoteElementArray) {
141
- if (element?.type === "img") {
142
- return element?.attrs?.src;
143
- } else if (element?.type === "at" && element?.attrs?.id && element.attrs.id !== session.selfId) {
144
- return `https://q1.qlogo.cn/g?b=qq&nk=${element?.attrs?.id}&s=640`;
220
+ if (quote) {
221
+ const quoteElementArray = session?.quote?.elements;
222
+ if (quoteElementArray?.length) {
223
+ for (const element of quoteElementArray) {
224
+ if (img && element?.type === "img") {
225
+ return element?.attrs?.src;
226
+ } else if (at && element?.type === "at" && element?.attrs?.id && element.attrs.id !== session.selfId) {
227
+ return `https://q1.qlogo.cn/g?b=qq&nk=${element?.attrs?.id}&s=640`;
228
+ }
145
229
  }
146
230
  }
147
231
  }
@@ -156,14 +240,14 @@ async function handleBanGDreamConfig(ctx, options) {
156
240
  happy: ["happy", "orange", "橙", "橙色"]
157
241
  };
158
242
  const bands = {
159
- ppp: ["ppp", "Poppin'Party", "破琵琶", "步品破茶", "poppin", "popipa", "poppinparty", "ポピパ"],
160
- ag: ["ag", "Afterglow", "夕阳红", "悪蓋愚狼"],
161
- pp: ["pp", "PastelPalettes", "Pastel*Palettes", "PastelPalettes", "怕死怕累", "pastel", "palettes", "pasupare", "パスパレ", "破巣照破烈斗"],
162
- hhw: ["hhw", "ハロー、ハッピーワールド!", "Hello,HappyWorld!", "helloHappyWorld", "ハロハピ", "HelloHappyWorld!", "harohapi", "破狼法被威悪怒", "儿歌团", "好好玩"],
163
- r: ["r", "Roselia", "露世里恶", "萝", "露世裏悪", "ロゼリア", "r组", "相声团", "相声组"],
164
- ras: ["ras", "RaiseASuilen", "raise", "suilen", "ラス", "零図悪酔恋", "睡莲", "麗厨唖睡蓮", "睡蓮"],
165
- mnk: ["mnk", "モニカ", "蝶团", "蝶", "Morfonica", "毛二力", "monika", "monica"],
166
- go: ["go", "MyGO!!!!!", "MyGO!!!!!", "mygo", "我去!!!!!", "我去!!!!!", "我去", "卖狗"]
243
+ ppp: ["ppp", "poppin'Party", "破琵琶", "步品破茶", "poppin", "popipa", "poppinparty", "ポピパ"],
244
+ ag: ["ag", "afterglow", "夕阳红", "悪蓋愚狼"],
245
+ pp: ["pp", "pastelpalettes", "pastel*palettes", "pastelPalettes", "怕死怕累", "pastel", "palettes", "pasupare", "パスパレ", "破巣照破烈斗"],
246
+ hhw: ["hhw", "ハロー、ハッピーワールド!", "hello,happyworld!", "hellohappyworld", "ハロハピ", "hellohappyworld!", "harohapi", "破狼法被威悪怒", "儿歌团", "好好玩"],
247
+ r: ["r", "roselia", "露世里恶", "萝", "露世裏悪", "ロゼリア", "r组", "相声团", "相声组"],
248
+ ras: ["ras", "raiseasuilen", "raise", "suilen", "ラス", "零図悪酔恋", "睡莲", "麗厨唖睡蓮", "睡蓮"],
249
+ mnk: ["mnk", "モニカ", "蝶团", "蝶", "morfonica", "毛二力", "monika", "monica"],
250
+ go: ["go", "mygo!!!!!", "mygo!!!!!", "mygo", "我去!!!!!", "我去!!!!!", "我去", "卖狗"]
167
251
  };
168
252
  const trains = {
169
253
  "color_star": ["花后", "1", "彩", "true"],
@@ -194,9 +278,9 @@ async function handleBanGDreamConfig(ctx, options) {
194
278
  }
195
279
  const starNum = options.starNum ? parseInt(options.starNum) : 0;
196
280
  drawConfig.starNum = starNum > 0 && starNum < 10 ? starNum : 0;
197
- if (drawConfig.starType) {
281
+ if (options.train) {
198
282
  for (const [train, aliases] of Object.entries(trains)) {
199
- if (aliases.includes(options.color.toLowerCase())) {
283
+ if (aliases.includes(options.train.toLowerCase())) {
200
284
  drawConfig.starType = train;
201
285
  break;
202
286
  }
@@ -360,13 +444,16 @@ __name(drawBanGDream, "drawBanGDream");
360
444
  // Annotate the CommonJS export names for ESM import in node:
361
445
  0 && (module.exports = {
362
446
  Config,
447
+ addRecord,
363
448
  apply,
364
449
  assetsDir,
365
450
  baseDir,
366
451
  drawLock,
367
452
  drawSold,
368
453
  getImageSrc,
454
+ getRecord,
369
455
  handleBanGDreamConfig,
370
456
  name,
457
+ starfxLogger,
371
458
  usage
372
459
  });
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "contributors": [
5
5
  "StarFreedomX <starfreedomx@outlook.com>"
6
6
  ],
7
- "version": "0.5.1",
7
+ "version": "0.6.0",
8
8
  "main": "lib/index.js",
9
9
  "typings": "lib/index.d.ts",
10
10
  "files": [
package/readme.md CHANGED
@@ -13,17 +13,18 @@ StarFreedomX机器人的小功能,自用
13
13
  * 我也喜欢你!
14
14
 
15
15
  # 更新日志
16
- | 版本 | 更新日志 |
17
- |---------|--------------------------|
18
- | `0.0.1` | 加入封印功能 |
19
- | `0.1.0` | 加入"卖掉了"功能 |
20
- | `0.2.0` | 加入"艾特我又不说话"回复功能 |
21
- | `0.3.0` | 加入"我喜欢你"和"我才不是机器人!"回复功能 |
22
- | `0.3.3` | 修订添加"我才不是机器人"是否需要at |
23
- | `0.3.4` | 分离"艾特我/他又不说话"的两个选项为单独的开关 |
24
- | `0.3.5` | 修复丢失的assets |
25
- | `0.3.6` | 添加"艾特我/他又不说话"的概率配置 |
26
- | `0.4.0` | 更改处理库为sharp |
27
- | `0.4.1` | 修复sharp处理w>h的图报错的bug |
28
- | `0.5.0` | 加入BanG Dream!边框功能 |
29
- | `0.5.1` | 对边框的参数做了限定,修复了异常输入导致的报错 |
16
+ | 版本 | 更新日志 |
17
+ |---------|-----------------------------|
18
+ | `0.0.1` | 加入封印功能 |
19
+ | `0.1.0` | 加入"卖掉了"功能 |
20
+ | `0.2.0` | 加入"艾特我又不说话"回复功能 |
21
+ | `0.3.0` | 加入"我喜欢你"和"我才不是机器人!"回复功能 |
22
+ | `0.3.3` | 修订添加"我才不是机器人"是否需要at |
23
+ | `0.3.4` | 分离"艾特我/他又不说话"的两个选项为单独的开关 |
24
+ | `0.3.5` | 修复丢失的assets |
25
+ | `0.3.6` | 添加"艾特我/他又不说话"的概率配置 |
26
+ | `0.4.0` | 更改处理库为sharp |
27
+ | `0.4.1` | 修复sharp处理w>h的图报错的bug |
28
+ | `0.5.0` | 加入BanG Dream!边框功能 |
29
+ | `0.5.1` | 对边框的参数做了限定,修复了异常输入导致的报错 |
30
+ | `0.6.0` | 加入群语录功能,修复一处bangdream绘制的bug |