@zhin.js/plugin-group-suite 3.0.4 → 3.0.6

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.
@@ -0,0 +1,11 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { doCheckin } from "../lib/checkin-lib.js";
5
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
6
+ export default defineCommand({
7
+ description: '每日签到获得积分',
8
+ execute({ config, input, owner, use }) {
9
+ return doCheckin(input ?? {}, resolveGroupSuiteConfig(config), resolveGroupSuiteRuntime({ owner, use }));
10
+ },
11
+ });
@@ -0,0 +1,10 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { teachForget } from "../lib/teach-lib.js";
4
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
5
+ export default defineCommand({
6
+ description: '忘记问答(删除问答对)',
7
+ execute({ input, args, owner, use }) {
8
+ return teachForget(input ?? {}, args.join(' '), resolveGroupSuiteRuntime({ owner, use }));
9
+ },
10
+ });
@@ -0,0 +1,15 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { addKeyword } from "../../lib/keyword-store.js";
4
+ import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
5
+ export default defineCommand({
6
+ description: '添加关键词自动回复',
7
+ execute({ params, args, owner, use }) {
8
+ const keyword = String(params.keyword ?? '');
9
+ const reply = args.join(' ').trim();
10
+ if (!keyword || !reply)
11
+ return '请提供关键词和回复内容';
12
+ addKeyword(keyword, reply, resolveGroupSuiteRuntime({ owner, use })?.keywords);
13
+ return `已添加关键词「${keyword}」→「${reply}」`;
14
+ },
15
+ });
@@ -0,0 +1,14 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { listKeywords } from "../lib/keyword-store.js";
4
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
5
+ export default defineCommand({
6
+ description: '查看所有关键词回复对',
7
+ execute({ owner, use }) {
8
+ const entries = listKeywords(resolveGroupSuiteRuntime({ owner, use })?.keywords);
9
+ if (entries.length === 0)
10
+ return '当前没有设置任何关键词';
11
+ const lines = entries.map(([k, v], i) => `${i + 1}. 「${k}」→「${v}」`);
12
+ return `关键词列表(共 ${entries.length} 条):\n${lines.join('\n')}`;
13
+ },
14
+ });
@@ -0,0 +1,15 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { removeKeyword } from "../../lib/keyword-store.js";
4
+ import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
5
+ export default defineCommand({
6
+ description: '删除关键词自动回复',
7
+ execute({ params, owner, use }) {
8
+ const keyword = String(params.keyword ?? '');
9
+ if (!keyword)
10
+ return '请提供要删除的关键词';
11
+ if (!removeKeyword(keyword, resolveGroupSuiteRuntime({ owner, use })?.keywords))
12
+ return `关键词「${keyword}」不存在`;
13
+ return `已删除关键词「${keyword}」`;
14
+ },
15
+ });
@@ -0,0 +1,10 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { myPoints } from "../lib/checkin-lib.js";
4
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
5
+ export default defineCommand({
6
+ description: '查看个人积分与签到信息',
7
+ execute({ input, owner, use }) {
8
+ return myPoints(input ?? {}, resolveGroupSuiteRuntime({ owner, use }));
9
+ },
10
+ });
@@ -0,0 +1,10 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { myStatsText } from "../lib/stats-lib.js";
4
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
5
+ export default defineCommand({
6
+ description: '查看个人消息统计',
7
+ execute({ input, owner, use }) {
8
+ return myStatsText(input ?? {}, resolveGroupSuiteRuntime({ owner, use }));
9
+ },
10
+ });
@@ -0,0 +1,11 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { pointsRank } from "../lib/checkin-lib.js";
5
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
6
+ export default defineCommand({
7
+ description: '查看积分排行榜',
8
+ execute({ config, input, owner, use }) {
9
+ return pointsRank(input ?? {}, resolveGroupSuiteConfig(config), resolveGroupSuiteRuntime({ owner, use }));
10
+ },
11
+ });
@@ -0,0 +1,13 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { monthStartStr, resolveGroupId, statsRankText } from "../lib/stats-lib.js";
5
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
6
+ export default defineCommand({
7
+ description: '查看本月话唠排行',
8
+ execute({ config, input, owner, use }) {
9
+ const groupId = resolveGroupId(input ?? {});
10
+ const title = groupId ? '本月话唠排行' : '全局话唠排行';
11
+ return statsRankText(input ?? {}, resolveGroupSuiteConfig(config), monthStartStr(), title, resolveGroupSuiteRuntime({ owner, use }));
12
+ },
13
+ });
@@ -0,0 +1,13 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { resolveGroupId, statsRankText, weekStartStr } from "../lib/stats-lib.js";
5
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
6
+ export default defineCommand({
7
+ description: '查看本周消息统计',
8
+ execute({ config, input, owner, use }) {
9
+ const groupId = resolveGroupId(input ?? {});
10
+ const title = groupId ? '本周本群消息统计' : '本周全局消息统计';
11
+ return statsRankText(input ?? {}, resolveGroupSuiteConfig(config), weekStartStr(), title, resolveGroupSuiteRuntime({ owner, use }));
12
+ },
13
+ });
@@ -0,0 +1,14 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { todayStr } from "../lib/shared-runtime.js";
5
+ import { resolveGroupId, statsRankText } from "../lib/stats-lib.js";
6
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
7
+ export default defineCommand({
8
+ description: '查看今日消息统计',
9
+ execute({ config, input, owner, use }) {
10
+ const groupId = resolveGroupId(input ?? {});
11
+ const title = groupId ? '今日本群消息统计' : '今日全局消息统计';
12
+ return statsRankText(input ?? {}, resolveGroupSuiteConfig(config), todayStr(), title, resolveGroupSuiteRuntime({ owner, use }));
13
+ },
14
+ });
@@ -0,0 +1,12 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { resolveGroupSuiteConfig } from "../../lib/config.js";
4
+ import { teachList } from "../../lib/teach-lib.js";
5
+ import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
6
+ export default defineCommand({
7
+ description: '查看问答列表',
8
+ execute({ config, input, params, owner, use }) {
9
+ const page = Number(params.page ?? 1);
10
+ return teachList(input ?? {}, resolveGroupSuiteConfig(config), page, resolveGroupSuiteRuntime({ owner, use }));
11
+ },
12
+ });
@@ -0,0 +1,11 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { teachAdd } from "../lib/teach-lib.js";
5
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
6
+ export default defineCommand({
7
+ description: '教我正则问答',
8
+ execute({ config, input, args, owner, use }) {
9
+ return teachAdd(input ?? {}, resolveGroupSuiteConfig(config), args.join(' '), true, resolveGroupSuiteRuntime({ owner, use }));
10
+ },
11
+ });
@@ -0,0 +1,11 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineCommand } from '@zhin.js/command';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { teachAdd } from "../lib/teach-lib.js";
5
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
6
+ export default defineCommand({
7
+ description: '教我问答(teach 问题 回答 或 问题|答案)',
8
+ execute({ config, input, args, owner, use }) {
9
+ return teachAdd(input ?? {}, resolveGroupSuiteConfig(config), args.join(' '), false, resolveGroupSuiteRuntime({ owner, use }));
10
+ },
11
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"checkin-lib.d.ts","sourceRoot":"","sources":["../src/checkin-lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAUpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAsC5D,wBAAsB,SAAS,CAC7B,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,EACzF,GAAG,EAAE,gBAAgB,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAyCjB;AAED,wBAAsB,QAAQ,CAC5B,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,EACzF,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,EACzF,GAAG,EAAE,gBAAgB,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAsBjB"}
1
+ {"version":3,"file":"checkin-lib.d.ts","sourceRoot":"","sources":["../src/checkin-lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAUpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAqD5D,wBAAsB,SAAS,CAC7B,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,EACzF,GAAG,EAAE,gBAAgB,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA2CjB;AAED,wBAAsB,QAAQ,CAC5B,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,EACzF,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED,wBAAsB,UAAU,CAC9B,KAAK,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,EACzF,GAAG,EAAE,gBAAgB,EACrB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAsBjB"}
@@ -28,6 +28,20 @@ async function getOrCreateUser(model, userId, userName, ctxType, ctxId) {
28
28
  }));
29
29
  return created[0] ?? null;
30
30
  }
