koishi-plugin-emojiluna-plus 0.0.3 → 0.0.4
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/adapters/autoCommands.js +7 -9
- package/lib/adapters/commands.js +2 -2
- package/lib/adapters/consoleListeners.js +12 -3
- package/lib/adapters/restApi.js +5 -3
- package/lib/collectors/autoCollector.d.ts +4 -0
- package/lib/collectors/autoCollector.js +42 -9
- package/lib/services/emojiluna.d.ts +6 -0
- package/lib/services/emojiluna.js +24 -3
- package/lib/types.d.ts +5 -0
- package/lib/types.js +6 -1
- package/package.json +1 -1
|
@@ -4,6 +4,8 @@ exports.registerAutoCollectCommands = registerAutoCollectCommands;
|
|
|
4
4
|
const koishi_1 = require("koishi");
|
|
5
5
|
const render_1 = require("./render");
|
|
6
6
|
const types_1 = require("../types");
|
|
7
|
+
const DEFAULT_HOUR_LIMIT = types_1.DEFAULT_COLLECT_LIMITS.hour;
|
|
8
|
+
const DEFAULT_DAY_LIMIT = types_1.DEFAULT_COLLECT_LIMITS.day;
|
|
7
9
|
const RECENT_RECORDS = 6;
|
|
8
10
|
const DEBUG_LINES = 15;
|
|
9
11
|
function registerAutoCollectCommands(ctx, config, autoCollector) {
|
|
@@ -83,7 +85,7 @@ function formatStatus(config, autoCollector) {
|
|
|
83
85
|
`条件: ${config.minEmojiSize}KB-${config.maxEmojiSize}MB${config.minEdgePixels ? ` | 短边≥${config.minEdgePixels}px` : ''} | 相似度阈值 ${config.similarityThreshold}`,
|
|
84
86
|
`取源: HTTP ${config.fetchTimeout}ms 超时 | 本地路径 ${config.allowLocalPaths ? '允许' : '禁止'}${config.localPathRoots.length ? `(限定 ${config.localPathRoots.length} 个目录)` : ''}`,
|
|
85
87
|
`AI: 类型过滤 ${config.enableImageTypeFilter ? `开启(超时 ${config.aiFilterTimeout}ms,兜底 ${config.aiFilterFallback})` : '关闭'} | 入库后分析 ${config.autoAnalyze ? '开启' : '关闭'}`,
|
|
86
|
-
`限流:
|
|
88
|
+
`限流: 单会话 ${quotaSummary(config)} | 全局 ${config.globalDayLimit || '不限'}/日 | 库存上限 ${config.maxEmojiCount}`,
|
|
87
89
|
`统计: 收到 ${stats.seen} 张 | 成功 ${stats.collected} 张 | 队列 ${stats.queue}/${config.autoCollectQueueSize} | 处理中 ${stats.active} | 特征 ${stats.signatures}${stats.preloaded ? '' : '(预热中)'}`,
|
|
88
90
|
];
|
|
89
91
|
const rejected = Object.entries(stats.rejected).sort((a, b) => b[1] - a[1]);
|
|
@@ -101,12 +103,8 @@ function formatStatus(config, autoCollector) {
|
|
|
101
103
|
}
|
|
102
104
|
return lines.join('\n');
|
|
103
105
|
}
|
|
104
|
-
function
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return firstQuota(config)?.dayLimit ?? 100;
|
|
109
|
-
}
|
|
110
|
-
function firstQuota(config) {
|
|
111
|
-
return Object.values(config.groupAutoCollectLimit ?? {})[0];
|
|
106
|
+
function quotaSummary(config) {
|
|
107
|
+
const overrides = Object.keys(config.groupAutoCollectLimit ?? {}).length;
|
|
108
|
+
const scope = overrides ? `,按群覆盖 ${overrides} 个` : '';
|
|
109
|
+
return `默认 ${DEFAULT_HOUR_LIMIT}/小时、${DEFAULT_DAY_LIMIT}/日${scope}`;
|
|
112
110
|
}
|
package/lib/adapters/commands.js
CHANGED
|
@@ -25,7 +25,7 @@ function registerTriggerMiddleware(ctx, config) {
|
|
|
25
25
|
const content = session.content.trim();
|
|
26
26
|
if (content.length < TRIGGER_MATCH_MIN_LENGTH)
|
|
27
27
|
return next();
|
|
28
|
-
const emoji = await ctx.emojiluna.
|
|
28
|
+
const emoji = await ctx.emojiluna.getTriggerEmoji(content);
|
|
29
29
|
if (!emoji)
|
|
30
30
|
return next();
|
|
31
31
|
return next(async () => (0, render_1.emojiMessage)(ctx, config, emoji));
|
|
@@ -157,7 +157,7 @@ function registerLibraryCommands(ctx, config, emojiluna) {
|
|
|
157
157
|
`自动分析: ${flag(config.autoAnalyze)}`,
|
|
158
158
|
`图片类型过滤: ${flag(config.enableImageTypeFilter)}`,
|
|
159
159
|
`使用模型: ${config.model || '未配置'}`,
|
|
160
|
-
`AI分析统计: ${JSON.stringify(emojiluna.getAiTaskStats())}`,
|
|
160
|
+
`AI分析统计: ${JSON.stringify(await emojiluna.getAiTaskStats())}`,
|
|
161
161
|
'',
|
|
162
162
|
'自动获取:',
|
|
163
163
|
`状态: ${flag(config.autoCollect)}`,
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.applyConsoleListeners = applyConsoleListeners;
|
|
7
|
+
const types_1 = require("../types");
|
|
7
8
|
const path_1 = __importDefault(require("path"));
|
|
8
9
|
const fs_1 = __importDefault(require("fs"));
|
|
9
10
|
const render_1 = require("./render");
|
|
@@ -32,7 +33,7 @@ const DIRECT_EVENTS = {
|
|
|
32
33
|
'emojiluna/deleteAiTask': 'deleteAiTask',
|
|
33
34
|
'emojiluna/retryAiTask': 'retryAiTask',
|
|
34
35
|
};
|
|
35
|
-
const MAX_REQUESTED_EMOJI_NAME =
|
|
36
|
+
const MAX_REQUESTED_EMOJI_NAME = types_1.MAX_EMOJI_NAME_LENGTH;
|
|
36
37
|
function resolveClientRoot(fromDir) {
|
|
37
38
|
let current = fromDir;
|
|
38
39
|
for (let depth = 0; depth < 5; depth++) {
|
|
@@ -45,7 +46,7 @@ function resolveClientRoot(fromDir) {
|
|
|
45
46
|
break;
|
|
46
47
|
current = parent;
|
|
47
48
|
}
|
|
48
|
-
return path_1.default.resolve(fromDir, '..', '..'
|
|
49
|
+
return path_1.default.resolve(fromDir, '..', '..');
|
|
49
50
|
}
|
|
50
51
|
function applyConsoleListeners(ctx, config) {
|
|
51
52
|
ctx.inject(['console', 'emojiluna'], (ctx) => {
|
|
@@ -62,7 +63,15 @@ async function registerListeners(ctx, config) {
|
|
|
62
63
|
prod: path_1.default.join(clientRoot, 'dist'),
|
|
63
64
|
});
|
|
64
65
|
for (const [event, method] of Object.entries(DIRECT_EVENTS)) {
|
|
65
|
-
|
|
66
|
+
const handler = invoke[method];
|
|
67
|
+
if (typeof handler !== 'function') {
|
|
68
|
+
emojiluna.debug.log('service', `控制台事件目标方法缺失,已跳过注册: ${event} -> ${method}`);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
ctx.console.addListener(event,
|
|
72
|
+
// Koishi invokes listeners with its own `this`, so the service
|
|
73
|
+
// receiver has to be bound explicitly before handing the method over.
|
|
74
|
+
handler.bind(emojiluna));
|
|
66
75
|
}
|
|
67
76
|
ctx.console.addListener('emojiluna/getBaseUrl', async () => {
|
|
68
77
|
const selfUrl = (0, render_1.resolveSelfUrl)(ctx, config);
|
package/lib/adapters/restApi.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.applyRestApi = applyRestApi;
|
|
7
|
+
const types_1 = require("../types");
|
|
7
8
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
const utils_1 = require("../utils");
|
|
@@ -176,10 +177,11 @@ function applyRestApi(ctx, config) {
|
|
|
176
177
|
if (!file?.filepath) {
|
|
177
178
|
return json(koa, { success: false, message: 'No file uploaded' }, 400);
|
|
178
179
|
}
|
|
180
|
+
const requestedName = firstField(fields, 'name') ||
|
|
181
|
+
file.originalFilename?.replace(/\.[^/.]+$/, '') ||
|
|
182
|
+
'uploaded';
|
|
179
183
|
const emoji = await ctx.emojiluna.addEmoji({
|
|
180
|
-
name:
|
|
181
|
-
file.originalFilename?.replace(/\.[^/.]+$/, '') ||
|
|
182
|
-
'uploaded',
|
|
184
|
+
name: requestedName.slice(0, types_1.MAX_EMOJI_NAME_LENGTH),
|
|
183
185
|
category: firstField(fields, 'category'),
|
|
184
186
|
tags: parseTagsField(firstField(fields, 'tags')),
|
|
185
187
|
}, { path: file.filepath }, firstField(fields, 'aiAnalysis') === 'true');
|
|
@@ -33,6 +33,7 @@ export declare class AutoCollector {
|
|
|
33
33
|
private rejectedHashes;
|
|
34
34
|
private aiVerdicts;
|
|
35
35
|
private queue;
|
|
36
|
+
private commitTail;
|
|
36
37
|
private active;
|
|
37
38
|
private nameSeq;
|
|
38
39
|
private manualEnabled;
|
|
@@ -52,12 +53,15 @@ export declare class AutoCollector {
|
|
|
52
53
|
dispose(): void;
|
|
53
54
|
private pump;
|
|
54
55
|
private processJob;
|
|
56
|
+
private commit;
|
|
55
57
|
private save;
|
|
56
58
|
private evaluateScope;
|
|
57
59
|
private evaluateSize;
|
|
58
60
|
private evaluateResolution;
|
|
59
61
|
private evaluateKnownHash;
|
|
62
|
+
private findSimilar;
|
|
60
63
|
private evaluateSimilarity;
|
|
64
|
+
private serialize;
|
|
61
65
|
private evaluateFrequency;
|
|
62
66
|
private evaluateLimit;
|
|
63
67
|
private evaluateLibrary;
|
|
@@ -7,6 +7,8 @@ const image_1 = require("../image");
|
|
|
7
7
|
const utils_1 = require("../utils");
|
|
8
8
|
const HOUR_MS = 3_600_000;
|
|
9
9
|
const DAY_MS = 86_400_000;
|
|
10
|
+
const DEFAULT_HOUR_LIMIT = types_1.DEFAULT_COLLECT_LIMITS.hour;
|
|
11
|
+
const DEFAULT_DAY_LIMIT = types_1.DEFAULT_COLLECT_LIMITS.day;
|
|
10
12
|
const PENDING_REF_TTL_MS = 60_000;
|
|
11
13
|
const REJECTED_HASH_TTL_MS = 6 * HOUR_MS;
|
|
12
14
|
const AI_VERDICT_TTL_MS = 24 * HOUR_MS;
|
|
@@ -39,6 +41,7 @@ class AutoCollector {
|
|
|
39
41
|
rejectedHashes = new Map();
|
|
40
42
|
aiVerdicts = new Map();
|
|
41
43
|
queue = [];
|
|
44
|
+
commitTail = Promise.resolve();
|
|
42
45
|
active = 0;
|
|
43
46
|
nameSeq = 0;
|
|
44
47
|
manualEnabled = null;
|
|
@@ -64,12 +67,10 @@ class AutoCollector {
|
|
|
64
67
|
return !this.stopped && (this.manualEnabled ?? this.config.autoCollect);
|
|
65
68
|
}
|
|
66
69
|
start() {
|
|
67
|
-
if (!this.config.autoCollect) {
|
|
68
|
-
this.debug.log('collect', '自动获取未启用,跳过监听注册');
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
70
|
this.ctx.on('message', (session) => this.observe(session));
|
|
72
|
-
this.ctx.logger.info(
|
|
71
|
+
this.ctx.logger.info(this.config.autoCollect
|
|
72
|
+
? 'Auto collector started'
|
|
73
|
+
: 'Auto collector idle: 自动获取未启用,可用 emojiluna.auto.toggle on 临时开启');
|
|
73
74
|
}
|
|
74
75
|
observe(session) {
|
|
75
76
|
if (!this.isEnabled)
|
|
@@ -237,7 +238,7 @@ class AutoCollector {
|
|
|
237
238
|
detail: `试运行:将保存为 "${this.buildName(session, isDirect)}",未实际写入`,
|
|
238
239
|
});
|
|
239
240
|
}
|
|
240
|
-
const saved = await this.
|
|
241
|
+
const saved = await this.serialize(() => this.commit(image.buffer, signature, hash, session, isDirect));
|
|
241
242
|
if (!pass(saved))
|
|
242
243
|
return;
|
|
243
244
|
this.consumeQuota(chatKey);
|
|
@@ -252,6 +253,22 @@ class AutoCollector {
|
|
|
252
253
|
this.pendingRefs.delete(ref);
|
|
253
254
|
}
|
|
254
255
|
}
|
|
256
|
+
async commit(buffer, signature, hash, session, isDirect) {
|
|
257
|
+
if (this.luna.uploadManager.hasHash(hash)) {
|
|
258
|
+
return { gate: '去重', ok: false, detail: '入库前已出现相同内容' };
|
|
259
|
+
}
|
|
260
|
+
if (signature) {
|
|
261
|
+
const similar = this.findSimilar(signature);
|
|
262
|
+
if (similar) {
|
|
263
|
+
return {
|
|
264
|
+
gate: '相似',
|
|
265
|
+
ok: false,
|
|
266
|
+
detail: `入库前与 ${similar.hash.slice(0, 8)} 相似度 ${similar.score.toFixed(3)}`,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return this.save(buffer, signature, hash, session, isDirect);
|
|
271
|
+
}
|
|
255
272
|
async save(buffer, signature, hash, session, isDirect) {
|
|
256
273
|
const name = this.buildName(session, isDirect);
|
|
257
274
|
const tags = this.buildTags(session, isDirect);
|
|
@@ -366,7 +383,7 @@ class AutoCollector {
|
|
|
366
383
|
}
|
|
367
384
|
return { gate: '去重', ok: true, detail: `内容哈希 ${hash.slice(0, 8)}` };
|
|
368
385
|
}
|
|
369
|
-
|
|
386
|
+
findSimilar(signature) {
|
|
370
387
|
let best = null;
|
|
371
388
|
for (const [hash, cached] of this.signatures) {
|
|
372
389
|
const score = similarityScore(signature, cached);
|
|
@@ -374,6 +391,10 @@ class AutoCollector {
|
|
|
374
391
|
best = { hash, score };
|
|
375
392
|
}
|
|
376
393
|
}
|
|
394
|
+
return best;
|
|
395
|
+
}
|
|
396
|
+
evaluateSimilarity(signature) {
|
|
397
|
+
const best = this.findSimilar(signature);
|
|
377
398
|
if (!best) {
|
|
378
399
|
return {
|
|
379
400
|
gate: '相似',
|
|
@@ -387,6 +408,11 @@ class AutoCollector {
|
|
|
387
408
|
detail: `与表情 ${best.hash.slice(0, 8)} 相似度 ${best.score.toFixed(3)},阈值 ${this.config.similarityThreshold}`,
|
|
388
409
|
};
|
|
389
410
|
}
|
|
411
|
+
serialize(task) {
|
|
412
|
+
const run = this.commitTail.then(task, task);
|
|
413
|
+
this.commitTail = run.then(() => undefined, () => undefined);
|
|
414
|
+
return run;
|
|
415
|
+
}
|
|
390
416
|
evaluateFrequency(hash, chatKey) {
|
|
391
417
|
const windowMs = this.config.frequencyWindow * 60_000;
|
|
392
418
|
const key = `${hash}|${chatKey}`;
|
|
@@ -411,8 +437,8 @@ class AutoCollector {
|
|
|
411
437
|
evaluateLimit(chatKey) {
|
|
412
438
|
const counter = this.windowCounter(chatKey);
|
|
413
439
|
const quota = this.config.groupAutoCollectLimit?.[chatKey.split(':')[1]];
|
|
414
|
-
const hourLimit = quota?.hourLimit ??
|
|
415
|
-
const dayLimit = quota?.dayLimit ??
|
|
440
|
+
const hourLimit = quota?.hourLimit ?? DEFAULT_HOUR_LIMIT;
|
|
441
|
+
const dayLimit = quota?.dayLimit ?? DEFAULT_DAY_LIMIT;
|
|
416
442
|
if (hourLimit > 0 && counter.hourCount >= hourLimit) {
|
|
417
443
|
return {
|
|
418
444
|
gate: '限流',
|
|
@@ -594,6 +620,13 @@ class AutoCollector {
|
|
|
594
620
|
else
|
|
595
621
|
this.frequency.delete(key);
|
|
596
622
|
}
|
|
623
|
+
for (const [key, counter] of this.counters) {
|
|
624
|
+
if (!counter.hourCount &&
|
|
625
|
+
!counter.dayCount &&
|
|
626
|
+
now - counter.dayStart >= DAY_MS) {
|
|
627
|
+
this.counters.delete(key);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
597
630
|
}
|
|
598
631
|
chatKey(session, isDirect) {
|
|
599
632
|
return isDirect
|
|
@@ -48,6 +48,12 @@ export declare class EmojiLunaService extends Service {
|
|
|
48
48
|
buffer: Buffer;
|
|
49
49
|
}[], aiAnalysis: boolean): Promise<EmojiItem[]>;
|
|
50
50
|
getEmojiByName(name: string): Promise<EmojiItem | null>;
|
|
51
|
+
/**
|
|
52
|
+
* Trigger-word replies should only fire on an exact emoji name or tag; the
|
|
53
|
+
* four-level lookup used by `emojiluna.get` also matches categories and ids,
|
|
54
|
+
* which would make ordinary messages steal a sticker.
|
|
55
|
+
*/
|
|
56
|
+
getTriggerEmoji(text: string): Promise<EmojiItem | null>;
|
|
51
57
|
getEmojisByName(name: string): Promise<EmojiItem[]>;
|
|
52
58
|
getEmojiById(id: string): Promise<EmojiItem | null>;
|
|
53
59
|
private filterEmojis;
|
|
@@ -13,6 +13,7 @@ const debug_1 = require("../debug");
|
|
|
13
13
|
const path_1 = __importDefault(require("path"));
|
|
14
14
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
15
15
|
const crypto_1 = require("crypto");
|
|
16
|
+
const MAX_IMPORT_ERRORS = 20;
|
|
16
17
|
class EmojiLunaService extends koishi_1.Service {
|
|
17
18
|
config;
|
|
18
19
|
_emojiStorage = {};
|
|
@@ -304,6 +305,18 @@ class EmojiLunaService extends koishi_1.Service {
|
|
|
304
305
|
const byCategory = this._byCategory.get(name)?.values().next().value;
|
|
305
306
|
return byCategory ? this._emojiStorage[byCategory] ?? null : null;
|
|
306
307
|
}
|
|
308
|
+
/**
|
|
309
|
+
* Trigger-word replies should only fire on an exact emoji name or tag; the
|
|
310
|
+
* four-level lookup used by `emojiluna.get` also matches categories and ids,
|
|
311
|
+
* which would make ordinary messages steal a sticker.
|
|
312
|
+
*/
|
|
313
|
+
async getTriggerEmoji(text) {
|
|
314
|
+
const byName = this._byName.get(text);
|
|
315
|
+
if (byName)
|
|
316
|
+
return this._emojiStorage[byName] ?? null;
|
|
317
|
+
const byTag = this._byTag.get(text)?.values().next().value;
|
|
318
|
+
return byTag ? this._emojiStorage[byTag] ?? null : null;
|
|
319
|
+
}
|
|
307
320
|
async getEmojisByName(name) {
|
|
308
321
|
const ids = new Set([
|
|
309
322
|
...(this._byName.get(name) ? [this._byName.get(name)] : []),
|
|
@@ -384,9 +397,15 @@ class EmojiLunaService extends koishi_1.Service {
|
|
|
384
397
|
try {
|
|
385
398
|
const emojis = Object.values(this._emojiStorage);
|
|
386
399
|
const concurrency = 4;
|
|
400
|
+
let failures = 0;
|
|
387
401
|
for (let i = 0; i < emojis.length; i += concurrency) {
|
|
388
402
|
const batch = emojis.slice(i, i + concurrency);
|
|
389
|
-
await Promise.all(batch.map((emoji) => this.deleteEmoji(emoji.id)));
|
|
403
|
+
const results = await Promise.all(batch.map((emoji) => this.deleteEmoji(emoji.id)));
|
|
404
|
+
failures += results.filter((deleted) => !deleted).length;
|
|
405
|
+
}
|
|
406
|
+
if (failures) {
|
|
407
|
+
this.ctx.logger.warn(`清空表情包时有 ${failures} 个未能删除`);
|
|
408
|
+
return false;
|
|
390
409
|
}
|
|
391
410
|
}
|
|
392
411
|
catch (error) {
|
|
@@ -617,7 +636,7 @@ class EmojiLunaService extends koishi_1.Service {
|
|
|
617
636
|
return removedCount;
|
|
618
637
|
}
|
|
619
638
|
async categorizeExistingEmojis() {
|
|
620
|
-
if (!this._aiAnalyzer.
|
|
639
|
+
if (!this._aiAnalyzer.hasModel || !this.config.autoCategorize) {
|
|
621
640
|
return { success: 0, failed: 0 };
|
|
622
641
|
}
|
|
623
642
|
let success = 0, failed = 0;
|
|
@@ -776,7 +795,9 @@ class EmojiLunaService extends koishi_1.Service {
|
|
|
776
795
|
}
|
|
777
796
|
catch (error) {
|
|
778
797
|
result.failed++;
|
|
779
|
-
result.errors.
|
|
798
|
+
if (result.errors.length < MAX_IMPORT_ERRORS) {
|
|
799
|
+
result.errors.push(`导入 ${file.name} 失败: ${error.message}`);
|
|
800
|
+
}
|
|
780
801
|
this.ctx.logger.error(`导入失败 ${file.path}:`, error);
|
|
781
802
|
}
|
|
782
803
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -111,6 +111,11 @@ export declare const GROUP_SCOPES: {
|
|
|
111
111
|
readonly whitelist: "仅白名单群";
|
|
112
112
|
readonly blacklist: "排除黑名单群";
|
|
113
113
|
};
|
|
114
|
+
export declare const DEFAULT_COLLECT_LIMITS: {
|
|
115
|
+
readonly hour: 20;
|
|
116
|
+
readonly day: 100;
|
|
117
|
+
};
|
|
118
|
+
export declare const MAX_EMOJI_NAME_LENGTH = 64;
|
|
114
119
|
export declare const COLLECT_MODES: {
|
|
115
120
|
readonly instant: "立即收集";
|
|
116
121
|
readonly frequency: "频次达标后收集";
|
package/lib/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IMAGE_TYPE_LABELS = exports.DEBUG_SCOPES = exports.AI_FILTER_FALLBACKS = exports.COLLECT_MODES = exports.GROUP_SCOPES = exports.DEFAULT_ACCEPTED_IMAGE_TYPES = exports.IMAGE_CONTENT_TYPES = void 0;
|
|
3
|
+
exports.IMAGE_TYPE_LABELS = exports.DEBUG_SCOPES = exports.AI_FILTER_FALLBACKS = exports.COLLECT_MODES = exports.MAX_EMOJI_NAME_LENGTH = exports.DEFAULT_COLLECT_LIMITS = exports.GROUP_SCOPES = exports.DEFAULT_ACCEPTED_IMAGE_TYPES = exports.IMAGE_CONTENT_TYPES = void 0;
|
|
4
4
|
exports.IMAGE_CONTENT_TYPES = [
|
|
5
5
|
{
|
|
6
6
|
type: 'emoji',
|
|
@@ -72,6 +72,11 @@ exports.GROUP_SCOPES = {
|
|
|
72
72
|
whitelist: '仅白名单群',
|
|
73
73
|
blacklist: '排除黑名单群',
|
|
74
74
|
};
|
|
75
|
+
exports.DEFAULT_COLLECT_LIMITS = {
|
|
76
|
+
hour: 20,
|
|
77
|
+
day: 100,
|
|
78
|
+
};
|
|
79
|
+
exports.MAX_EMOJI_NAME_LENGTH = 64;
|
|
75
80
|
exports.COLLECT_MODES = {
|
|
76
81
|
instant: '立即收集',
|
|
77
82
|
frequency: '频次达标后收集',
|
package/package.json
CHANGED