@zhin.js/plugin-group-suite 1.0.0 → 1.1.0

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