@zhin.js/plugin-group-suite 1.1.24 → 1.1.26

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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +18 -1
  3. package/commands/checkin/index.js +3 -3
  4. package/commands/checkin/index.ts +3 -3
  5. package/commands/forget/index.js +1 -1
  6. package/commands/forget/index.ts +1 -1
  7. package/commands/keyword-add/[keyword]/index.js +1 -1
  8. package/commands/keyword-add/[keyword]/index.ts +1 -1
  9. package/commands/keyword-remove/[keyword]/index.js +1 -1
  10. package/commands/keyword-remove/[keyword]/index.ts +1 -1
  11. package/commands/rank/index.js +3 -3
  12. package/commands/rank/index.ts +3 -3
  13. package/commands/stats/index.js +3 -3
  14. package/commands/stats/index.ts +3 -3
  15. package/commands/stats-card/index.js +2 -2
  16. package/commands/stats-card/index.ts +2 -2
  17. package/commands/stats-rank/index.js +3 -3
  18. package/commands/stats-rank/index.ts +3 -3
  19. package/commands/stats-week/index.js +3 -3
  20. package/commands/stats-week/index.ts +3 -3
  21. package/commands/teach/index.js +4 -4
  22. package/commands/teach/index.ts +4 -4
  23. package/commands/teach-list/[[page]]/index.js +3 -3
  24. package/commands/teach-list/[[page]]/index.ts +3 -3
  25. package/commands/teach-regex/index.js +4 -4
  26. package/commands/teach-regex/index.ts +4 -4
  27. package/handlers/welcome/index.js +2 -2
  28. package/handlers/welcome/index.ts +2 -2
  29. package/lib/config.d.ts +15 -1
  30. package/lib/config.d.ts.map +1 -1
  31. package/lib/config.js +11 -1
  32. package/lib/config.js.map +1 -1
  33. package/lib/teach-lib.d.ts +12 -0
  34. package/lib/teach-lib.d.ts.map +1 -1
  35. package/lib/teach-lib.js +104 -29
  36. package/lib/teach-lib.js.map +1 -1
  37. package/middlewares/keyword-reply/index.js +2 -2
  38. package/middlewares/keyword-reply/index.ts +2 -2
  39. package/middlewares/teach-reply/index.js +2 -2
  40. package/middlewares/teach-reply/index.ts +2 -2
  41. package/package.json +16 -21
  42. package/plugin.js +5 -1
  43. package/schema.json +97 -14
  44. package/src/config.ts +22 -2
  45. package/src/teach-lib.ts +86 -23
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 凉菜
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -36,10 +36,18 @@ group-suite:
36
36
  rankSize: 10
37
37
  teachMaxPerGroup: 200
38
38
  teachCooldownMs: 3000
39
- teachAllowRegex: true
39
+ teachAllowRegex: false # 默认关闭;见下方“正则问答”
40
40
  teachPageSize: 10
