@zhin.js/plugin-group-suite 1.0.1 → 1.1.2

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.
Files changed (143) hide show
  1. package/README.md +42 -58
  2. package/commands/checkin/index.js +11 -0
  3. package/commands/checkin/index.ts +12 -0
  4. package/commands/forget/index.js +10 -0
  5. package/commands/forget/index.ts +12 -0
  6. package/commands/keyword-add/[keyword]/index.js +16 -0
  7. package/commands/keyword-add/[keyword]/index.ts +16 -0
  8. package/commands/keyword-list/index.js +14 -0
  9. package/commands/keyword-list/index.ts +14 -0
  10. package/commands/keyword-remove/[keyword]/index.js +16 -0
  11. package/commands/keyword-remove/[keyword]/index.ts +15 -0
  12. package/commands/mypoints/index.js +10 -0
  13. package/commands/mypoints/index.ts +12 -0
  14. package/commands/mystats/index.js +10 -0
  15. package/commands/mystats/index.ts +12 -0
  16. package/commands/rank/index.js +11 -0
  17. package/commands/rank/index.ts +12 -0
  18. package/commands/stats/index.js +14 -0
  19. package/commands/stats/index.ts +21 -0
  20. package/commands/stats-rank/index.js +13 -0
  21. package/commands/stats-rank/index.ts +20 -0
  22. package/commands/stats-week/index.js +13 -0
  23. package/commands/stats-week/index.ts +20 -0
  24. package/commands/teach/index.js +11 -0
  25. package/commands/teach/index.ts +12 -0
  26. package/commands/teach-list/[[page]]/index.js +13 -0
  27. package/commands/teach-list/[[page]]/index.ts +14 -0
  28. package/commands/teach-regex/index.js +11 -0
  29. package/commands/teach-regex/index.ts +12 -0
  30. package/lib/checkin-lib.d.ts +27 -0
  31. package/lib/checkin-lib.d.ts.map +1 -0
  32. package/lib/checkin-lib.js +133 -0
  33. package/lib/checkin-lib.js.map +1 -0
  34. package/lib/config.d.ts +4 -57
  35. package/lib/config.d.ts.map +1 -1
  36. package/lib/config.js +18 -40
  37. package/lib/config.js.map +1 -1
  38. package/lib/db-store.d.ts +5 -0
  39. package/lib/db-store.d.ts.map +1 -0
  40. package/lib/db-store.js +11 -0
  41. package/lib/db-store.js.map +1 -0
  42. package/lib/index.d.ts +9 -1
  43. package/lib/index.d.ts.map +1 -1
  44. package/lib/index.js +7 -29
  45. package/lib/index.js.map +1 -1
  46. package/lib/keyword-store.d.ts +5 -0
  47. package/lib/keyword-store.d.ts.map +1 -0
  48. package/lib/keyword-store.js +17 -0
  49. package/lib/keyword-store.js.map +1 -0
  50. package/lib/memory-store.d.ts +31 -0
  51. package/lib/memory-store.d.ts.map +1 -0
  52. package/lib/memory-store.js +63 -0
  53. package/lib/memory-store.js.map +1 -0
  54. package/lib/runtime-state.d.ts +24 -0
  55. package/lib/runtime-state.d.ts.map +1 -0
  56. package/lib/runtime-state.js +15 -0
  57. package/lib/runtime-state.js.map +1 -0
  58. package/lib/shared-runtime.d.ts +26 -0
  59. package/lib/shared-runtime.d.ts.map +1 -0
  60. package/lib/shared-runtime.js +34 -0
  61. package/lib/shared-runtime.js.map +1 -0
  62. package/lib/stats-lib.d.ts +39 -0
  63. package/lib/stats-lib.d.ts.map +1 -0
  64. package/lib/stats-lib.js +172 -0
  65. package/lib/stats-lib.js.map +1 -0
  66. package/lib/tables.d.ts +4 -0
  67. package/lib/tables.d.ts.map +1 -0
  68. package/lib/tables.js +40 -0
  69. package/lib/tables.js.map +1 -0
  70. package/lib/teach-lib.d.ts +23 -0
  71. package/lib/teach-lib.d.ts.map +1 -0
  72. package/lib/teach-lib.js +228 -0
  73. package/lib/teach-lib.js.map +1 -0
  74. package/middlewares/keyword-reply/index.js +36 -0
  75. package/middlewares/keyword-reply/index.ts +37 -0
  76. package/middlewares/stats-count/index.js +20 -0
  77. package/middlewares/stats-count/index.ts +22 -0
  78. package/middlewares/teach-reply/index.js +21 -0
  79. package/middlewares/teach-reply/index.ts +22 -0
  80. package/package.json +57 -14
  81. package/plugin.js +38 -0
  82. package/schema.json +17 -0
  83. package/skills/checkin/tools/checkin_query/index.js +42 -0
  84. package/skills/checkin/tools/checkin_query/index.ts +41 -0
  85. package/skills/checkin/tools/checkin_rank/index.js +34 -0
  86. package/skills/checkin/tools/checkin_rank/index.ts +34 -0
  87. package/skills/group-daily-analysis/SKILL.md +11 -4
  88. package/skills/group-daily-analysis/tools/group_announce/index.js +14 -0
  89. package/skills/group-daily-analysis/tools/group_announce/index.ts +14 -0
  90. package/skills/group-daily-analysis/tools/stats_query/index.js +35 -0
  91. package/skills/group-daily-analysis/tools/stats_query/index.ts +36 -0
  92. package/skills/group-daily-analysis/tools/stats_user/index.js +50 -0
  93. package/skills/group-daily-analysis/tools/stats_user/index.ts +46 -0
  94. package/src/checkin-lib.ts +167 -0
  95. package/src/config.ts +23 -57
  96. package/src/db-store.ts +19 -0
  97. package/src/index.ts +39 -33
  98. package/src/keyword-store.ts +18 -0
  99. package/src/memory-store.ts +90 -0
  100. package/src/runtime-state.ts +41 -0
  101. package/src/shared-runtime.ts +44 -0
  102. package/src/stats-lib.ts +198 -0
  103. package/src/tables.ts +46 -0
  104. package/src/teach-lib.ts +294 -0
  105. package/lib/admin.d.ts +0 -4
  106. package/lib/admin.d.ts.map +0 -1
  107. package/lib/admin.js +0 -123
  108. package/lib/admin.js.map +0 -1
  109. package/lib/checkin.d.ts +0 -5
  110. package/lib/checkin.d.ts.map +0 -1
  111. package/lib/checkin.js +0 -168
  112. package/lib/checkin.js.map +0 -1
  113. package/lib/daily-analysis.d.ts +0 -7
  114. package/lib/daily-analysis.d.ts.map +0 -1
  115. package/lib/daily-analysis.js +0 -334
  116. package/lib/daily-analysis.js.map +0 -1
  117. package/lib/shared.d.ts +0 -25
  118. package/lib/shared.d.ts.map +0 -1
  119. package/lib/shared.js +0 -40
  120. package/lib/shared.js.map +0 -1
  121. package/lib/stats.d.ts +0 -12
  122. package/lib/stats.d.ts.map +0 -1
  123. package/lib/stats.js +0 -256
  124. package/lib/stats.js.map +0 -1
  125. package/lib/teach.d.ts +0 -4
  126. package/lib/teach.d.ts.map +0 -1
  127. package/lib/teach.js +0 -294
  128. package/lib/teach.js.map +0 -1
  129. package/plugin.yml +0 -3
  130. package/src/admin.ts +0 -145
  131. package/src/checkin.ts +0 -196
  132. package/src/daily-analysis.ts +0 -458
  133. package/src/shared.ts +0 -51
  134. package/src/stats.ts +0 -297
  135. package/src/teach.ts +0 -307
  136. package/tools/checkin-query/checkin-query.tool.md +0 -11
  137. package/tools/checkin-query/handler.ts +0 -22
  138. package/tools/checkin-rank/checkin-rank.tool.md +0 -11
  139. package/tools/checkin-rank/handler.ts +0 -16
  140. package/tools/stats-query/handler.ts +0 -31
  141. package/tools/stats-query/stats-query.tool.md +0 -16
  142. package/tools/stats-user/handler.ts +0 -28
  143. package/tools/stats-user/stats-user.tool.md +0 -12