31
+ /**
32
+ * 同一 user_id+context 的签到串行化(per-user promise 链),
33
+ * 避免 check-then-act 竞态导致连发两条都签到成功。
34
+ */
35
+ const checkinChains = new Map();
36
+ function serializedCheckin(key, task) {
37
+ const prev = checkinChains.get(key) ?? Promise.resolve();
38
+ const next = prev.then(task, task);
39
+ checkinChains.set(key, next);
40
+ return next.finally(() => {
41
+ if (checkinChains.get(key) === next)
42
+ checkinChains.delete(key);
43
+ });
44
+ }
31
45
  export async function doCheckin(input, cfg, runtime) {
32
46
  const M = getCheckinModel(runtime?.db);
33
47
  if (!M)
@@ -36,37 +50,39 @@ export async function doCheckin(input, cfg, runtime) {
36
50
  if (!userId)
37
51
  return '无法获取用户信息';
38
52
  const { type: ctxType, id: ctxId } = resolveContextKey(input);
39
- const user = await getOrCreateUser(M, userId, userName, ctxType, ctxId);
40
- if (!user)
41
- return '签到失败,请重试';
42
- const today = todayStr();
43
- if (user.last_checkin === today) {
44
- return `你今天已经签到过了哦~\n当前积分: ${user.points}\n连续签到: ${user.streak} 天`;
45
- }
46
- const isConsecutive = user.last_checkin === yesterdayStr();
47
- const newStreak = isConsecutive ? Number(user.streak) + 1 : 1;
48
- const base = randomInt(cfg.basePointsMin, cfg.basePointsMax);
49
- const bonus = Math.min(newStreak * cfg.streakBonus, cfg.streakCap);
50
- const earned = base + bonus;
51
- const newPoints = Number(user.points || 0) + earned;
52
- await M.update({
53
- points: newPoints,
54
- total_checkins: Number(user.total_checkins || 0) + 1,
55
- streak: newStreak,
56
- max_streak: Math.max(Number(user.max_streak || 0), newStreak),
57
- last_checkin: today,
58
- user_name: userName,
59
- updated_at: ts(),
60
- }).where({
61
- user_id: userId,
62
- context_type: ctxType,
63
- context_id: ctxId,
53
+ return serializedCheckin(`${userId}:${ctxType}:${ctxId}`, async () => {
54
+ const user = await getOrCreateUser(M, userId, userName, ctxType, ctxId);
55
+ if (!user)
56
+ return '签到失败,请重试';
57
+ const today = todayStr();
58
+ if (user.last_checkin === today) {
59
+ return `你今天已经签到过了哦~\n当前积分: ${user.points}\n连续签到: ${user.streak} 天`;
60
+ }
61
+ const isConsecutive = user.last_checkin === yesterdayStr();
62
+ const newStreak = isConsecutive ? Number(user.streak) + 1 : 1;
63
+ const base = randomInt(cfg.basePointsMin, cfg.basePointsMax);
64
+ const bonus = Math.min(newStreak * cfg.streakBonus, cfg.streakCap);
65
+ const earned = base + bonus;
66
+ const newPoints = Number(user.points || 0) + earned;
67
+ await M.update({
68
+ points: newPoints,
69
+ total_checkins: Number(user.total_checkins || 0) + 1,
70
+ streak: newStreak,
71
+ max_streak: Math.max(Number(user.max_streak || 0), newStreak),
72
+ last_checkin: today,
73
+ user_name: userName,
74
+ updated_at: ts(),
75
+ }).where({
76
+ user_id: userId,
77
+ context_type: ctxType,
78
+ context_id: ctxId,
79
+ });
80
+ const lines = [`签到成功!`, `基础积分: +${base}`];
81
+ if (bonus > 0)
82
+ lines.push(`连续奖励: +${bonus} (连续${newStreak}天)`);
83
+ lines.push(`本次获得: +${earned}`, `当前积分: ${newPoints}`);
84
+ return lines.join('\n');
64
85
  });
65
- const lines = [`签到成功!`, `基础积分: +${base}`];
66
- if (bonus > 0)
67
- lines.push(`连续奖励: +${bonus} (连续${newStreak}天)`);
68
- lines.push(`本次获得: +${earned}`, `当前积分: ${newPoints}`);
69
- return lines.join('\n');
70
86
  }
71
87
  export async function myPoints(input, runtime) {
72
88
  const M = getCheckinModel(runtime?.db);
@@ -1 +1 @@
1
- {"version":3,"file":"checkin-lib.js","sourceRoot":"","sources":["../src/checkin-lib.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkin-lib.js","sourceRoot":"","sources":["../src/checkin-lib.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"stats-lib.d.ts","sourceRoot":"","sources":["../src/stats-lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAapD,OAAO,KAAK,EAAE,iBAAiB,EAAyB,MAAM,oBAAoB,CAAC;AAEnF,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAGtC;AAQD,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C,GAAG,MAAM,CAUT;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAmBpC;AAED,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCjF;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAsBvD;AAED,KAAK,YAAY,GAAG;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C,CAAC;AAEF,wBAAsB,aAAa,CACjC,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmCnG;AAED,kBAAkB;AAClB,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
1
+ {"version":3,"file":"stats-lib.d.ts","sourceRoot":"","sources":["../src/stats-lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAapD,OAAO,KAAK,EAAE,iBAAiB,EAAyB,MAAM,oBAAoB,CAAC;AAEnF,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAGtC;AAQD,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C,GAAG,MAAM,CAUT;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAmBpC;AAED,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCjF;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAsBvD;AAED,KAAK,YAAY,GAAG;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C,CAAC;AAEF,wBAAsB,aAAa,CACjC,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,gBAAgB,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmCnG;AAED,kBAAkB;AAClB,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
package/lib/stats-lib.js CHANGED
@@ -53,9 +53,9 @@ export async function flushStatsBuffer(runtime) {
53
53
  const M = getStatsModel(runtime?.db);
54
54
  if (!M || targetBuffer.size === 0)
55
55
  return;
56
- const entries = [...targetBuffer.values()];
57
- targetBuffer.clear();
58
- for (const entry of entries) {
56
+ for (const [key, entry] of [...targetBuffer.entries()]) {
57
+ // 快照本次要落库的计数;flush 期间新累计的部分留在缓冲
58
+ const countSnapshot = entry.count;
59
59
  try {
60
60
  const existing = (await M.select().where({
61
61
  user_id: entry.user_id,
@@ -64,7 +64,7 @@ export async function flushStatsBuffer(runtime) {
64
64
  }));
65
65
  if (existing.length > 0) {
66
66
  await M.update({
67
- count: Number(existing[0].count || 0) + entry.count,
67
+ count: Number(existing[0].count || 0) + countSnapshot,
68
68
  user_name: entry.user_name,
69
69
  updated_at: ts(),
70
70
  }).where({
@@ -79,13 +79,17 @@ export async function flushStatsBuffer(runtime) {
79
79
  user_name: entry.user_name,
80
80
  group_id: entry.group_id,
81
81
  date: entry.date,
82
- count: entry.count,
82
+ count: countSnapshot,
83
83
  updated_at: ts(),
84
84
  });
85
85
  }
86
+ // 只移除写入成功的部分;失败的 key 留在缓冲等下一轮重试
87
+ entry.count -= countSnapshot;
88
+ if (entry.count <= 0 && targetBuffer.get(key) === entry)
89
+ targetBuffer.delete(key);
86
90
  }
87
91
  catch {
88
- /* single row failure */
92
+ /* single row failure: keep entry in buffer for next flush */
89
93
  }
90
94
  }
91
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stats-lib.js","sourceRoot":"","sources":["../src/stats-lib.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stats-lib.js","sourceRoot":"","sources":["../src/stats-lib.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineMiddleware } from '@zhin.js/middleware';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { matchKeyword } from "../lib/keyword-store.js";
5
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
6
+ /**
7
+ * Keyword auto-reply (enabled via config.keywordReply).
8
+ * Uses Runtime Message.content / metadata (legacy used $raw / $channel).
9
+ */
10
+ export default defineMiddleware({
11
+ target: 'inbound',
12
+ async handle(context, next) {
13
+ const config = resolveGroupSuiteConfig(context.config);
14
+ if (!config.keywordReply) {
15
+ await next();
16
+ return;
17
+ }
18
+ const meta = context.input.metadata ?? {};
19
+ const channelType = String(meta.type ?? meta.channelType ?? '');
20
+ if (channelType === 'private') {
21
+ await next();
22
+ return;
23
+ }
24
+ const text = typeof context.input.content === 'string' ? context.input.content.trim() : '';
25
+ if (!text) {
26
+ await next();
27
+ return;
28
+ }
29
+ const reply = matchKeyword(text, resolveGroupSuiteRuntime(context)?.keywords);
30
+ if (reply) {
31
+ await context.input.$reply(reply);
32
+ return;
33
+ }
34
+ await next();
35
+ },
36
+ });
@@ -0,0 +1,20 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineMiddleware } from '@zhin.js/middleware';
3
+ import { recordMessage } from "../lib/stats-lib.js";
4
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
5
+ /**
6
+ * Buffer inbound messages into in-memory message_stats (flushed on query).
7
+ * Skips command messages (legacy used `isActionMessage` to skip interactive
8
+ * action/command messages; the Runtime pipeline represents commands as
9
+ * text starting with the dispatcher prefix '/').
10
+ */
11
+ export default defineMiddleware({
12
+ target: 'inbound',
13
+ async handle(context, next) {
14
+ const content = typeof context.input.content === 'string' ? context.input.content : '';
15
+ if (!content.startsWith('/')) {
16
+ recordMessage(context.input, resolveGroupSuiteRuntime(context));
17
+ }
18
+ await next();
19
+ },
20
+ });
@@ -0,0 +1,21 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineMiddleware } from '@zhin.js/middleware';
3
+ import { resolveGroupSuiteConfig } from "../lib/config.js";
4
+ import { tryTeachReply } from "../lib/teach-lib.js";
5
+ import { resolveGroupSuiteRuntime } from "../lib/runtime-state.js";
6
+ /**
7
+ * Teach Q&A auto-reply (exact / optional regex).
8
+ * Uses Runtime Message.content / metadata.
9
+ */
10
+ export default defineMiddleware({
11
+ target: 'inbound',
12
+ async handle(context, next) {
13
+ const config = resolveGroupSuiteConfig(context.config);
14
+ const reply = await tryTeachReply(context.input, config, resolveGroupSuiteRuntime(context));
15
+ if (reply) {
16
+ await context.input.$reply(reply);
17
+ return;
18
+ }
19
+ await next();
20
+ },
21
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-group-suite",
3
- "version": "3.0.4",
3
+ "version": "3.0.6",
4
4
  "description": "Zhin.js 群运营套件 — slice-2 checkin/teach/stats + keywords (Plugin Runtime, in-memory)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -14,7 +14,7 @@
14
14
  "./package.json": "./package.json"
15
15
  },
16
16
  "files": [
17
- "plugin.ts",
17
+ "plugin.js",
18
18
  "schema.json",
19
19
  "commands",
20
20
  "middlewares",
@@ -41,22 +41,22 @@
41
41
  },
42
42
  "license": "MIT",
43
43
  "dependencies": {
44
- "@zhin.js/command": "1.0.2",
45
- "@zhin.js/core": "1.4.0",
46
- "@zhin.js/middleware": "1.0.2",
47
- "@zhin.js/plugin-runtime": "1.1.0",
48
- "@zhin.js/satori": "1.0.16"
44
+ "@zhin.js/command": "1.0.4",
45
+ "@zhin.js/core": "1.4.2",
46
+ "@zhin.js/middleware": "1.0.4",
47
+ "@zhin.js/plugin-runtime": "1.1.1",
48
+ "@zhin.js/satori": "1.0.17"
49
49
  },
50
50
  "devDependencies": {
51
51
  "typescript": "^6.0.3",
52
52
  "vitest": "^4.1.10",
53
53
  "zod": "^4.4.3",
54
- "@zhin.js/agent": "1.0.5",
55
- "zhin.js": "5.0.0"
54
+ "@zhin.js/agent": "1.0.7",
55
+ "zhin.js": "5.0.2"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "zod": "^4.0.0",
59
- "@zhin.js/agent": "1.0.5"
59
+ "@zhin.js/agent": "1.0.7"
60
60
  },
61
61
  "peerDependenciesMeta": {
62
62
  "@zhin.js/agent": {
@@ -81,7 +81,7 @@
81
81
  "zhin": {
82
82
  "protocol": 1,
83
83
  "type": "plugin",
84
- "entry": "./plugin.ts",
84
+ "entry": "./plugin.js",
85
85
  "engine": "^1.0.0",
86
86
  "runtime": "trusted",
87
87
  "features": [
package/plugin.js ADDED
@@ -0,0 +1,37 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { definePlugin, databaseHostToken } from '@zhin.js/plugin-runtime';
3
+ import { registerGroupSuiteDb } from "./lib/db-store.js";
4
+ import { createInMemoryGroupSuiteDb } from "./lib/memory-store.js";
5
+ import { createGroupSuiteRuntime, groupSuiteRuntimeToken } from "./lib/runtime-state.js";
6
+ import { flushStatsBuffer } from "./lib/stats-lib.js";
7
+ import { defineGroupSuiteTables } from "./lib/tables.js";
8
+ /**
9
+ * Plugin Runtime:
10
+ * - checkin / teach / stats commands + keyword middleware
11
+ * - DB: prefer `databaseHostToken`; else in-memory fallback
12
+ * - Stats buffer: periodic flush every 10s + final flush on dispose
13
+ */
14
+ export default definePlugin({
15
+ name: 'group-suite',
16
+ metadata: {
17
+ displayName: 'Group Suite',
18
+ },
19
+ setup(context) {
20
+ const db = context.resources.has(databaseHostToken)
21
+ ? context.resources.use(databaseHostToken)
22
+ : createInMemoryGroupSuiteDb();
23
+ if (context.resources.has(databaseHostToken)) {
24
+ defineGroupSuiteTables(db);
25
+ }
26
+ const runtime = createGroupSuiteRuntime(db);
27
+ context.resources.provide(groupSuiteRuntimeToken, runtime);
28
+ context.lifecycle.add(registerGroupSuiteDb(db));
29
+ const flushTimer = setInterval(() => {
30
+ void flushStatsBuffer(runtime);
31
+ }, 10_000);
32
+ context.lifecycle.add(async () => {
33
+ clearInterval(flushTimer);
34
+ await flushStatsBuffer(runtime);
35
+ });
36
+ },
37
+ });
@@ -46,6 +46,21 @@ async function getOrCreateUser(
46
46
  return created[0] ?? null;
47
47
  }
48
48
 
49
+ /**
50
+ * 同一 user_id+context 的签到串行化(per-user promise 链),
51
+ * 避免 check-then-act 竞态导致连发两条都签到成功。
52
+ */
53
+ const checkinChains = new Map<string, Promise<unknown>>();
54
+
55
+ function serializedCheckin<T>(key: string, task: () => Promise<T>): Promise<T> {
56
+ const prev = checkinChains.get(key) ?? Promise.resolve();
57
+ const next = prev.then(task, task);
58
+ checkinChains.set(key, next);
59
+ return next.finally(() => {
60
+ if (checkinChains.get(key) === next) checkinChains.delete(key);
61
+ });
62
+ }
63
+
49
64
  export async function doCheckin(
50
65
  input: { sender?: string; target?: string; metadata?: Readonly<Record<string, unknown>> },
51
66
  cfg: GroupSuiteConfig,
@@ -58,39 +73,41 @@ export async function doCheckin(
58
73
  if (!userId) return '无法获取用户信息';
59
74
 
60
75
  const { type: ctxType, id: ctxId } = resolveContextKey(input);
61
- const user = await getOrCreateUser(M, userId, userName, ctxType, ctxId);
62
- if (!user) return '签到失败,请重试';
76
+ return serializedCheckin(`${userId}:${ctxType}:${ctxId}`, async () => {
77
+ const user = await getOrCreateUser(M, userId, userName, ctxType, ctxId);
78
+ if (!user) return '签到失败,请重试';
63
79
 
64
- const today = todayStr();
65
- if (user.last_checkin === today) {
66
- return `你今天已经签到过了哦~\n当前积分: ${user.points}\n连续签到: ${user.streak} 天`;
67
- }
80
+ const today = todayStr();
81
+ if (user.last_checkin === today) {
82
+ return `你今天已经签到过了哦~\n当前积分: ${user.points}\n连续签到: ${user.streak} 天`;
83
+ }
68
84
 
69
- const isConsecutive = user.last_checkin === yesterdayStr();
70
- const newStreak = isConsecutive ? Number(user.streak) + 1 : 1;
71
- const base = randomInt(cfg.basePointsMin, cfg.basePointsMax);
72
- const bonus = Math.min(newStreak * cfg.streakBonus, cfg.streakCap);
73
- const earned = base + bonus;
74
- const newPoints = Number(user.points || 0) + earned;
85
+ const isConsecutive = user.last_checkin === yesterdayStr();
86
+ const newStreak = isConsecutive ? Number(user.streak) + 1 : 1;
87
+ const base = randomInt(cfg.basePointsMin, cfg.basePointsMax);
88
+ const bonus = Math.min(newStreak * cfg.streakBonus, cfg.streakCap);
89
+ const earned = base + bonus;
90
+ const newPoints = Number(user.points || 0) + earned;
75
91
 
76
- await M.update({
77
- points: newPoints,
78
- total_checkins: Number(user.total_checkins || 0) + 1,
79
- streak: newStreak,
80
- max_streak: Math.max(Number(user.max_streak || 0), newStreak),
81
- last_checkin: today,
82
- user_name: userName,
83
- updated_at: ts(),
84
- }).where({
85
- user_id: userId,
86
- context_type: ctxType,
87
- context_id: ctxId,
88
- });
92
+ await M.update({
93
+ points: newPoints,
94
+ total_checkins: Number(user.total_checkins || 0) + 1,
95
+ streak: newStreak,
96
+ max_streak: Math.max(Number(user.max_streak || 0), newStreak),
97
+ last_checkin: today,
98
+ user_name: userName,
99
+ updated_at: ts(),
100
+ }).where({
101
+ user_id: userId,
102
+ context_type: ctxType,
103
+ context_id: ctxId,
104
+ });
89
105
 
90
- const lines = [`签到成功!`, `基础积分: +${base}`];
91
- if (bonus > 0) lines.push(`连续奖励: +${bonus} (连续${newStreak}天)`);
92
- lines.push(`本次获得: +${earned}`, `当前积分: ${newPoints}`);
93
- return lines.join('\n');
106
+ const lines = [`签到成功!`, `基础积分: +${base}`];
107
+ if (bonus > 0) lines.push(`连续奖励: +${bonus} (连续${newStreak}天)`);
108
+ lines.push(`本次获得: +${earned}`, `当前积分: ${newPoints}`);
109
+ return lines.join('\n');
110
+ });
94
111
  }
95
112
 
96
113
  export async function myPoints(
package/src/stats-lib.ts CHANGED
@@ -75,9 +75,9 @@ export async function flushStatsBuffer(runtime?: GroupSuiteRuntime): Promise<voi
75
75
  const targetBuffer = runtime?.statsBuffer ?? buffer;
76
76
  const M = getStatsModel(runtime?.db);
77
77
  if (!M || targetBuffer.size === 0) return;
78
- const entries = [...targetBuffer.values()];
79
- targetBuffer.clear();
80
- for (const entry of entries) {
78
+ for (const [key, entry] of [...targetBuffer.entries()]) {
79
+ // 快照本次要落库的计数;flush 期间新累计的部分留在缓冲
80
+ const countSnapshot = entry.count;
81
81
  try {
82
82
  const existing = (await M.select().where({
83
83
  user_id: entry.user_id,
@@ -86,7 +86,7 @@ export async function flushStatsBuffer(runtime?: GroupSuiteRuntime): Promise<voi
86
86
  })) as Record<string, unknown>[];
87
87
  if (existing.length > 0) {
88
88
  await M.update({
89
- count: Number(existing[0]!.count || 0) + entry.count,
89
+ count: Number(existing[0]!.count || 0) + countSnapshot,
90
90
  user_name: entry.user_name,
91
91
  updated_at: ts(),
92
92
  }).where({
@@ -100,12 +100,15 @@ export async function flushStatsBuffer(runtime?: GroupSuiteRuntime): Promise<voi
100
100
  user_name: entry.user_name,
101
101
  group_id: entry.group_id,
102
102
  date: entry.date,
103
- count: entry.count,
103
+ count: countSnapshot,
104
104
  updated_at: ts(),
105
105
  });
106
106
  }
107
+ // 只移除写入成功的部分;失败的 key 留在缓冲等下一轮重试
108
+ entry.count -= countSnapshot;
109
+ if (entry.count <= 0 && targetBuffer.get(key) === entry) targetBuffer.delete(key);
107
110
  } catch {
108
- /* single row failure */
111
+ /* single row failure: keep entry in buffer for next flush */
109
112
  }
110
113
  }
111
114
  }
@@ -0,0 +1,22 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { getCheckinModel } from "../../lib/db-store.js";
3
+ import { todayStr } from "../../lib/shared-runtime.js";
4
+ export default async function (args) {
5
+ const M = getCheckinModel();
6
+ if (!M)
7
+ return '签到数据库尚未就绪';
8
+ const userId = args.user_id;
9
+ if (userId) {
10
+ const rows = await M.select().where({ user_id: userId });
11
+ if (rows.length === 0)
12
+ return `用户 ${userId} 没有签到记录`;
13
+ const u = rows[0];
14
+ return `${u.user_name}: 积分=${u.points}, 累计=${u.total_checkins}天, 连续=${u.streak}天, 最长=${u.max_streak}天, 上次=${u.last_checkin}`;
15
+ }
16
+ const all = await M.select();
17
+ const totalUsers = all.length;
18
+ const totalPoints = all.reduce((s, u) => s + (u.points || 0), 0);
19
+ const today = todayStr();
20
+ const todayCount = all.filter((u) => u.last_checkin === today).length;
21
+ return `签到系统统计\n总用户: ${totalUsers}\n总积分: ${totalPoints}\n今日签到: ${todayCount}人`;
22
+ }
@@ -0,0 +1,15 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { getCheckinModel } from "../../lib/db-store.js";
3
+ export default async function (args) {
4
+ const M = getCheckinModel();
5
+ if (!M)
6
+ return '签到数据库尚未就绪';
7
+ const limit = Math.min(Math.max(Number(args.limit) || 10, 1), 50);
8
+ const all = await M.select();
9
+ const sorted = all.sort((a, b) => (b.points || 0) - (a.points || 0)).slice(0, limit);
10
+ if (sorted.length === 0)
11
+ return '暂无排行数据';
12
+ return sorted
13
+ .map((u, i) => `${i + 1}. ${u.user_name || u.user_id} — ${u.points}分 (连续${u.streak}天)`)
14
+ .join('\n');
15
+ }
@@ -0,0 +1,28 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { flushStatsBuffer, queryStats, weekStartStr, monthStartStr, } from "../../lib/stats-lib.js";
3
+ import { todayStr } from "../../lib/shared-runtime.js";
4
+ export default async function (args) {
5
+ await flushStatsBuffer();
6
+ const groupId = args.group_id || '';
7
+ const period = args.period || 'today';
8
+ let fromDate;
9
+ switch (period) {
10
+ case 'week':
11
+ fromDate = weekStartStr();
12
+ break;
13
+ case 'month':
14
+ fromDate = monthStartStr();
15
+ break;
16
+ default:
17
+ fromDate = todayStr();
18
+ break;
19
+ }
20
+ const stats = await queryStats(groupId, fromDate);
21
+ if (stats.size === 0)
22
+ return `${period} 暂无消息统计数据`;
23
+ const sorted = [...stats.entries()].sort((a, b) => b[1].count - a[1].count);
24
+ const total = sorted.reduce((s, [, v]) => s + v.count, 0);
25
+ const top10 = sorted.slice(0, 10);
26
+ const lines = top10.map(([, v], i) => `${i + 1}. ${v.name} — ${v.count}条`);
27
+ return `消息统计 (${period})\n总消息: ${total}条, 活跃用户: ${stats.size}人\n${lines.join('\n')}`;
28
+ }
@@ -0,0 +1,29 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { flushStatsBuffer, weekStartStr } from "../../lib/stats-lib.js";
3
+ import { getStatsModel } from "../../lib/db-store.js";
4
+ import { todayStr } from "../../lib/shared-runtime.js";
5
+ export default async function (args) {
6
+ await flushStatsBuffer();
7
+ const M = getStatsModel();
8
+ if (!M)
9
+ return '统计数据库尚未就绪';
10
+ const userId = args.user_id;
11
+ if (!userId)
12
+ return '请提供用户ID';
13
+ const rows = await M.select().where({ user_id: userId });
14
+ if (rows.length === 0)
15
+ return `用户 ${userId} 暂无消息记录`;
16
+ const today = todayStr();
17
+ const weekStart = weekStartStr();
18
+ let todayCount = 0, weekCount = 0, totalCount = 0;
19
+ for (const row of rows) {
20
+ const c = row.count || 0;
21
+ totalCount += c;
22
+ if (row.date >= weekStart)
23
+ weekCount += c;
24
+ if (row.date === today)
25
+ todayCount += c;
26
+ }
27
+ const name = rows[0].user_name || userId;
28
+ return `${name} 的统计\n今日: ${todayCount}条\n本周: ${weekCount}条\n总计: ${totalCount}条\n活跃天数: ${rows.length}天`;
29
+ }
package/plugin.ts DELETED
@@ -1,39 +0,0 @@
1
- import { definePlugin, databaseHostToken } from '@zhin.js/plugin-runtime';
2
- import type { GroupSuiteConfig } from './src/config.js';
3
- import { registerGroupSuiteDb } from './src/db-store.js';
4
- import { createInMemoryGroupSuiteDb } from './src/memory-store.js';
5
- import { createGroupSuiteRuntime, groupSuiteRuntimeToken } from './src/runtime-state.js';
6
- import { flushStatsBuffer } from './src/stats-lib.js';
7
- import { defineGroupSuiteTables } from './src/tables.js';
8
-
9
- /**
10
- * Plugin Runtime:
11
- * - checkin / teach / stats commands + keyword middleware
12
- * - DB: prefer `databaseHostToken`; else in-memory fallback
13
- * - Stats buffer: periodic flush every 10s + final flush on dispose
14
- */
15
- export default definePlugin<GroupSuiteConfig>({
16
- name: 'group-suite',
17
- metadata: {
18
- displayName: 'Group Suite',
19
- },
20
- setup(context) {
21
- const db = context.resources.has(databaseHostToken)
22
- ? context.resources.use(databaseHostToken)
23
- : createInMemoryGroupSuiteDb();
24
- if (context.resources.has(databaseHostToken)) {
25
- defineGroupSuiteTables(db);
26
- }
27
- const runtime = createGroupSuiteRuntime(db);
28
- context.resources.provide(groupSuiteRuntimeToken, runtime);
29
- context.lifecycle.add(registerGroupSuiteDb(db));
30
-
31
- const flushTimer = setInterval(() => {
32
- void flushStatsBuffer(runtime);
33
- }, 10_000);
34
- context.lifecycle.add(async () => {
35
- clearInterval(flushTimer);
36
- await flushStatsBuffer(runtime);
37
- });
38
- },
39
- });