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 +1 -1
- package/lib/index.js +104 -18
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
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
|
-
|
|
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{
|
|
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
|
|
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
|
|
188
|
+
const triggerRegex = /神金|发|掉落|猫猫钻|w|\b\d{3,5}\b|一千|一百|十|九|八|七|六|五|四|三|两|二|一/i;
|
|
140
189
|
if (!triggerRegex.test(messageForChecks)) {
|
|
141
190
|
return;
|
|
142
191
|
}
|
|
143
|
-
const
|
|
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) =>
|
|
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
|
|
152
|
-
if (
|
|
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(
|
|
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
|
-
|
|
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(`向监听群 ${
|
|
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
|
}
|