koishi-plugin-cat-raising 0.1.6 → 0.1.8

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
@@ -3,7 +3,7 @@ export declare const name = "cat-raising";
3
3
  export interface Config {
4
4
  targetQQ: string;
5
5
  isGroup: boolean;
6
- monitorGroup: string;
6
+ monitorGroups: string[];
7
7
  historySize: number;
8
8
  }
9
9
  export declare const Config: Schema<Config>;
package/lib/index.js CHANGED
@@ -30,14 +30,62 @@ var name = "cat-raising";
30
30
  var Config = import_koishi.Schema.object({
31
31
  targetQQ: import_koishi.Schema.string().description("目标QQ号或QQ群号").required(),
32
32
  isGroup: import_koishi.Schema.boolean().description("是否为QQ群").default(false),
33
- monitorGroup: import_koishi.Schema.string().description("监听的群号(只检测此群的消息)").required(),
34
- // [核心改动 2] 添加配置项的UI描述
33
+ monitorGroups: import_koishi.Schema.array(import_koishi.Schema.string()).description("监听的群号列表 (可以添加多个群,插件只会处理这些群里的消息)").required(),
35
34
  historySize: import_koishi.Schema.number().description("防复读历史记录大小 (记录最近N条转发信息,防止短期内对同一直播间的同一活动重复转发)").default(30).min(5).max(100)
36
35
  });