41
41
  ```
42
42
 
43
+ ### 正则问答
44
+
45
+ `teachAllowRegex` 默认 `false`:正则规则会对每条入站消息执行,开启前请确认群成员可信。开启后:
46
+
47
+ - `teach-regex` 只接受结构安全的表达式。带量词的分组内部不能再有量词或 `|`(如 `(\w+\s?)+`、`(a|aa)+`、`(.*a){10}` 会被拒绝,可改用字符类 `[ab]+`),不支持反向引用与环视,一条表达式最多 3 个 `*` / `+` / `{n,m}`。
48
+ - 正则规则只对不超过 200 个字符的消息尝试匹配;精确问答不受此限制。
49
+ - 关闭后已保存的正则规则保留但不再触发;旧版本存下的不安全表达式在匹配时会被跳过。
50
+
43
51
  约束以 [schema.json](./schema.json) 为准。启用关键词回复时默认要求 Database Host 的原子
44
52
  状态服务;没有该服务会启动失败并提示原因。演示环境可显式设置 `ephemeralKeywords: true`,
45
53
  此时词库只活在当前插件实例,插件重载或进程重启后会丢失。
@@ -57,6 +65,15 @@ group-suite:
57
65
  它是 best-effort 计数,并非持久 outbox:停止、插件重载或崩溃时尚未落库的批次可能丢失。
58
66
  退休 generation 的清理不额外写数据库,也不绕过代级准入。
59
67
 
68
+ ## 分层配置(ADR 0050 / 0055)
69
+
70
+ 支持全部四个层级:
71
+
72
+ - 适配器、账号、会话层可以覆盖 `welcomeMessage`、`basePointsMin`、`basePointsMax`、`streakBonus`、`streakCap`、`rankSize`、`teachMaxPerGroup`、`teachCooldownMs`、`teachPageSize`。
73
+ - `keywordReply`、`ephemeralKeywords`(决定存储方式)、`welcomeConversations`、`teachAllowRegex`(正则安全)只能在全局层修改。
74
+ - 开启 `features.selfService.enabled` 后,群里的 `admin` 可以用 `功能 设置 group-suite welcomeMessage "欢迎 {name}"` 改本群欢迎语,也可以改 `rankSize`、`teachCooldownMs`、`teachPageSize`(`selfServiceFields`);积分与问答上限只能在 Console 改。
75
+ - 命令、中间件与入群欢迎都按所在会话读取有效配置,改动原地生效。推荐用会话层开关(`功能 关闭 group-suite`)代替 `welcomeConversations` 这类按群名单。
76
+
60
77
  ## 使用与权限
61
78
 
62
79
  未配置命名空间时直接使用表内指令名;如果实例设 `commandNamespace: suite`,使用
@@ -1,12 +1,12 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
3
+ import { groupSuiteConfigFor } from "../../lib/config.js";
4
4
  import { doCheckin } from "../../lib/checkin-lib.js";
5
5
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
6
6
  export default defineCommand({
7
7
  description: '每日签到获得积分', descriptionI18n: { en: "Check in daily to earn points" },
8
8
  alias: ['checkin do', '签到'],
9
- execute({ config, input, owner, use, locale }) {
10
- return doCheckin({ ...input, locale }, resolveGroupSuiteConfig(config), resolveGroupSuiteRuntime({ owner, use }));
9
+ execute({ config, input, owner, use, has, locale }) {
10
+ return doCheckin({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), resolveGroupSuiteRuntime({ owner, use }));
11
11
  },
12
12
  });
@@ -1,13 +1,13 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
2
  import type { Message } from '@zhin.js/core/runtime';
3
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
3
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../src/config.js';
4
4
  import { doCheckin } from '../../src/checkin-lib.js';
5
5
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
6
6
 
7
7
  export default defineCommand<GroupSuiteConfig, string, Message>({
8
8
  description: '每日签到获得积分', descriptionI18n: { en: "Check in daily to earn points" },
9
9
  alias: ['checkin do', '签到'],
10
- execute({ config, input, owner, use, locale }) {
11
- return doCheckin({ ...input, locale }, resolveGroupSuiteConfig(config), resolveGroupSuiteRuntime({ owner, use }));
10
+ execute({ config, input, owner, use, has, locale }) {
11
+ return doCheckin({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), resolveGroupSuiteRuntime({ owner, use }));
12
12
  },
13
13
  });
@@ -3,7 +3,7 @@ import { defineCommand } from 'zhin.js/command';
3
3
  import { teachForget } from "../../lib/teach-lib.js";
4
4
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
5
5
  export default defineCommand({
6
- permit: ['group()', 'role(owner,admin,master,trusted)'],
6
+ permit: ['group()', 'trusted'],
7
7
  description: '忘记问答(删除问答对)', descriptionI18n: { en: "Delete a learned question and answer pair" },
8
8
  execute({ input, args, owner, use, locale }) {
9
9
  return teachForget({ ...input, locale }, args.join(' '), resolveGroupSuiteRuntime({ owner, use }));
@@ -5,7 +5,7 @@ import { teachForget } from '../../src/teach-lib.js';
5
5
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
6
6
 
7
7
  export default defineCommand<GroupSuiteConfig, string, Message>({
8
- permit: ['group()', 'role(owner,admin,master,trusted)'],
8
+ permit: ['group()', 'trusted'],
9
9
  description: '忘记问答(删除问答对)', descriptionI18n: { en: "Delete a learned question and answer pair" },
10
10
  execute({ input, args, owner, use, locale }) {
11
11
  return teachForget({ ...input, locale }, args.join(' '), resolveGroupSuiteRuntime({ owner, use }));
@@ -3,7 +3,7 @@ import { messages as t } from "../../../lib/i18n.js";
3
3
  import { defineCommand } from 'zhin.js/command';
4
4
  import { keywordsForCommand } from "../../../lib/keywords.js";
5
5
  export default defineCommand({
6
- permit: ['group()', 'role(owner,admin,master,trusted)'],
6
+ permit: ['group()', 'trusted'],
7
7
  description: '添加当前群关键词自动回复', descriptionI18n: { en: "Add a keyword reply in this group" },
8
8
  params: { keyword: { type: 'string' } },
9
9
  async execute(context) {
@@ -5,7 +5,7 @@ import type { GroupSuiteConfig } from '../../../src/config.js';
5
5
  import { keywordsForCommand } from '../../../src/keywords.js';
6
6
 
7
7
  export default defineCommand<GroupSuiteConfig, string, Message>({
8
- permit: ['group()', 'role(owner,admin,master,trusted)'],
8
+ permit: ['group()', 'trusted'],
9
9
  description: '添加当前群关键词自动回复', descriptionI18n: { en: "Add a keyword reply in this group" },
10
10
  params: { keyword: { type: 'string' } },
11
11
  async execute(context) {
@@ -3,7 +3,7 @@ import { messages as t } from "../../../lib/i18n.js";
3
3
  import { defineCommand } from 'zhin.js/command';
4
4
  import { keywordsForCommand } from "../../../lib/keywords.js";
5
5
  export default defineCommand({
6
- permit: ['group()', 'role(owner,admin,master,trusted)'],
6
+ permit: ['group()', 'trusted'],
7
7
  description: '删除当前群关键词自动回复', descriptionI18n: { en: "Delete a keyword reply in this group" },
8
8
  params: { keyword: { type: 'string' } },
9
9
  async execute(context) {
@@ -5,7 +5,7 @@ import type { GroupSuiteConfig } from '../../../src/config.js';
5
5
  import { keywordsForCommand } from '../../../src/keywords.js';
6
6
 
7
7
  export default defineCommand<GroupSuiteConfig, string, Message>({
8
- permit: ['group()', 'role(owner,admin,master,trusted)'],
8
+ permit: ['group()', 'trusted'],
9
9
  description: '删除当前群关键词自动回复', descriptionI18n: { en: "Delete a keyword reply in this group" },
10
10
  params: { keyword: { type: 'string' } },
11
11
  async execute(context) {
@@ -1,12 +1,12 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
3
+ import { groupSuiteConfigFor } from "../../lib/config.js";
4
4
  import { pointsRank } from "../../lib/checkin-lib.js";
5
5
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
6
6
  export default defineCommand({
7
7
  description: '查看积分排行榜', descriptionI18n: { en: "View the points leaderboard" },
8
8
  alias: ['checkin rank'],
9
- execute({ config, input, owner, use, locale }) {
10
- return pointsRank({ ...input, locale }, resolveGroupSuiteConfig(config), resolveGroupSuiteRuntime({ owner, use }));
9
+ execute({ config, input, owner, use, has, locale }) {
10
+ return pointsRank({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), resolveGroupSuiteRuntime({ owner, use }));
11
11
  },
12
12
  });
@@ -1,13 +1,13 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
2
  import type { Message } from '@zhin.js/core/runtime';
3
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
3
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../src/config.js';
4
4
  import { pointsRank } from '../../src/checkin-lib.js';
5
5
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
6
6
 
7
7
  export default defineCommand<GroupSuiteConfig, string, Message>({
8
8
  description: '查看积分排行榜', descriptionI18n: { en: "View the points leaderboard" },
9
9
  alias: ['checkin rank'],
10
- execute({ config, input, owner, use, locale }) {
11
- return pointsRank({ ...input, locale }, resolveGroupSuiteConfig(config), resolveGroupSuiteRuntime({ owner, use }));
10
+ execute({ config, input, owner, use, has, locale }) {
11
+ return pointsRank({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), resolveGroupSuiteRuntime({ owner, use }));
12
12
  },
13
13
  });
@@ -1,15 +1,15 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../lib/i18n.js";
3
3
  import { defineCommand } from 'zhin.js/command';
4
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
4
+ import { groupSuiteConfigFor } from "../../lib/config.js";
5
5
  import { todayStr } from "../../lib/shared-runtime.js";
6
6
  import { resolveGroupId, statsRankText } from "../../lib/stats-lib.js";
7
7
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
8
8
  export default defineCommand({
9
9
  description: '查看今日消息统计', descriptionI18n: { en: "View today's message statistics" },
10
- execute({ config, input, owner, use, locale }) {
10
+ execute({ config, input, owner, use, has, locale }) {
11
11
  const groupId = resolveGroupId({ ...input, locale });
12
12
  const title = groupId ? t(locale, 'statsTodayGroup') : t(locale, 'statsTodayAll');
13
- return statsRankText({ ...input, locale }, resolveGroupSuiteConfig(config), todayStr(), title, resolveGroupSuiteRuntime({ owner, use }));
13
+ return statsRankText({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), todayStr(), title, resolveGroupSuiteRuntime({ owner, use }));
14
14
  },
15
15
  });
@@ -1,19 +1,19 @@
1
1
  import { messages as t } from '../../src/i18n.js';
2
2
  import { defineCommand } from 'zhin.js/command';
3
3
  import type { Message } from '@zhin.js/core/runtime';
4
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
4
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../src/config.js';
5
5
  import { todayStr } from '../../src/shared-runtime.js';
6
6
  import { resolveGroupId, statsRankText } from '../../src/stats-lib.js';
7
7
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
8
8
 
9
9
  export default defineCommand<GroupSuiteConfig, string, Message>({
10
10
  description: '查看今日消息统计', descriptionI18n: { en: "View today's message statistics" },
11
- execute({ config, input, owner, use, locale }) {
11
+ execute({ config, input, owner, use, has, locale }) {
12
12
  const groupId = resolveGroupId({ ...input, locale });
13
13
  const title = groupId ? t(locale, 'statsTodayGroup') : t(locale, 'statsTodayAll');
14
14
  return statsRankText(
15
15
  { ...input, locale },
16
- resolveGroupSuiteConfig(config),
16
+ groupSuiteConfigFor({ config, has, use }, input),
17
17
  todayStr(),
18
18
  title,
19
19
  resolveGroupSuiteRuntime({ owner, use }),
@@ -2,7 +2,7 @@
2
2
  import { messages as t } from "../../lib/i18n.js";
3
3
  import { defineCommand } from 'zhin.js/command';
4
4
  import { segment } from 'zhin.js';
5
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
5
+ import { groupSuiteConfigFor } from "../../lib/config.js";
6
6
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
7
7
  import { flushStatsBuffer, queryStats, resolveGroupId } from "../../lib/stats-lib.js";
8
8
  import { buildStatsRankReportData } from "../../lib/stats-data.js";
@@ -17,7 +17,7 @@ export default defineCommand({
17
17
  const runtime = resolveGroupSuiteRuntime(context);
18
18
  await flushStatsBuffer(runtime);
19
19
  const stats = await queryStats(resolveGroupId(context.input), todayStr(), runtime);
20
- const data = buildStatsRankReportData(stats, t(context.locale, 'statsTodayGroup'), resolveGroupSuiteConfig(context.config).rankSize, resolveSender(context.input).id);
20
+ const data = buildStatsRankReportData(stats, t(context.locale, 'statsTodayGroup'), groupSuiteConfigFor(context, context.input).rankSize, resolveSender(context.input).id);
21
21
  return segment.html({ html: await buildStatsRankHtml(data, context.locale), width: 540,
22
22
  backgroundColor: STATS_REPORT_CANVAS, fileName: 'group-stats.png' });
23
23
  },
@@ -2,7 +2,7 @@ import { messages as t } from '../../src/i18n.js';
2
2
  import { defineCommand } from 'zhin.js/command';
3
3
  import { segment } from 'zhin.js';
4
4
  import type { Message, SendContent } from '@zhin.js/core/runtime';
5
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
5
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../src/config.js';
6
6
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
7
7
  import { flushStatsBuffer, queryStats, resolveGroupId } from '../../src/stats-lib.js';
8
8
  import { buildStatsRankReportData } from '../../src/stats-data.js';
@@ -18,7 +18,7 @@ export default defineCommand<GroupSuiteConfig, SendContent, Message>({
18
18
  await flushStatsBuffer(runtime);
19
19
  const stats = await queryStats(resolveGroupId(context.input), todayStr(), runtime);
20
20
  const data = buildStatsRankReportData(stats, t(context.locale, 'statsTodayGroup'),
21
- resolveGroupSuiteConfig(context.config).rankSize, resolveSender(context.input).id);
21
+ groupSuiteConfigFor(context, context.input).rankSize, resolveSender(context.input).id);
22
22
  return segment.html({ html: await buildStatsRankHtml(data, context.locale), width: 540,
23
23
  backgroundColor: STATS_REPORT_CANVAS, fileName: 'group-stats.png' });
24
24
  },
@@ -1,14 +1,14 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../lib/i18n.js";
3
3
  import { defineCommand } from 'zhin.js/command';
4
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
4
+ import { groupSuiteConfigFor } from "../../lib/config.js";
5
5
  import { monthStartStr, resolveGroupId, statsRankText } from "../../lib/stats-lib.js";
6
6
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
7
7
  export default defineCommand({
8
8
  description: '查看本月话唠排行', descriptionI18n: { en: "View this month's most active members" },
9
- execute({ config, input, owner, use, locale }) {
9
+ execute({ config, input, owner, use, has, locale }) {
10
10
  const groupId = resolveGroupId({ ...input, locale });
11
11
  const title = groupId ? t(locale, 'statsMonthGroup') : t(locale, 'statsMonthAll');
12
- return statsRankText({ ...input, locale }, resolveGroupSuiteConfig(config), monthStartStr(), title, resolveGroupSuiteRuntime({ owner, use }));
12
+ return statsRankText({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), monthStartStr(), title, resolveGroupSuiteRuntime({ owner, use }));
13
13
  },
14
14
  });
@@ -1,18 +1,18 @@
1
1
  import { messages as t } from '../../src/i18n.js';
2
2
  import { defineCommand } from 'zhin.js/command';
3
3
  import type { Message } from '@zhin.js/core/runtime';
4
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
4
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../src/config.js';
5
5
  import { monthStartStr, resolveGroupId, statsRankText } from '../../src/stats-lib.js';
6
6
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
7
7
 
8
8
  export default defineCommand<GroupSuiteConfig, string, Message>({
9
9
  description: '查看本月话唠排行', descriptionI18n: { en: "View this month's most active members" },
10
- execute({ config, input, owner, use, locale }) {
10
+ execute({ config, input, owner, use, has, locale }) {
11
11
  const groupId = resolveGroupId({ ...input, locale });
12
12
  const title = groupId ? t(locale, 'statsMonthGroup') : t(locale, 'statsMonthAll');
13
13
  return statsRankText(
14
14
  { ...input, locale },
15
- resolveGroupSuiteConfig(config),
15
+ groupSuiteConfigFor({ config, has, use }, input),
16
16
  monthStartStr(),
17
17
  title,
18
18
  resolveGroupSuiteRuntime({ owner, use }),
@@ -1,14 +1,14 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../lib/i18n.js";
3
3
  import { defineCommand } from 'zhin.js/command';
4
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
4
+ import { groupSuiteConfigFor } from "../../lib/config.js";
5
5
  import { resolveGroupId, statsRankText, weekStartStr } from "../../lib/stats-lib.js";
6
6
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
7
7
  export default defineCommand({
8
8
  description: '查看本周消息统计', descriptionI18n: { en: "View this week's message statistics" },
9
- execute({ config, input, owner, use, locale }) {
9
+ execute({ config, input, owner, use, has, locale }) {
10
10
  const groupId = resolveGroupId({ ...input, locale });
11
11
  const title = groupId ? t(locale, 'statsWeekGroup') : t(locale, 'statsWeekAll');
12
- return statsRankText({ ...input, locale }, resolveGroupSuiteConfig(config), weekStartStr(), title, resolveGroupSuiteRuntime({ owner, use }));
12
+ return statsRankText({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), weekStartStr(), title, resolveGroupSuiteRuntime({ owner, use }));
13
13
  },
14
14
  });
@@ -1,18 +1,18 @@
1
1
  import { messages as t } from '../../src/i18n.js';
2
2
  import { defineCommand } from 'zhin.js/command';
3
3
  import type { Message } from '@zhin.js/core/runtime';
4
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
4
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../src/config.js';
5
5
  import { resolveGroupId, statsRankText, weekStartStr } from '../../src/stats-lib.js';
6
6
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
7
7
 
8
8
  export default defineCommand<GroupSuiteConfig, string, Message>({
9
9
  description: '查看本周消息统计', descriptionI18n: { en: "View this week's message statistics" },
10
- execute({ config, input, owner, use, locale }) {
10
+ execute({ config, input, owner, use, has, locale }) {
11
11
  const groupId = resolveGroupId({ ...input, locale });
12
12
  const title = groupId ? t(locale, 'statsWeekGroup') : t(locale, 'statsWeekAll');
13
13
  return statsRankText(
14
14
  { ...input, locale },
15
- resolveGroupSuiteConfig(config),
15
+ groupSuiteConfigFor({ config, has, use }, input),
16
16
  weekStartStr(),
17
17
  title,
18
18
  resolveGroupSuiteRuntime({ owner, use }),
@@ -1,12 +1,12 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
3
+ import { groupSuiteConfigFor } from "../../lib/config.js";
4
4
  import { teachAdd } from "../../lib/teach-lib.js";
5
5
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
6
6
  export default defineCommand({
7
- permit: ['group()', 'role(owner,admin,master,trusted)'],
7
+ permit: ['group()', 'trusted'],
8
8
  description: '教我问答(teach 问题 回答 或 问题|答案)', descriptionI18n: { en: "Teach a question and answer pair" },
9
- execute({ config, input, args, owner, use, locale }) {
10
- return teachAdd({ ...input, locale }, resolveGroupSuiteConfig(config), args.join(' '), false, resolveGroupSuiteRuntime({ owner, use }));
9
+ execute({ config, input, args, owner, use, has, locale }) {
10
+ return teachAdd({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), args.join(' '), false, resolveGroupSuiteRuntime({ owner, use }));
11
11
  },
12
12
  });
@@ -1,13 +1,13 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
2
  import type { Message } from '@zhin.js/core/runtime';
3
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
3
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../src/config.js';
4
4
  import { teachAdd } from '../../src/teach-lib.js';
5
5
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
6
6
 
7
7
  export default defineCommand<GroupSuiteConfig, string, Message>({
8
- permit: ['group()', 'role(owner,admin,master,trusted)'],
8
+ permit: ['group()', 'trusted'],
9
9
  description: '教我问答(teach 问题 回答 或 问题|答案)', descriptionI18n: { en: "Teach a question and answer pair" },
10
- execute({ config, input, args, owner, use, locale }) {
11
- return teachAdd({ ...input, locale }, resolveGroupSuiteConfig(config), args.join(' '), false, resolveGroupSuiteRuntime({ owner, use }));
10
+ execute({ config, input, args, owner, use, has, locale }) {
11
+ return teachAdd({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), args.join(' '), false, resolveGroupSuiteRuntime({ owner, use }));
12
12
  },
13
13
  });
@@ -1,13 +1,13 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { resolveGroupSuiteConfig } from "../../../lib/config.js";
3
+ import { groupSuiteConfigFor } from "../../../lib/config.js";
4
4
  import { teachList } from "../../../lib/teach-lib.js";
5
5
  import { resolveGroupSuiteRuntime } from "../../../lib/runtime-state.js";
6
6
  export default defineCommand({
7
7
  description: '查看问答列表', descriptionI18n: { en: "List learned questions and answers" },
8
8
  params: { page: { type: 'number', default: 1 } },
9
- execute({ config, input, params, owner, use, locale }) {
9
+ execute({ config, input, params, owner, use, has, locale }) {
10
10
  const page = Number(params.page ?? 1);
11
- return teachList({ ...input, locale }, resolveGroupSuiteConfig(config), page, resolveGroupSuiteRuntime({ owner, use }));
11
+ return teachList({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), page, resolveGroupSuiteRuntime({ owner, use }));
12
12
  },
13
13
  });
@@ -1,14 +1,14 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
2
  import type { Message } from '@zhin.js/core/runtime';
3
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../../src/config.js';
3
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../../src/config.js';
4
4
  import { teachList } from '../../../src/teach-lib.js';
5
5
  import { resolveGroupSuiteRuntime } from '../../../src/runtime-state.js';
6
6
 
7
7
  export default defineCommand<GroupSuiteConfig, string, Message>({
8
8
  description: '查看问答列表', descriptionI18n: { en: "List learned questions and answers" },
9
9
  params: { page: { type: 'number', default: 1 } },
10
- execute({ config, input, params, owner, use, locale }) {
10
+ execute({ config, input, params, owner, use, has, locale }) {
11
11
  const page = Number(params.page ?? 1);
12
- return teachList({ ...input, locale }, resolveGroupSuiteConfig(config), page, resolveGroupSuiteRuntime({ owner, use }));
12
+ return teachList({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), page, resolveGroupSuiteRuntime({ owner, use }));
13
13
  },
14
14
  });
@@ -1,12 +1,12 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
3
+ import { groupSuiteConfigFor } from "../../lib/config.js";
4
4
  import { teachAdd } from "../../lib/teach-lib.js";
5
5
  import { resolveGroupSuiteRuntime } from "../../lib/runtime-state.js";
6
6
  export default defineCommand({
7
- permit: ['group()', 'role(owner,admin,master,trusted)'],
7
+ permit: ['group()', 'trusted'],
8
8
  description: '教我正则问答', descriptionI18n: { en: "Teach a regular-expression question and answer pair" },
9
- execute({ config, input, args, owner, use, locale }) {
10
- return teachAdd({ ...input, locale }, resolveGroupSuiteConfig(config), args.join(' '), true, resolveGroupSuiteRuntime({ owner, use }));
9
+ execute({ config, input, args, owner, use, has, locale }) {
10
+ return teachAdd({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), args.join(' '), true, resolveGroupSuiteRuntime({ owner, use }));
11
11
  },
12
12
  });
@@ -1,13 +1,13 @@
1
1
  import { defineCommand } from 'zhin.js/command';
2
2
  import type { Message } from '@zhin.js/core/runtime';
3
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
3
+ import { groupSuiteConfigFor, type GroupSuiteConfig } from '../../src/config.js';
4
4
  import { teachAdd } from '../../src/teach-lib.js';
5
5
  import { resolveGroupSuiteRuntime } from '../../src/runtime-state.js';
6
6
 
7
7
  export default defineCommand<GroupSuiteConfig, string, Message>({
8
- permit: ['group()', 'role(owner,admin,master,trusted)'],
8
+ permit: ['group()', 'trusted'],
9
9
  description: '教我正则问答', descriptionI18n: { en: "Teach a regular-expression question and answer pair" },
10
- execute({ config, input, args, owner, use, locale }) {
11
- return teachAdd({ ...input, locale }, resolveGroupSuiteConfig(config), args.join(' '), true, resolveGroupSuiteRuntime({ owner, use }));
10
+ execute({ config, input, args, owner, use, has, locale }) {
11
+ return teachAdd({ ...input, locale }, groupSuiteConfigFor({ config, has, use }, input), args.join(' '), true, resolveGroupSuiteRuntime({ owner, use }));
12
12
  },
13
13
  });
@@ -2,13 +2,13 @@
2
2
  import { defineHandler } from 'zhin.js/handler';
3
3
  import { hasResource } from 'zhin.js';
4
4
  import { memberWelcomeOwnerToken, outboundMessageToken } from '@zhin.js/core/runtime';
5
- import { resolveGroupSuiteConfig } from "../../lib/config.js";
5
+ import { groupSuiteConfigFor } from "../../lib/config.js";
6
6
  import { welcomeConversationAllowed } from "../../lib/welcome-scope.js";
7
7
  /** Canonical notice input only; no SDK-specific callbacks or direct platform sends. */
8
8
  export default defineHandler({
9
9
  event: 'notice.receive',
10
10
  async handle({ payload: notice }) {
11
- const config = resolveGroupSuiteConfig(this.config);
11
+ const config = groupSuiteConfigFor(this, notice);
12
12
  const text = config.welcomeMessage;
13
13
  if (!text || notice.name !== 'notice.group.member_increase'
14
14
  || notice.conversation?.kind !== 'group' || !notice.target?.id)
@@ -1,14 +1,14 @@
1
1
  import { defineHandler } from 'zhin.js/handler';
2
2
  import { hasResource } from 'zhin.js';
3
3
  import { memberWelcomeOwnerToken, outboundMessageToken } from '@zhin.js/core/runtime';
4
- import { resolveGroupSuiteConfig, type GroupSuiteConfig } from '../../src/config.js';
4
+ import { groupSuiteConfigFor } from '../../src/config.js';
5
5
  import { welcomeConversationAllowed } from '../../src/welcome-scope.js';
6
6
 
7
7
  /** Canonical notice input only; no SDK-specific callbacks or direct platform sends. */
8
8
  export default defineHandler({
9
9
  event: 'notice.receive',
10
10
  async handle({ payload: notice }) {
11
- const config = resolveGroupSuiteConfig(this.config as Partial<GroupSuiteConfig>);
11
+ const config = groupSuiteConfigFor(this as Parameters<typeof groupSuiteConfigFor>[0], notice);
12
12
  const text = config.welcomeMessage;
13
13
  if (!text || notice.name !== 'notice.group.member_increase'
14
14
  || notice.conversation?.kind !== 'group' || !notice.target?.id) return;
package/lib/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DeliveryTarget } from 'zhin.js';
1
+ import { type DeliveryTarget } from 'zhin.js';
2
2
  export interface GroupSuiteConfig {
3
3
  keywordReply: boolean;
4
4
  /** Explicitly volatile keywords for demos without a persistent Database Host. */
@@ -19,4 +19,18 @@ export interface GroupSuiteConfig {
19
19
  }
20
20
  export declare const DEFAULT_GROUP_SUITE_CONFIG: GroupSuiteConfig;
21
21
  export declare function resolveGroupSuiteConfig(raw: Partial<GroupSuiteConfig> | undefined): GroupSuiteConfig;
22
+ /** Effective configuration per message / notice (ADR 0050 / 0055): global < adapter < endpoint < conversation. */
23
+ export interface GroupSuiteConfigResolver {
24
+ configFor(target: unknown): Readonly<Partial<GroupSuiteConfig>>;
25
+ }
26
+ export declare const groupSuiteConfigStore: import("zhin.js").PluginStore<GroupSuiteConfigResolver, unknown>;
27
+ /**
28
+ * Settings for one capability call: the conversation's effective config when the resolver is
29
+ * provided (Plugin setup), else the global view. `target` is the message or notice being handled.
30
+ */
31
+ export declare function groupSuiteConfigFor(context: {
32
+ readonly config?: Partial<GroupSuiteConfig>;
33
+ readonly has?: (token: typeof groupSuiteConfigStore) => boolean;
34
+ readonly use: (token: typeof groupSuiteConfigStore) => GroupSuiteConfigResolver;
35
+ }, target: unknown): GroupSuiteConfig;
22
36
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,iFAAiF;IACjF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,sFAAsF;IACtF,cAAc,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,oBAAoB,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,0BAA0B,EAAE,gBAaxC,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,SAAS,GACzC,gBAAgB,CAQlB"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAGjE,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,iFAAiF;IACjF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,sFAAsF;IACtF,cAAc,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,oBAAoB,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IACjD,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,0BAA0B,EAAE,gBAaxC,CAAC;AAEF,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,SAAS,GACzC,gBAAgB,CAQlB;AAED,kHAAkH;AAClH,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;CACjE;AACD,eAAO,MAAM,qBAAqB,kEACoD,CAAC;AAEvF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,qBAAqB,KAAK,OAAO,CAAC;IAChE,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,qBAAqB,KAAK,wBAAwB,CAAC;CACjF,EAAE,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAGpC"}
package/lib/config.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { definePluginStore } from 'zhin.js';
1
2
  import { normalizeWelcomeConversations } from './welcome-scope.js';
2
3
  export const DEFAULT_GROUP_SUITE_CONFIG = {
3
4
  keywordReply: false,
@@ -10,7 +11,7 @@ export const DEFAULT_GROUP_SUITE_CONFIG = {
10
11
  rankSize: 10,
11
12
  teachMaxPerGroup: 200,
12
13
  teachCooldownMs: 3000,
13
- teachAllowRegex: true,
14
+ teachAllowRegex: false,
14
15
  teachPageSize: 10,
15
16
  };
16
17
  export function resolveGroupSuiteConfig(raw) {
@@ -22,4 +23,13 @@ export function resolveGroupSuiteConfig(raw) {
22
23
  }),
23
24
  };
24
25
  }
26
+ export const groupSuiteConfigStore = definePluginStore('zhin.group-suite.config', 'Layered group-suite configuration for one conversation');
27
+ /**
28
+ * Settings for one capability call: the conversation's effective config when the resolver is
29
+ * provided (Plugin setup), else the global view. `target` is the message or notice being handled.
30
+ */
31
+ export function groupSuiteConfigFor(context, target) {
32
+ const resolver = target !== undefined && context.has?.(groupSuiteConfigStore) ? context.use(groupSuiteConfigStore) : undefined;
33
+ return resolveGroupSuiteConfig({ ...(context.config ?? {}), ...(resolver?.configFor(target) ?? {}) });
34
+ }
25
35
  //# sourceMappingURL=config.js.map
package/lib/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AAqBnE,MAAM,CAAC,MAAM,0BAA0B,GAAqB;IAC1D,YAAY,EAAE,KAAK;IACnB,iBAAiB,EAAE,KAAK;IACxB,cAAc,EAAE,EAAE;IAClB,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,EAAE;IACjB,WAAW,EAAE,CAAC;IACd,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,EAAE;IACZ,gBAAgB,EAAE,GAAG;IACrB,eAAe,EAAE,IAAI;IACrB,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,EAAE;CAClB,CAAC;AAEF,MAAM,UAAU,uBAAuB,CACrC,GAA0C;IAE1C,OAAO;QACL,GAAG,0BAA0B;QAC7B,GAAG,GAAG;QACN,GAAG,CAAC,GAAG,EAAE,oBAAoB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACjD,oBAAoB,EAAE,6BAA6B,CAAC,GAAG,CAAC,oBAAoB,CAAC;SAC9E,CAAC;KACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAuB,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAC;AAqBnE,MAAM,CAAC,MAAM,0BAA0B,GAAqB;IAC1D,YAAY,EAAE,KAAK;IACnB,iBAAiB,EAAE,KAAK;IACxB,cAAc,EAAE,EAAE;IAClB,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,EAAE;IACjB,WAAW,EAAE,CAAC;IACd,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,EAAE;IACZ,gBAAgB,EAAE,GAAG;IACrB,eAAe,EAAE,IAAI;IACrB,eAAe,EAAE,KAAK;IACtB,aAAa,EAAE,EAAE;CAClB,CAAC;AAEF,MAAM,UAAU,uBAAuB,CACrC,GAA0C;IAE1C,OAAO;QACL,GAAG,0BAA0B;QAC7B,GAAG,GAAG;QACN,GAAG,CAAC,GAAG,EAAE,oBAAoB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACjD,oBAAoB,EAAE,6BAA6B,CAAC,GAAG,CAAC,oBAAoB,CAAC;SAC9E,CAAC;KACH,CAAC;AACJ,CAAC;AAMD,MAAM,CAAC,MAAM,qBAAqB,GAAG,iBAAiB,CACpD,yBAAyB,EAAE,wDAAwD,CAAC,CAAC;AAEvF;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAInC,EAAE,MAAe;IAChB,MAAM,QAAQ,GAAG,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/H,OAAO,uBAAuB,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AACxG,CAAC"}
@@ -2,6 +2,18 @@ import type { ConversationInput } from './conversation-scope.js';
2
2
  import type { GroupSuiteConfig } from './config.js';
3
3
  import type { GroupSuiteRuntime } from './runtime-state.js';
4
4
  export declare const TEACH_USAGE_HINT = "\u683C\u5F0F\uFF1A\u5173\u952E\u8BCD \u56DE\u7B54\uFF0C\u6216 \u95EE\u9898|\u7B54\u6848";
5
+ /** Regex rules are only tried against messages up to this length. */
6
+ export declare const TEACH_REGEX_MAX_CONTENT = 200;
7
+ /**
8
+ * Conservative structural check for user-taught patterns, which run against every inbound
9
+ * message. It refuses the shapes that backtrack super-linearly:
10
+ * - a repeated group whose body contains a quantifier or an alternation
11
+ * (`(\w+\s?)+`, `(a|aa)+`, `(.*a){10}`);
12
+ * - backreferences and lookarounds;
13
+ * - more than a few repeat operators in one pattern (`.*.*.*.*x`).
14
+ * A character class (`[ab]+`) is the accepted way to repeat a set of alternatives.
15
+ */
16
+ export declare function isSafeRegex(pattern: string): boolean;
5
17
  export declare function parseTeachPair(raw: string): {
6
18
  question: string;
7
19
  answer: string;
@@ -1 +1 @@
1
- {"version":3,"file":"teach-lib.d.ts","sourceRoot":"","sources":["../src/teach-lib.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAOpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,eAAO,MAAM,gBAAgB,4FAAsB,CAAC;AAapD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAevF;AAmCD,KAAK,YAAY,GAAG,iBAAiB,CAAC;AA8BtC,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,CAoBjB;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"}
1
+ {"version":3,"file":"teach-lib.d.ts","sourceRoot":"","sources":["../src/teach-lib.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAOpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,eAAO,MAAM,gBAAgB,4FAAsB,CAAC;AAEpD,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAI3C;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CA0CpD;AAsBD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAevF;AAmCD,KAAK,YAAY,GAAG,iBAAiB,CAAC;AA8BtC,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,CAoBjB;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,CAyCxB"}