@@ -0,0 +1,34 @@
1
+ export function todayStr() {
2
+ const d = new Date();
3
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
4
+ }
5
+ export function yesterdayStr() {
6
+ const d = new Date();
7
+ d.setDate(d.getDate() - 1);
8
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
9
+ }
10
+ export function ts() {
11
+ return new Date().toISOString();
12
+ }
13
+ export function randomInt(min, max) {
14
+ return Math.floor(Math.random() * (max - min + 1)) + min;
15
+ }
16
+ /** Runtime Message → group/global context */
17
+ export function resolveContextKey(input) {
18
+ const meta = input.metadata ?? {};
19
+ const channelType = String(meta.type ?? meta.channelType ?? '');
20
+ if (channelType === 'group' || channelType === 'guild' || channelType === 'channel') {
21
+ return { type: 'group', id: String(meta.channelId ?? input.conversation?.id ?? '') };
22
+ }
23
+ if (input.conversation && channelType !== 'private') {
24
+ return { type: 'group', id: String(input.conversation.id ?? '') };
25
+ }
26
+ return { type: 'global', id: '' };
27
+ }
28
+ export function resolveSender(input) {
29
+ const meta = input.metadata ?? {};
30
+ const id = input.sender?.id ?? String(meta.senderId ?? '');
31
+ const name = input.sender?.name ?? String(meta.senderName ?? meta.name ?? '用户');
32
+ return { id, name };
33
+ }
34
+ //# sourceMappingURL=shared-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-runtime.js","sourceRoot":"","sources":["../src/shared-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ;IACtB,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACnH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3B,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACnH,CAAC;AAED,MAAM,UAAU,EAAE;IAChB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,GAAW;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AAC3D,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,iBAAiB,CAAC,KAGjC;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAChE,IAAI,WAAW,KAAK,OAAO,IAAI,WAAW,KAAK,OAAO,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QACpF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACvF,CAAC;IACD,IAAI,KAAK,CAAC,YAAY,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAG7B;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;IAClC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IAChF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { GroupSuiteConfig } from './config.js';
2
+ import type { GroupSuiteRuntime } from './runtime-state.js';
3
+ export declare function weekStartStr(): string;
4
+ export declare function monthStartStr(): string;
5
+ export declare function resolveGroupId(input: {
6
+ conversation?: {
7
+ readonly kind?: string;
8
+ readonly id?: string;
9
+ };
10
+ metadata?: Readonly<Record<string, unknown>>;
11
+ }): string;
12
+ export declare function recordMessage(input: {
13
+ sender?: {
14
+ readonly id: string;
15
+ readonly name?: string;
16
+ };
17
+ conversation?: {
18
+ readonly kind?: string;
19
+ readonly id?: string;
20
+ };
21
+ metadata?: Readonly<Record<string, unknown>>;
22
+ }, runtime: GroupSuiteRuntime): void;
23
+ export declare function flushStatsBuffer(runtime: GroupSuiteRuntime): Promise<void>;
24
+ export declare function queryStats(groupId: string, fromDate: string, runtime: GroupSuiteRuntime): Promise<Map<string, {
25
+ name: string;
26
+ count: number;
27
+ }>>;
28
+ type MessageInput = {
29
+ sender?: {
30
+ readonly id: string;
31
+ readonly name?: string;
32
+ };
33
+ target?: string;
34
+ metadata?: Readonly<Record<string, unknown>>;
35
+ };
36
+ export declare function statsRankText(input: MessageInput, cfg: GroupSuiteConfig, fromDate: string, title: string, runtime: GroupSuiteRuntime): Promise<string>;
37
+ export declare function myStatsText(input: MessageInput, runtime: GroupSuiteRuntime): Promise<string>;
38
+ export {};
39
+ //# sourceMappingURL=stats-lib.d.ts.map
@@ -0,0 +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;AAMD,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,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;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChE,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAmBnC;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwChF;AAED,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,iBAAiB,GACzB,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;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,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,EAAE,iBAAiB,GACzB,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClG"}
@@ -0,0 +1,172 @@
1
+ import { getStatsModel } from './db-store.js';
2
+ import { resolveSender, todayStr, ts, } from './shared-runtime.js';
3
+ import { buildStatsRankReportData, formatMyStatsText, formatRankText, } from './stats-data.js';
4
+ export function weekStartStr() {
5
+ const d = new Date();
6
+ const day = d.getDay() || 7;
7
+ d.setDate(d.getDate() - day + 1);
8
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
9
+ }
10
+ export function monthStartStr() {
11
+ const d = new Date();
12
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-01`;
13
+ }
14
+ function bufferKey(userId, groupId, date) {
15
+ return `${userId}:${groupId}:${date}`;
16
+ }
17
+ export function resolveGroupId(input) {
18
+ const meta = input.metadata ?? {};
19
+ const channelType = String(meta.type ?? meta.channelType ?? '');
20
+ if (channelType === 'group' || channelType === 'guild' || channelType === 'channel') {
21
+ return String(meta.channelId ?? input.conversation?.id ?? '');
22
+ }
23
+ if (input.conversation && channelType !== 'private') {
24
+ return String(input.conversation.id ?? '');
25
+ }
26
+ return '';
27
+ }
28
+ export function recordMessage(input, runtime) {
29
+ const targetBuffer = runtime.statsBuffer;
30
+ const { id: userId, name: userName } = resolveSender(input);
31
+ if (!userId)
32
+ return;
33
+ const groupId = resolveGroupId(input);
34
+ const key = bufferKey(userId, groupId, todayStr());
35
+ const pending = targetBuffer.get(key);
36
+ if (pending) {
37
+ pending.count++;
38
+ pending.user_name = userName;
39
+ }
40
+ else {
41
+ targetBuffer.set(key, {
42
+ user_id: userId,
43
+ user_name: userName,
44
+ group_id: groupId,
45
+ date: todayStr(),
46
+ count: 1,
47
+ });
48
+ }
49
+ }
50
+ export async function flushStatsBuffer(runtime) {
51
+ const targetBuffer = runtime.statsBuffer;
52
+ const M = getStatsModel(runtime.db);
53
+ if (!M || targetBuffer.size === 0)
54
+ return;
55
+ for (const [key, entry] of [...targetBuffer.entries()]) {
56
+ // 快照本次要落库的计数;flush 期间新累计的部分留在缓冲
57
+ const countSnapshot = entry.count;
58
+ try {
59
+ const existing = (await M.select().where({
60
+ user_id: entry.user_id,
61
+ group_id: entry.group_id,
62
+ date: entry.date,
63
+ }));
64
+ if (existing.length > 0) {
65
+ await M.update({
66
+ count: Number(existing[0].count || 0) + countSnapshot,
67
+ user_name: entry.user_name,
68
+ updated_at: ts(),
69
+ }).where({
70
+ user_id: entry.user_id,
71
+ group_id: entry.group_id,
72
+ date: entry.date,
73
+ });
74
+ }
75
+ else {
76
+ await M.insert({
77
+ user_id: entry.user_id,
78
+ user_name: entry.user_name,
79
+ group_id: entry.group_id,
80
+ date: entry.date,
81
+ count: countSnapshot,
82
+ updated_at: ts(),
83
+ });
84
+ }
85
+ // 只移除写入成功的部分;失败的 key 留在缓冲等下一轮重试
86
+ entry.count -= countSnapshot;
87
+ if (entry.count <= 0 && targetBuffer.get(key) === entry)
88
+ targetBuffer.delete(key);
89
+ }
90
+ catch {
91
+ /* single row failure: keep entry in buffer for next flush */
92
+ }
93
+ }
94
+ }
95
+ export async function queryStats(groupId, fromDate, runtime) {
96
+ const M = getStatsModel(runtime.db);
97
+ if (!M)
98
+ return new Map();
99
+ const all = (groupId
100
+ ? await M.select().where({ group_id: groupId })
101
+ : await M.select());
102
+ const result = new Map();
103
+ for (const row of all) {
104
+ if (String(row.date) < fromDate)
105
+ continue;
106
+ const userId = String(row.user_id);
107
+ const existing = result.get(userId);
108
+ if (existing) {
109
+ existing.count += Number(row.count || 0);
110
+ if (row.user_name)
111
+ existing.name = String(row.user_name);
112
+ }
113
+ else {
114
+ result.set(userId, {
115
+ name: String(row.user_name || row.user_id),
116
+ count: Number(row.count || 0),
117
+ });
118
+ }
119
+ }
120
+ return result;
121
+ }
122
+ export async function statsRankText(input, cfg, fromDate, title, runtime) {
123
+ await flushStatsBuffer(runtime);
124
+ const groupId = resolveGroupId(input);
125
+ const stats = await queryStats(groupId, fromDate, runtime);
126
+ const { id: userId } = resolveSender(input);
127
+ const data = buildStatsRankReportData(stats, title, cfg.rankSize, userId);
128
+ return formatRankText(data);
129
+ }
130
+ export async function myStatsText(input, runtime) {
131
+ await flushStatsBuffer(runtime);
132
+ const M = getStatsModel(runtime.db);
133
+ if (!M)
134
+ return '统计数据库尚未就绪';
135
+ const { id: userId, name: userName } = resolveSender(input);
136
+ if (!userId)
137
+ return '无法获取用户信息';
138
+ const groupId = resolveGroupId(input);
139
+ const rows = (groupId
140
+ ? await M.select().where({ user_id: userId, group_id: groupId })
141
+ : await M.select().where({ user_id: userId }));
142
+ if (rows.length === 0)
143
+ return '暂无你的消息记录';
144
+ const today = todayStr();
145
+ const weekStart = weekStartStr();
146
+ const monthStart = monthStartStr();
147
+ let todayCount = 0;
148
+ let weekCount = 0;
149
+ let monthCount = 0;
150
+ let totalCount = 0;
151
+ for (const row of rows) {
152
+ const c = Number(row.count || 0);
153
+ totalCount += c;
154
+ if (String(row.date) >= monthStart)
155
+ monthCount += c;
156
+ if (String(row.date) >= weekStart)
157
+ weekCount += c;
158
+ if (row.date === today)
159
+ todayCount += c;
160
+ }
161
+ const data = {
162
+ userName: userName || '你',
163
+ scope: groupId ? '本群' : '全局',
164
+ todayCount,
165
+ weekCount,
166
+ monthCount,
167
+ totalCount,
168
+ activeDays: rows.length,
169
+ };
170
+ return formatMyStatsText(data);
171
+ }
172
+ //# sourceMappingURL=stats-lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats-lib.js","sourceRoot":"","sources":["../src/stats-lib.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function defineGroupSuiteTables(db: {
2
+ define: (name: string, schema: Record<string, unknown>) => void;
3
+ }): void;
4
+ //# sourceMappingURL=tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AASA,wBAAgB,sBAAsB,CACpC,EAAE,EAAE;IAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;CAAE,GACtE,IAAI,CAkCN"}
package/lib/tables.js ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Group-suite table schemas for DatabaseHost.
3
+ */
4
+ import { CHECKIN_TABLE, TEACH_TABLE, STATS_TABLE, } from './memory-store.js';
5
+ export function defineGroupSuiteTables(db) {
6
+ db.define(CHECKIN_TABLE, {
7
+ user_id: { type: 'text', nullable: false },
8
+ user_name: { type: 'text', default: '' },
9
+ points: { type: 'integer', default: 0 },
10
+ total_checkins: { type: 'integer', default: 0 },
11
+ streak: { type: 'integer', default: 0 },
12
+ max_streak: { type: 'integer', default: 0 },
13
+ last_checkin: { type: 'text', default: '' },
14
+ context_type: { type: 'text', default: 'global' },
15
+ context_id: { type: 'text', default: '' },
16
+ created_at: { type: 'text', default: '' },
17
+ updated_at: { type: 'text', default: '' },
18
+ });
19
+ db.define(TEACH_TABLE, {
20
+ question: { type: 'text', nullable: false },
21
+ answer: { type: 'text', nullable: false },
22
+ is_regex: { type: 'integer', default: 0 },
23
+ context_type: { type: 'text', default: 'global' },
24
+ context_id: { type: 'text', default: '' },
25
+ creator_id: { type: 'text', default: '' },
26
+ creator_name: { type: 'text', default: '' },
27
+ hit_count: { type: 'integer', default: 0 },
28
+ created_at: { type: 'text', default: '' },
29
+ updated_at: { type: 'text', default: '' },
30
+ });
31
+ db.define(STATS_TABLE, {
32
+ user_id: { type: 'text', nullable: false },
33
+ user_name: { type: 'text', default: '' },
34
+ group_id: { type: 'text', default: '' },
35
+ date: { type: 'text', nullable: false },
36
+ count: { type: 'integer', default: 0 },
37
+ updated_at: { type: 'text', default: '' },
38
+ });
39
+ }
40
+ //# sourceMappingURL=tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.js","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,aAAa,EACb,WAAW,EACX,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,MAAM,UAAU,sBAAsB,CACpC,EAAuE;IAEvE,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE;QACvB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC1C,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACxC,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACvC,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC/C,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACvC,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC3C,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QAC3C,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QACjD,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACzC,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACzC,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;KAC1C,CAAC,CAAC;IACH,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;QACrB,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC3C,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QACzC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACzC,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QACjD,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACzC,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACzC,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QAC3C,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1C,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACzC,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;KAC1C,CAAC,CAAC;IACH,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;QACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC1C,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACxC,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACvC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QACvC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACtC,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;KAC1C,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { GroupSuiteConfig } from './config.js';
2
+ import type { GroupSuiteRuntime } from './runtime-state.js';
3
+ export declare const TEACH_USAGE_HINT = "\u683C\u5F0F\uFF1Ateach \u5173\u952E\u8BCD \u56DE\u7B54\uFF08\u56DE\u7B54\u53EF\u542B\u7A7A\u683C\uFF09\uFF0C\u6216 teach \u95EE\u9898|\u7B54\u6848";
4
+ export declare function parseTeachPair(raw: string): {
5
+ question: string;
6
+ answer: string;
7
+ } | null;
8
+ type MessageInput = {
9
+ sender?: {
10
+ readonly id: string;
11
+ readonly name?: string;
12
+ };
13
+ target?: string;
14
+ content?: unknown;
15
+ metadata?: Readonly<Record<string, unknown>>;
16
+ };
17
+ export declare function teachAdd(input: MessageInput, cfg: GroupSuiteConfig, payload: string, regex: boolean | undefined, runtime: GroupSuiteRuntime): Promise<string>;
18
+ export declare function teachList(input: MessageInput, cfg: GroupSuiteConfig, page: number | undefined, runtime: GroupSuiteRuntime): Promise<string>;
19
+ export declare function teachForget(input: MessageInput, questionRaw: string, runtime: GroupSuiteRuntime): Promise<string>;
20
+ /** Try teach auto-reply; returns reply text or null. */
21
+ export declare function tryTeachReply(input: MessageInput, cfg: GroupSuiteConfig, runtime: GroupSuiteRuntime): Promise<string | null>;
22
+ export {};
23
+ //# sourceMappingURL=teach-lib.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teach-lib.d.ts","sourceRoot":"","sources":["../src/teach-lib.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAOpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,eAAO,MAAM,gBAAgB,wJACY,CAAC;AAa1C,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAevF;AAkCD,KAAK,YAAY,GAAG;IAClB,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC9C,CAAC;AAiCF,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,MAAM,EACf,KAAK,qBAAQ,EACb,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,MAAM,CAAC,CAqEjB;AAED,wBAAsB,SAAS,CAC7B,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,gBAAgB,EACrB,IAAI,oBAAI,EACR,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED,wDAAwD;AACxD,wBAAsB,aAAa,CACjC,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6CxB"}
@@ -0,0 +1,228 @@
1
+ import { getTeachModel } from './db-store.js';
2
+ import { resolveContextKey, resolveSender, ts, } from './shared-runtime.js';
3
+ export const TEACH_USAGE_HINT = '格式:teach 关键词 回答(回答可含空格),或 teach 问题|答案';
4
+ function isSafeRegex(pattern) {
5
+ if (pattern.length > 200)
6
+ return false;
7
+ if (/(\+|\*|\{)\)?(\+|\*|\{)/.test(pattern))
8
+ return false;
9
+ if (/\([^)]*(\+|\*)[^)]*(\+|\*)[^)]*\)[+*]/.test(pattern))
10
+ return false;
11
+ const altGroups = pattern.match(/\([^)]*\|[^)]*\)/g) || [];
12
+ for (const g of altGroups) {
13
+ if ((g.match(/\|/g) || []).length > 10)
14
+ return false;
15
+ }
16
+ return true;
17
+ }
18
+ export function parseTeachPair(raw) {
19
+ if (!raw)
20
+ return null;
21
+ const pipe = raw.indexOf('|');
22
+ if (pipe >= 0) {
23
+ const question = raw.slice(0, pipe).trim();
24
+ const answer = raw.slice(pipe + 1).trim();
25
+ if (question && answer)
26
+ return { question, answer };
27
+ return null;
28
+ }
29
+ const lastSpace = raw.lastIndexOf(' ');
30
+ if (lastSpace < 0)
31
+ return null;
32
+ const question = raw.slice(0, lastSpace).trim();
33
+ const answer = raw.slice(lastSpace + 1).trim();
34
+ if (!question || !answer)
35
+ return null;
36
+ return { question, answer };
37
+ }
38
+ function processAnswer(answer, sender, match) {
39
+ let result = answer;
40
+ result = result.replace(/\{sender\}/g, sender.name || '你');
41
+ result = result.replace(/\{sender\.id\}/g, sender.id || '');
42
+ result = result.replace(/\{time\}/g, new Date().toLocaleTimeString('zh-CN'));
43
+ result = result.replace(/\{date\}/g, new Date().toLocaleDateString('zh-CN'));
44
+ if (match) {
45
+ for (let i = 1; i < match.length; i++) {
46
+ result = result.replace(new RegExp(`\\$${i}`, 'g'), match[i] || '');
47
+ }
48
+ }
49
+ return result;
50
+ }
51
+ function qaWhereKey(row) {
52
+ return {
53
+ question: row.question,
54
+ context_type: row.context_type,
55
+ context_id: row.context_id,
56
+ is_regex: row.is_regex ? 1 : 0,
57
+ };
58
+ }
59
+ async function findMatch(content, ctxType, ctxId, cfg, runtime) {
60
+ const QA = getTeachModel(runtime.db);
61
+ if (!QA)
62
+ return null;
63
+ const allItems = (await QA.select());
64
+ const candidates = allItems.filter((item) => item.context_type === 'global' ||
65
+ (item.context_type === ctxType && item.context_id === ctxId));
66
+ for (const item of candidates) {
67
+ if (!item.is_regex && item.question === content)
68
+ return item;
69
+ }
70
+ if (cfg.teachAllowRegex) {
71
+ for (const item of candidates) {
72
+ if (!item.is_regex)
73
+ continue;
74
+ try {
75
+ if (new RegExp(String(item.question), 'i').test(content))
76
+ return item;
77
+ }
78
+ catch {
79
+ continue;
80
+ }
81
+ }
82
+ }
83
+ return null;
84
+ }
85
+ export async function teachAdd(input, cfg, payload, regex = false, runtime) {
86
+ const QA = getTeachModel(runtime.db);
87
+ if (!QA)
88
+ return '问答数据库尚未就绪,请稍后重试';
89
+ if (regex && !cfg.teachAllowRegex)
90
+ return '管理员已禁用正则问答';
91
+ const parsed = parseTeachPair(payload.trim());
92
+ if (!parsed) {
93
+ return regex
94
+ ? '格式:teach-regex 正则 回答,或 teach-regex 正则|回答'
95
+ : TEACH_USAGE_HINT;
96
+ }
97
+ const { question, answer } = parsed;
98
+ if (regex) {
99
+ try {
100
+ new RegExp(question, 'i');
101
+ }
102
+ catch (e) {
103
+ return `正则表达式不合法: ${e.message}`;
104
+ }
105
+ if (!isSafeRegex(question))
106
+ return '该正则可能导致性能问题,请简化';
107
+ }
108
+ const { type: ctxType, id: ctxId } = resolveContextKey(input);
109
+ const sender = resolveSender(input);
110
+ if (ctxType === 'group') {
111
+ const existing = (await QA.select().where({
112
+ context_type: ctxType,
113
+ context_id: ctxId,
114
+ }));
115
+ if (existing.length >= cfg.teachMaxPerGroup) {
116
+ return `该群问答数已达上限 (${cfg.teachMaxPerGroup})`;
117
+ }
118
+ }
119
+ const duplicate = (await QA.select().where({
120
+ question,
121
+ context_type: ctxType,
122
+ context_id: ctxId,
123
+ }));
124
+ if (duplicate.length > 0 && !regex) {
125
+ await QA.update({ answer, updated_at: ts() }).where(qaWhereKey(duplicate[0]));
126
+ return `已更新问答:「${question}」→「${answer}」`;
127
+ }
128
+ await QA.insert({
129
+ question,
130
+ answer,
131
+ is_regex: regex ? 1 : 0,
132
+ context_type: ctxType,
133
+ context_id: ctxId,
134
+ creator_id: sender.id,
135
+ creator_name: sender.name,
136
+ hit_count: 0,
137
+ created_at: ts(),
138
+ updated_at: ts(),
139
+ });
140
+ return regex
141
+ ? `学会了!匹配 /${question}/ 的消息我会回复「${answer}」`
142
+ : `学会了!发送「${question}」我会回复「${answer}」`;
143
+ }
144
+ export async function teachList(input, cfg, page = 1, runtime) {
145
+ const QA = getTeachModel(runtime.db);
146
+ if (!QA)
147
+ return '问答数据库尚未就绪';
148
+ const safePage = Math.max(1, page);
149
+ const { type: ctxType, id: ctxId } = resolveContextKey(input);
150
+ const allItems = (await QA.select().where(ctxType === 'global'
151
+ ? { context_type: 'global' }
152
+ : { context_type: ctxType, context_id: ctxId }));
153
+ if (allItems.length === 0)
154
+ return '还没有教过任何问答哦~';
155
+ const totalPages = Math.ceil(allItems.length / cfg.teachPageSize);
156
+ const pageNum = Math.min(safePage, totalPages);
157
+ const start = (pageNum - 1) * cfg.teachPageSize;
158
+ const pageItems = allItems.slice(start, start + cfg.teachPageSize);
159
+ const lines = pageItems.map((item, i) => {
160
+ const prefix = item.is_regex ? '[正则]' : '[精确]';
161
+ const q = item.is_regex ? `/${item.question}/` : item.question;
162
+ return `${start + i + 1}. ${prefix} ${q} → ${item.answer}`;
163
+ });
164
+ const header = ctxType === 'global' ? '全局问答列表' : '本群问答列表';
165
+ return `${header}\n${lines.join('\n')}\n第 ${pageNum}/${totalPages} 页 · 共 ${allItems.length} 条`;
166
+ }
167
+ export async function teachForget(input, questionRaw, runtime) {
168
+ const QA = getTeachModel(runtime.db);
169
+ if (!QA)
170
+ return '问答数据库尚未就绪';
171
+ const question = questionRaw.trim();
172
+ if (!question)
173
+ return '请提供要删除的问题';
174
+ const { type: ctxType, id: ctxId } = resolveContextKey(input);
175
+ const items = (await QA.select().where({
176
+ question,
177
+ context_type: ctxType,
178
+ context_id: ctxId,
179
+ }));
180
+ if (items.length === 0)
181
+ return `没有找到问题「${question}」`;
182
+ await QA.delete().where(qaWhereKey(items[0]));
183
+ return `已忘记「${question}」的回答`;
184
+ }
185
+ /** Try teach auto-reply; returns reply text or null. */
186
+ export async function tryTeachReply(input, cfg, runtime) {
187
+ const content = typeof input.content === 'string' ? input.content.trim() : '';
188
+ if (!content)
189
+ return null;
190
+ const { type: ctxType, id: ctxId } = resolveContextKey(input);
191
+ const matched = await findMatch(content, ctxType, ctxId, cfg, runtime);
192
+ if (!matched)
193
+ return null;
194
+ const cooldownKey = `${matched.question}:${ctxType}:${ctxId}:${matched.is_regex ?? 0}`;
195
+ const cooldowns = runtime.teachCooldowns;
196
+ const last = cooldowns.get(cooldownKey);
197
+ if (last && Date.now() - last < cfg.teachCooldownMs)
198
+ return null;
199
+ cooldowns.set(cooldownKey, Date.now());
200
+ const QA = getTeachModel(runtime.db);
201
+ if (QA) {
202
+ try {
203
+ await QA.update({
204
+ hit_count: Number(matched.hit_count || 0) + 1,
205
+ updated_at: ts(),
206
+ }).where(qaWhereKey(matched));
207
+ }
208
+ catch {
209
+ /* ignore */
210
+ }
211
+ }
212
+ const sender = resolveSender(input);
213
+ let answer = String(matched.answer ?? '');
214
+ if (matched.is_regex) {
215
+ try {
216
+ const m = content.match(new RegExp(String(matched.question), 'i'));
217
+ answer = processAnswer(answer, sender, m || undefined);
218
+ }
219
+ catch {
220
+ /* ignore */
221
+ }
222
+ }
223
+ else {
224
+ answer = processAnswer(answer, sender);
225
+ }
226
+ return answer;
227
+ }
228
+ //# sourceMappingURL=teach-lib.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teach-lib.js","sourceRoot":"","sources":["../src/teach-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
+ });