36
+ function preprocessChineseNumerals(text) {
37
+ const replacements = {
38
+ "三十六": "36",
39
+ "三十五": "35",
40
+ "三十四": "34",
41
+ "三十三": "33",
42
+ "三十二": "32",
43
+ "三十一": "31",
44
+ "三十": "30",
45
+ "二十九": "29",
46
+ "二十八": "28",
47
+ "二十七": "27",
48
+ "二十六": "26",
49
+ "二十五": "25",
50
+ "二十四": "24",
51
+ "二十三": "23",
52
+ "二十二": "22",
53
+ "二十一": "21",
54
+ "二十": "20",
55
+ "十九": "19",
56
+ "十八": "18",
57
+ "十七": "17",
58
+ "十六": "16",
59
+ "十五": "15",
60
+ "十四": "14",
61
+ "十三": "13",
62
+ "十二": "12",
63
+ "十一": "11",
64
+ "十": "10",
65
+ "一千": "1000",
66
+ "一百": "100",
67
+ "九": "9",
68
+ "八": "8",
69
+ "七": "7",
70
+ "六": "6",
71
+ "五": "5",
72
+ "四": "4",
73
+ "三": "3",
74
+ "两": "2",
75
+ "二": "2",
76
+ "一": "1"
77
+ };
78
+ let processedText = text;
79
+ for (const [cn, ar] of Object.entries(replacements)) {
80
+ processedText = processedText.replace(new RegExp(cn, "g"), ar);
81
+ }
82
+ return processedText;
83
+ }
84
+ __name(preprocessChineseNumerals, "preprocessChineseNumerals");
37
85
  function extractAllRoomIds(text) {
38
86
  const patterns = [
39
87
  /(?:播间号|房间号|直播间)[::\s]*(\d{6,15})/g,
40
- /\b(\d{8,15})\b/g
88
+ /\b(\d{6,15})\b/g
41
89
  ];
42
90
  const foundIds = /* @__PURE__ */ new Set();
43
91
  for (const pattern of patterns) {
@@ -129,36 +177,38 @@ function parseEvents(text) {
129
177
  __name(parseEvents, "parseEvents");
130
178
  function apply(ctx, config) {
131
179
  const forwardedHistory = [];
180
+ const warningMessageMap = /* @__PURE__ */ new Map();
132
181
  const REJECTION_KEYWORDS = ["签到", "打卡"];
133
182
  const OVERRIDE_KEYWORDS = ["神金", "发"];
134
183
  ctx.on("message", async (session) => {
135
- if (session.channelId !== config.monitorGroup) return;
184
+ if (!config.monitorGroups.includes(session.channelId)) return;
136
185
  const originalMessageContent = session.content;
137
186
  const messageForChecks = session.stripped.content;
138
187
  const messageId = session.messageId;
139
- const triggerRegex = /神金|发|掉落|猫猫钻|w|\b\d{3,5}\b/i;
188
+ const triggerRegex = /神金|发|掉落|猫猫钻|w|\b\d{3,5}\b|一千|一百|十|九|八|七|六|五|四|三|两|二|一/i;
140
189
  if (!triggerRegex.test(messageForChecks)) {
141
190
  return;
142
191
  }
143
- const hasRejectionKeyword = REJECTION_KEYWORDS.some((keyword) => messageForChecks.includes(keyword));
192
+ const roomIds = extractAllRoomIds(messageForChecks);
193
+ if (roomIds.length !== 1) {
194
+ return;
195
+ }
196
+ const roomId = roomIds[0];
197
+ const preprocessedMessage = preprocessChineseNumerals(messageForChecks);
198
+ const hasRejectionKeyword = REJECTION_KEYWORDS.some((keyword) => preprocessedMessage.includes(keyword));
144
199
  if (hasRejectionKeyword) {
145
- const hasOverrideKeyword = OVERRIDE_KEYWORDS.some((keyword) => messageForChecks.includes(keyword));
200
+ const hasOverrideKeyword = OVERRIDE_KEYWORDS.some((keyword) => preprocessedMessage.includes(keyword));
146
201
  if (!hasOverrideKeyword) {
147
202
  ctx.logger.info(`消息包含拒绝关键词且无覆盖词,已忽略: ${messageForChecks.substring(0, 50)}...`);
148
203
  return;
149
204
  }
150
205
  }
151
- const roomIds = extractAllRoomIds(messageForChecks);
152
- if (roomIds.length > 1) {
153
- return;
154
- }
155
- const roomId = roomIds.length === 1 ? roomIds[0] : null;
156
- const parsedEvents = parseEvents(messageForChecks);
157
- if (!parsedEvents || !roomId) {
206
+ const parsedEvents = parseEvents(preprocessedMessage);
207
+ if (!parsedEvents) {
158
208
  return;
159
209
  }
160
210
  const strongContextRegex = /神金|发|掉落|猫猫钻|w/i;
161
- const hasStrongContext = strongContextRegex.test(messageForChecks);
211
+ const hasStrongContext = strongContextRegex.test(preprocessedMessage);
162
212
  const hasTime = parsedEvents.some((event) => event.dateTime !== "时间未知");
163
213
  if (!hasStrongContext && !hasTime) {
164
214
  ctx.logger.info(`纯数字信息缺少时间,已忽略: ${messageForChecks.replace(/\s+/g, " ").substring(0, 50)}...`);
@@ -166,10 +216,23 @@ function apply(ctx, config) {
166
216
  }
167
217
  const currentDateTime = parsedEvents[0].dateTime;
168
218
  if (forwardedHistory.some((entry) => entry.roomId === roomId && entry.dateTime === currentDateTime)) {
169
- session.send(`看到啦看到啦,不要发那么多次嘛~`);
219
+ try {
220
+ const sentMessageIds = await session.send(`看到啦看到啦,不要发那么多次嘛~`);
221
+ if (sentMessageIds && sentMessageIds.length > 0) {
222
+ const warningMessageId = sentMessageIds[0];
223
+ warningMessageMap.set(messageId, warningMessageId);
224
+ if (warningMessageMap.size > config.historySize) {
225
+ const oldestKey = warningMessageMap.keys().next().value;
226
+ warningMessageMap.delete(oldestKey);
227
+ }
228
+ }
229
+ } catch (e) {
230
+ ctx.logger.warn("发送重复警告消息时失败:", e);
231
+ }
170
232
  return;
171
233
  }
172
234
  let biliInfo = "";
235
+ let helperMessageId = void 0;
173
236
  try {
174
237
  const roomInfoUrl = `https://api.live.bilibili.com/room/v1/Room/get_info?room_id=${roomId}`;
175
238
  const roomInfo = await ctx.http.get(roomInfoUrl);
@@ -184,10 +247,13 @@ function apply(ctx, config) {
184
247
  ---
185
248
  用户投稿数: ${videoCount}`;
186
249
  try {
187
- await session.send(`直播间: ${roomId}
250
+ const sentMessageIds = await session.send(`直播间: ${roomId}
188
251
  用户投稿数: ${videoCount}`);
252
+ if (sentMessageIds && sentMessageIds.length > 0) {
253
+ helperMessageId = sentMessageIds[0];
254
+ }
189
255
  } catch (e) {
190
- ctx.logger.warn(`向监听群 ${config.monitorGroup} 发送B站信息时失败:`, e);
256
+ ctx.logger.warn(`向监听群 ${session.channelId} 发送B站信息时失败:`, e);
191
257
  }
192
258
  } catch (error) {
193
259
  ctx.logger.warn(`获取直播间 ${roomId} 的B站信息失败: ${error.message}`);
@@ -206,6 +272,7 @@ function apply(ctx, config) {
206
272
  const newEntry = {
207
273
  originalMessageId: messageId,
208
274
  forwardedMessageId,
275
+ helperMessageId,
209
276
  originalContent: originalMessageContent,
210
277
  roomId,
211
278
  dateTime: currentDateTime
@@ -220,10 +287,19 @@ function apply(ctx, config) {
220
287
  }
221
288
  });
222
289
  ctx.on("message-deleted", async (session) => {
290
+ if (!config.monitorGroups.includes(session.channelId)) return;
223
291
  const originalMessageId = session.messageId;
224
292
  const entryIndex = forwardedHistory.findIndex((entry) => entry.originalMessageId === originalMessageId);
225
293
  if (entryIndex !== -1) {
226
294
  const entry = forwardedHistory[entryIndex];
295
+ if (entry.helperMessageId) {
296
+ try {
297
+ await session.bot.deleteMessage(session.channelId, entry.helperMessageId);
298
+ ctx.logger.info(`成功撤回监听群内的助手消息: ${entry.helperMessageId}`);
299
+ } catch (error) {
300
+ ctx.logger.error(`撤回助手消息 (ID: ${entry.helperMessageId}) 失败:`, error);
301
+ }
302
+ }
227
303
  try {
228
304
  await session.bot.deleteMessage(config.targetQQ, entry.forwardedMessageId);
229
305
  ctx.logger.info(`成功撤回转发的消息: ${entry.forwardedMessageId}`);
@@ -232,6 +308,16 @@ function apply(ctx, config) {
232
308
  } finally {
233
309
  forwardedHistory.splice(entryIndex, 1);
234
310
  }
311
+ } else if (warningMessageMap.has(originalMessageId)) {
312
+ const warningMessageId = warningMessageMap.get(originalMessageId);
313
+ try {
314
+ await session.bot.deleteMessage(session.channelId, warningMessageId);
315
+ ctx.logger.info(`成功撤回重复提示消息: ${warningMessageId}`);
316
+ } catch (error) {
317
+ ctx.logger.error(`撤回重复提示消息 (ID: ${warningMessageId}) 失败:`, error);
318
+ } finally {
319
+ warningMessageMap.delete(originalMessageId);
320
+ }
235
321
  }
236
322
  });
237
323
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-cat-raising",
3
3
  "description": "",
4
- "version": "0.1.6",
4
+ "version": "0.1.8",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [