@sfmc-bds/qq-bridge 0.2.0-beta.12 → 0.2.0-beta.13

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 (70) hide show
  1. package/README.md +68 -1
  2. package/deploy/install-nginx-webhook.sh +34 -0
  3. package/deploy/nginx-webhook-location.conf +10 -0
  4. package/deploy/qq-bridge.service +23 -0
  5. package/deploy/qq-config-sync.ps1 +106 -0
  6. package/deploy/qq-tunnel.ps1 +15 -0
  7. package/deploy/sync-qq-config.mjs +229 -0
  8. package/dist/commands/account-format.js +41 -0
  9. package/dist/commands/account-format.js.map +7 -0
  10. package/dist/commands/content-format.js +114 -0
  11. package/dist/commands/content-format.js.map +7 -0
  12. package/dist/commands/db-api.js +21 -6
  13. package/dist/commands/db-api.js.map +2 -2
  14. package/dist/commands/handlers.js +392 -524
  15. package/dist/commands/handlers.js.map +2 -2
  16. package/dist/commands/index.js +5 -5
  17. package/dist/commands/index.js.map +3 -3
  18. package/dist/commands/interaction-router.js +38 -133
  19. package/dist/commands/interaction-router.js.map +2 -2
  20. package/dist/commands/join-settings-ui.js +1 -24
  21. package/dist/commands/join-settings-ui.js.map +2 -2
  22. package/dist/commands/menu-format.js +36 -33
  23. package/dist/commands/menu-format.js.map +2 -2
  24. package/dist/commands/menu-panel-sync.js +39 -13
  25. package/dist/commands/menu-panel-sync.js.map +2 -2
  26. package/dist/commands/message-text.js +91 -0
  27. package/dist/commands/message-text.js.map +7 -0
  28. package/dist/commands/pending.js +23 -16
  29. package/dist/commands/pending.js.map +2 -2
  30. package/dist/commands/permissions.js +17 -0
  31. package/dist/commands/permissions.js.map +7 -0
  32. package/dist/commands/registry.js +1 -1
  33. package/dist/commands/registry.js.map +2 -2
  34. package/dist/commands/render.js +7 -16
  35. package/dist/commands/render.js.map +2 -2
  36. package/dist/commands/reply-llbot.js +18 -7
  37. package/dist/commands/reply-llbot.js.map +2 -2
  38. package/dist/commands/reply-official.js +55 -39
  39. package/dist/commands/reply-official.js.map +3 -3
  40. package/dist/commands/router.js +116 -23
  41. package/dist/commands/router.js.map +2 -2
  42. package/dist/config.js +35 -27
  43. package/dist/config.js.map +2 -2
  44. package/dist/console.js +3 -3
  45. package/dist/console.js.map +2 -2
  46. package/dist/index.js +30 -16
  47. package/dist/index.js.map +2 -2
  48. package/dist/llbot-ws-api.js +2 -2
  49. package/dist/llbot-ws-api.js.map +2 -2
  50. package/dist/official/events.js +32 -7
  51. package/dist/official/events.js.map +2 -2
  52. package/dist/official/gateway.js +10 -1
  53. package/dist/official/gateway.js.map +2 -2
  54. package/dist/official/webhook.js +165 -0
  55. package/dist/official/webhook.js.map +7 -0
  56. package/dist/onebot.js +0 -4
  57. package/dist/onebot.js.map +2 -2
  58. package/package.json +4 -4
  59. package/dist/commands/join-settings-ui.test.js +0 -43
  60. package/dist/commands/join-settings-ui.test.js.map +0 -7
  61. package/dist/commands/menu-panel-sync.test.js +0 -27
  62. package/dist/commands/menu-panel-sync.test.js.map +0 -7
  63. package/dist/commands/render.test.js +0 -44
  64. package/dist/commands/render.test.js.map +0 -7
  65. package/dist/commands/router.test.js +0 -92
  66. package/dist/commands/router.test.js.map +0 -7
  67. package/dist/llbot-ws-api.test.js +0 -32
  68. package/dist/llbot-ws-api.test.js.map +0 -7
  69. package/dist/official/events.test.js +0 -123
  70. package/dist/official/events.test.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/commands/handlers.ts"],
4
- "sourcesContent": ["/**\n * commands/handlers.ts \u2014 \u5185\u7F6E menu / ping / whoami / status / online / bind / join / kick / group\n */\n\nimport {\n getGroupBotState,\n getGroupInfo,\n sendGroupMessage,\n} from \"@sfmc-bds/sdk/node/qq-official\";\nimport {\n fetchBindMe,\n fetchJoinPending,\n fetchJoinSettings,\n fetchSfmcStatus,\n postAdminKick,\n postBindRequest,\n postBindUnbind,\n postJoinDecide,\n postJoinRequest,\n postJoinSettings,\n type DbEndpoint,\n} from \"./db-api.js\";\nimport { buildJoinSettingsPanel, settingsFromResponse } from \"./join-settings-ui.js\";\nimport { formatCommandMenu } from \"./menu-format.js\";\nimport type { CommandRegistry } from \"./registry.js\";\nimport type { CommandContext, CommandHandler, CommandResult } from \"./types.js\";\n\nfunction formatUptime(startedAt: number): string {\n const ms = Math.max(0, Date.now() - startedAt);\n const s = Math.floor(ms / 1000);\n const m = Math.floor(s / 60);\n const h = Math.floor(m / 60);\n if (h > 0) return `${h}h ${m % 60}m`;\n if (m > 0) return `${m}m ${s % 60}s`;\n return `${s}s`;\n}\n\nfunction dbEp(ctx: CommandContext): DbEndpoint | null {\n const host = ctx.runtimeInfo.dbHost;\n const port = ctx.runtimeInfo.dbPort;\n if (!host || !port) return null;\n return { host, port };\n}\n\nfunction isAdmin(ctx: CommandContext): boolean {\n const admins = ctx.runtimeInfo.adminOpenids ?? [];\n if (admins.length > 0 && admins.includes(ctx.inbound.userId)) return true;\n // \u7FA4\u7BA1\uFF1A\u6865\u4FA7\u5148\u653E\u884C\uFF1Bdb \u518D\u6309 treat_group_admins_as_admins \u9274\u6743\n return ctx.inbound.isGroupAdmin === true;\n}\n\nfunction asGroupAdminField(ctx: CommandContext): boolean {\n return ctx.inbound.isGroupAdmin === true;\n}\n\n/** \u62C9\u53D6\u5B98\u65B9\u7FA4 info + bot_state\uFF1B\u5931\u8D25\u8FD4\u56DE\u63D0\u793A\u884C */\nasync function fetchQqGroupLines(ctx: CommandContext): Promise<string[]> {\n const creds = ctx.runtimeInfo.officialCreds;\n const gid = ctx.runtimeInfo.groupOpenid || ctx.inbound.groupId;\n if (!creds || !gid || ctx.inbound.backend !== \"official\") return [];\n const lines: string[] = [];\n try {\n const [infoRes, stateRes] = await Promise.all([\n getGroupInfo(creds, gid),\n getGroupBotState(creds, gid),\n ]);\n if (infoRes.ok && infoRes.json && typeof infoRes.json === \"object\") {\n const j = infoRes.json as Record<string, unknown>;\n lines.push(`QQ\u7FA4\uFF1A${j.group_name ?? \"\u2014\"} \u00B7 \u6210\u5458 ${j.group_member_num ?? \"\u2014\"}`);\n } else if (!infoRes.ok) {\n const hint = /11253/.test(infoRes.error || infoRes.body || \"\")\n ? \"\u7FA4\u4FE1\u606F\u63A5\u53E3\u672A\u5F00\u901A\u767D\u540D\u5355(11253)\"\n : `\u7FA4\u4FE1\u606F\u5931\u8D25\uFF1A${(infoRes.error || \"\").slice(0, 60)}`;\n lines.push(hint);\n }\n if (stateRes.ok && stateRes.json && typeof stateRes.json === \"object\") {\n const j = stateRes.json as Record<string, unknown>;\n lines.push(\n `\u673A\u5668\u4EBA\uFF1A\u89D2\u8272=${j.member_role ?? \"\u2014\"} \u00B7 \u4E3B\u52A8\u63A8\u9001=${j.allow_proactive_msg === true ? \"\u5F00\" : \"\u5173\"} \u00B7 \u6536\u6D88\u606F=${j.recv_msg_setting ?? \"\u2014\"}`\n );\n }\n } catch (e) {\n lines.push(`\u7FA4\u4FE1\u606F\u5F02\u5E38\uFF1A${(e as Error).message}`);\n }\n return lines;\n}\n\nexport function createMenuHandler(registry: CommandRegistry): CommandHandler {\n return (): CommandResult => {\n const cmds = registry.userMenu().filter((c) => c.name !== \"menu\");\n return formatCommandMenu({\n title: \"SFMC \u6307\u4EE4\",\n subtitle: \"\u70B9\u6309\u94AE\u6216\u53D1\u540D\u79F0/\u7F16\u53F7\uFF1B\u7BA1\u7406\u5458\u53D1\u300C\u7BA1\u7406\u300D\u6253\u5F00\u7BA1\u7406\u83DC\u5355\u3002\",\n cmds,\n idPrefix: \"cmd\",\n footerMd: \"_\u5B98\u65B9\u4EC5 @\u673A\u5668\u4EBA \u89E6\u53D1\uFF1B\u6E38\u620F\u804A\u5929\u9700\u914D\u7F6E `bridge_channel_id`\u3002_\",\n footerText: \"\u5B98\u65B9\u4EC5 @\u673A\u5668\u4EBA \u89E6\u53D1\uFF1B\u6E38\u620F\u804A\u5929\u9700\u914D\u7F6E bridge_channel_id\u3002\",\n });\n };\n}\n\n/** \u7BA1\u7406\u5B50\u83DC\u5355\uFF1A\u4EC5\u7BA1\u7406\u5458\uFF1B\u5217\u51FA adminMenu \u6307\u4EE4 */\nexport function createAdminMenuHandler(registry: CommandRegistry): CommandHandler {\n return (ctx: CommandContext): CommandResult => {\n if (!isAdmin(ctx)) {\n return { text: \"\u4EC5\u7BA1\u7406\u5458\u53EF\u6253\u5F00\u7BA1\u7406\u83DC\u5355\uFF08\u9700\u5728 qq_admin_openids\uFF0C\u6216\u5F00\u542F\u7FA4\u7BA1\u89C6\u4F5C\u7BA1\u7406\u5458\uFF09\" };\n }\n const cmds = registry.adminMenu();\n if (cmds.length === 0) {\n return { text: \"\u6682\u65E0\u7BA1\u7406\u6307\u4EE4\" };\n }\n return formatCommandMenu({\n title: \"SFMC \u7BA1\u7406\",\n subtitle: \"\u4EE5\u4E0B\u4E3A\u7BA1\u7406\u6307\u4EE4\uFF1B\u4E5F\u53EF\u76F4\u63A5\u53D1\u300C\u8E22\u4EBA\u300D\u300C\u5F85\u5BA1\u300D\u7B49\u89E6\u53D1\u8BCD\u3002\",\n cmds,\n idPrefix: \"adm\",\n footerMd: \"_\u654F\u611F\u64CD\u4F5C\u8BF7\u786E\u8BA4\u5BF9\u8C61\u6B63\u786E\u3002_\",\n footerText: \"\u654F\u611F\u64CD\u4F5C\u8BF7\u786E\u8BA4\u5BF9\u8C61\u6B63\u786E\u3002\",\n });\n };\n}\n\nexport const pingHandler: CommandHandler = (ctx: CommandContext): CommandResult => {\n const { runtimeInfo, startedAt, inbound } = ctx;\n const parts = [\"pong\", `backend=${inbound.backend}`, `uptime=${formatUptime(startedAt)}`];\n if (inbound.backend === \"official\") {\n parts.push(`sandbox=${runtimeInfo.sandbox ? \"true\" : \"false\"}`);\n if (runtimeInfo.appIdHint) parts.push(`app=${runtimeInfo.appIdHint}`);\n }\n return { text: parts.join(\" \u00B7 \") };\n};\n\nexport const whoamiHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const { inbound } = ctx;\n const lines = [`\u4F60\u662F ${inbound.userName}`, `id=${inbound.userId}`, `group=${inbound.groupId}`];\n const ep = dbEp(ctx);\n if (ep) {\n try {\n const me = await fetchBindMe(ep, inbound.userId);\n if (me.bound && me.binding) {\n lines.push(`\u5DF2\u7ED1\u5B9A MC\uFF1A${me.binding.player_name || \"?\"} (${me.binding.player_xuid || \"?\"})`);\n } else {\n lines.push(\"\u672A\u7ED1\u5B9A MC\uFF08\u53D1\u9001\u300C\u7ED1\u5B9A\u300D\u83B7\u53D6\u9A8C\u8BC1\u7801\uFF09\");\n }\n } catch {\n lines.push(\"\u7ED1\u5B9A\u67E5\u8BE2\u5931\u8D25\uFF08db-server \u4E0D\u53EF\u8FBE\uFF09\");\n }\n }\n return { text: lines.join(\"\\n\") };\n};\n\nexport const statusHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const ep = dbEp(ctx);\n if (!ep) return { text: \"status\uFF1A\u672A\u914D\u7F6E db_host/db_port\" };\n try {\n const st = await fetchSfmcStatus(ep);\n const n = Array.isArray(st.online) ? st.online.length : 0;\n const day = st.world?.day != null ? String(st.world.day) : \"\u2014\";\n const diff = st.world?.difficulty ? String(st.world.difficulty) : \"\u2014\";\n const age =\n typeof st.updatedAt === \"number\" ? `${Math.max(0, Math.floor((Date.now() - st.updatedAt) / 1000))}s\u524D` : \"\u2014\";\n const host = st.host;\n const bds = st.processes?.bds;\n const db = st.processes?.db;\n const hostUp = host?.uptimeText || \"\u2014\";\n const bdsLine =\n bds?.state === \"running\"\n ? `\u8FD0\u884C\u4E2D \u00B7 ${bds.uptimeText || \"\u2014\"}${bds.pid ? ` (PID ${bds.pid})` : \"\"}`\n : \"\u672A\u8FD0\u884C\";\n const mem =\n host?.memory != null\n ? `${host.memory.usedMb ?? \"\u2014\"}/${host.memory.totalMb ?? \"\u2014\"} MB (${host.memory.usedPercent ?? \"\u2014\"}%)`\n : \"\u2014\";\n const cpu =\n host?.cpu != null ? `${host.cpu.cores ?? \"\u2014\"} \u6838 \u00B7 ${host.cpu.model || \"\u2014\"}` : \"\u2014\";\n const machine = host\n ? `${host.hostname || \"\u2014\"} \u00B7 ${host.platform || \"\u2014\"}/${host.arch || \"\u2014\"} ${host.release || \"\"}`.trim()\n : \"\u2014\";\n const note = st.note ? `\\n${st.note}` : n === 0 ? \"\\n\u6682\u65E0\u5728\u7EBF\u73A9\u5BB6\u6570\u636E\" : \"\";\n const qqLines = await fetchQqGroupLines(ctx);\n const text = [\n \"\u670D\u52A1\u5668\u72B6\u6001\",\n `\u5728\u7EBF\uFF1A${n} \u4EBA`,\n `\u4E16\u754C\u65E5\uFF1A${day}`,\n `\u96BE\u5EA6\uFF1A${diff}`,\n `\u4E3B\u673A\uFF1A${machine}`,\n `\u4E3B\u673A\u8FD0\u884C\uFF1A${hostUp}`,\n `BDS\uFF1A${bdsLine}`,\n `\u5185\u5B58\uFF1A${mem}`,\n `CPU\uFF1A${cpu}`,\n `db-server\uFF1A${db?.uptimeText || \"\u2014\"}${db?.pid ? ` (PID ${db.pid})` : \"\"}`,\n ...qqLines,\n `\u6570\u636E\uFF1A${age}${note}`,\n ].join(\"\\n\");\n const markdown = [\n \"## \u670D\u52A1\u5668\u72B6\u6001\",\n \"\",\n `- **\u5728\u7EBF**\uFF1A${n} \u4EBA`,\n `- **\u4E16\u754C\u65E5**\uFF1A${day}`,\n `- **\u96BE\u5EA6**\uFF1A${diff}`,\n `- **\u4E3B\u673A**\uFF1A${machine}`,\n `- **\u4E3B\u673A\u8FD0\u884C**\uFF1A${hostUp}`,\n `- **BDS**\uFF1A${bdsLine}`,\n `- **\u5185\u5B58**\uFF1A${mem}`,\n `- **CPU**\uFF1A${cpu}`,\n `- **db-server**\uFF1A${db?.uptimeText || \"\u2014\"}${db?.pid ? ` (PID ${db.pid})` : \"\"}`,\n ...qqLines.map((l) => `- ${l}`),\n `- **\u6570\u636E**\uFF1A${age}`,\n note ? `\\n_${(st.note || \"\u6682\u65E0\u5728\u7EBF\u73A9\u5BB6\u6570\u636E\").trim()}_` : \"\",\n ]\n .filter((line) => line !== \"\")\n .join(\"\\n\");\n return { text, markdown };\n } catch (e) {\n return { text: `status \u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\nconst ONLINE_CAP = 30;\n\nexport const onlineHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const ep = dbEp(ctx);\n if (!ep) return { text: \"online\uFF1A\u672A\u914D\u7F6E db_host/db_port\" };\n try {\n const st = await fetchSfmcStatus(ep);\n const list = Array.isArray(st.online) ? st.online : [];\n if (list.length === 0) {\n return { text: st.note || \"\u6682\u65E0\u5728\u7EBF\u73A9\u5BB6\" };\n }\n const shown = list.slice(0, ONLINE_CAP);\n const names = shown.map((p, i) => `${i + 1}. ${p.name || p.id || \"?\"}`).join(\"\\n\");\n const more = list.length > ONLINE_CAP ? `\\n\u2026\u53E6\u6709 ${list.length - ONLINE_CAP} \u4EBA\u672A\u5217\u51FA` : \"\";\n return { text: `\u5728\u7EBF ${list.length} \u4EBA\\n${names}${more}` };\n } catch (e) {\n return { text: `online \u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\nexport const bindHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const ep = dbEp(ctx);\n if (!ep) return { text: \"\u7ED1\u5B9A\uFF1A\u672A\u914D\u7F6E db_host/db_port\" };\n try {\n const { status, data } = await postBindRequest(ep, {\n openid: ctx.inbound.userId,\n qq_backend: ctx.inbound.backend,\n });\n if (status === 409 || data.error === \"already_bound\") {\n return {\n text: `\u4F60\u5DF2\u7ED1\u5B9A MC \u73A9\u5BB6\u300C${data.player_name || \"?\"}\u300D\u3002\u5982\u9700\u6362\u7ED1\u8BF7\u5148\u53D1\u9001\u300C\u89E3\u7ED1\u300D\u3002`,\n };\n }\n if (!data.success || !data.code) {\n return { text: `\u7533\u8BF7\u7ED1\u5B9A\u5931\u8D25\uFF1A${data.error || `HTTP ${status}`}` };\n }\n return {\n text: `\u7ED1\u5B9A\u7801\uFF1A${data.code}\\n\u8BF7\u5728\u6E38\u620F\u5185\u8F93\u5165 !bind\uFF0C\u7136\u540E\u5728 60 \u79D2\u5185\u53D1\u9001\u6B64\u6570\u5B57\u7801\uFF08\u4E0D\u8981\u5E26 !\uFF09\u3002`,\n markdown: `## \u7ED1\u5B9A\u7801 \\`${data.code}\\`\\n\\n1. \u6E38\u620F\u5185\u6267\u884C **!bind**\\n2. \u5728 **60 \u79D2\u5185**\u53D1\u9001\u672C\u6570\u5B57\u7801\uFF08\u4E0D\u8981\u5E26 \\`!\\`\uFF09\\n\\n_\u8D85\u65F6\u8BF7\u91CD\u65B0\u7533\u8BF7_`,\n };\n } catch (e) {\n return { text: `\u7ED1\u5B9A\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\nexport const unbindHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const ep = dbEp(ctx);\n if (!ep) return { text: \"\u89E3\u7ED1\uFF1A\u672A\u914D\u7F6E db_host/db_port\" };\n try {\n const { data } = await postBindUnbind(ep, { openid: ctx.inbound.userId });\n if (data.unbound) return { text: \"\u5DF2\u89E3\u9664 QQ\u2194MC \u7ED1\u5B9A\u3002\" };\n return { text: \"\u5F53\u524D\u6CA1\u6709\u7ED1\u5B9A\u8BB0\u5F55\u3002\" };\n } catch (e) {\n return { text: `\u89E3\u7ED1\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\nexport const groupInfoHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const lines = await fetchQqGroupLines(ctx);\n if (lines.length === 0) {\n return { text: \"\u7FA4\u4FE1\u606F\u4EC5\u5B98\u65B9\u540E\u7AEF\u53EF\u7528\uFF0C\u4E14\u9700\u914D\u7F6E qq_group_openid / \u51ED\u8BC1\u3002\" };\n }\n return { text: [\"QQ \u7FA4\u4FE1\u606F\", ...lines].join(\"\\n\") };\n};\n\nexport const joinHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const ep = dbEp(ctx);\n if (!ep) return { text: \"\u7533\u8BF7\u5165\u670D\uFF1A\u672A\u914D\u7F6E db_host/db_port\" };\n let playerName = ctx.inbound.text.replace(/^\\/?(\u7533\u8BF7\u5165\u670D|join)\\s*/i, \"\").trim();\n if (!playerName) {\n try {\n const me = await fetchBindMe(ep, ctx.inbound.userId);\n if (me.bound && me.binding?.player_name) playerName = String(me.binding.player_name);\n } catch {\n /* ignore */\n }\n }\n if (!playerName) {\n return { text: \"\u7528\u6CD5\uFF1A\u7533\u8BF7\u5165\u670D <\u73A9\u5BB6\u540D>\\n\uFF08\u5DF2\u7ED1\u5B9A\u53EF\u7701\u7565\u540D\u5B57\uFF09\" };\n }\n try {\n const { data } = await postJoinRequest(ep, {\n openid: ctx.inbound.userId,\n player_name: playerName,\n qq_backend: ctx.inbound.backend,\n });\n if (!data.success || !data.id) {\n if (data.error === \"join_allowlist_disabled\") {\n return { text: \"\u5165\u670D\u767D\u540D\u5355\u5DF2\u5173\u95ED\uFF08\u7BA1\u7406\u5458\u53EF\u53D1\u300C\u914D\u7F6E \u767D\u540D\u5355 \u5F00\u300D\uFF09\" };\n }\n return { text: `\u7533\u8BF7\u5931\u8D25\uFF1A${data.error || \"unknown\"}` };\n }\n if (data.auto_approved || data.status === \"approved\") {\n return {\n text: data.note\n ? `\u300C${playerName}\u300D${data.note}`\n : `\u5DF2\u81EA\u52A8\u901A\u8FC7\u300C${playerName}\u300D\u5165\u670D\uFF0C\u7B49\u5F85 BDS \u5199\u5165\u767D\u540D\u5355`,\n };\n }\n const admins = ctx.runtimeInfo.adminOpenids ?? [];\n const creds = ctx.runtimeInfo.officialCreds;\n const gid = ctx.runtimeInfo.groupOpenid || ctx.inbound.groupId;\n if (creds && gid && admins.length > 0 && ctx.inbound.backend === \"official\") {\n void sendGroupMessage(creds, {\n groupOpenid: gid,\n msgType: 2,\n markdown: `## \u5165\u670D\u7533\u8BF7\\n\\n\u73A9\u5BB6 **${playerName}**\\n\u7533\u8BF7\u4EBA \\`${ctx.inbound.userId.slice(0, 8)}\u2026\\`\\n\u8BF7\u6C42 id=\\`${data.id}\\``,\n keyboardButtons: [\n {\n id: `ap_${data.id}`,\n label: \"\u901A\u8FC7\",\n data: `join:approve:${data.id}`,\n actionType: 1,\n style: 1,\n permission: { type: 0, specify_user_ids: admins },\n },\n {\n id: `rj_${data.id}`,\n label: \"\u62D2\u7EDD\",\n data: `join:reject:${data.id}`,\n actionType: 1,\n style: 0,\n permission: { type: 0, specify_user_ids: admins },\n },\n ],\n }).catch(() => undefined);\n }\n const note = data.note ? `\\n${data.note}` : admins.length === 0 ? \"\\n\u672A\u914D\u7F6E qq_admin_openids\uFF0C\u7BA1\u7406\u5458\u6536\u4E0D\u5230\u901A\u77E5\" : \"\";\n return {\n text: `\u5DF2\u63D0\u4EA4\u5165\u670D\u7533\u8BF7\u300C${playerName}\u300D${note}`,\n buttons:\n ctx.inbound.backend === \"llbot\" && admins.length > 0\n ? [\n { id: \"a\", label: `\u901A\u8FC7 ${playerName}`, command: `/approve ${data.id}` },\n { id: \"r\", label: `\u62D2\u7EDD ${playerName}`, command: `/reject ${data.id}` },\n ]\n : undefined,\n };\n } catch (e) {\n return { text: `\u7533\u8BF7\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\nfunction parseOnOff(raw: string): boolean | null {\n const s = raw.trim().toLowerCase();\n if ([\"\u5F00\", \"\u5F00\u542F\", \"on\", \"true\", \"1\", \"yes\"].includes(s)) return true;\n if ([\"\u5173\", \"\u5173\u95ED\", \"off\", \"false\", \"0\", \"no\"].includes(s)) return false;\n return null;\n}\n\n/** \u7BA1\u7406\u5458\u67E5\u770B/\u5207\u6362 qq-link \u5165\u670D\u5F00\u5173\uFF08\u4E92\u52A8\u6309\u94AE\u9762\u677F\uFF09 */\nexport const joinConfigHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n if (!isAdmin(ctx)) return { text: \"\u4EC5\u7BA1\u7406\u5458\u53EF\u914D\u7F6E\u5165\u670D\u5F00\u5173\uFF08qq_admin_openids / \u7FA4\u7BA1\u89C6\u4F5C\u7BA1\u7406\u5458\uFF09\" };\n const ep = dbEp(ctx);\n if (!ep) return { text: \"\u914D\u7F6E\uFF1A\u672A\u8FDE\u63A5 db\" };\n\n const admins = ctx.runtimeInfo.adminOpenids ?? [];\n const rest = ctx.inbound.text.replace(/^\\/?(\u914D\u7F6E|config|\u5165\u670D\u914D\u7F6E)\\s*/i, \"\").trim();\n if (!rest) {\n try {\n const data = await fetchJoinSettings(ep);\n if (data.success === false) return { text: `\u8BFB\u53D6\u5931\u8D25\uFF1A${data.error || \"unknown\"}` };\n return buildJoinSettingsPanel({\n settings: settingsFromResponse(data),\n backend: ctx.inbound.backend,\n adminOpenids: admins,\n });\n } catch (e) {\n return { text: `\u8BFB\u53D6\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n }\n\n if (/^(\u7FA4\u7BA1|\u7FA4\u7BA1\u7406\u5458|treat|group.?admin)/i.test(rest)) {\n return {\n text: \"\u300C\u7FA4\u7BA1\u89C6\u4F5C\u7BA1\u7406\u5458\u300D\u53EA\u80FD\u6539 configs/qq_link.json \u7684 treat_group_admins_as_admins\uFF0C\u7FA4\u804A\u4E0D\u53EF\u6539\u3002\u53D1\u300C\u914D\u7F6E\u300D\u53EF\u67E5\u770B\u5F53\u524D\u503C\u3002\",\n };\n }\n\n const m = /^(\u767D\u540D\u5355|allowlist|\u5BA1\u6279|approval)\\s+(\\S+)/i.exec(rest);\n if (!m) {\n return { text: \"\u7528\u6CD5\uFF1A\u914D\u7F6E\\n\u3000\u3000\u3000\u6216\u70B9\u9762\u677F\u6309\u94AE\u5207\u6362\u767D\u540D\u5355/\u5BA1\u6279\" };\n }\n const which = m[1]!.toLowerCase();\n const onOff = parseOnOff(m[2]!);\n if (onOff === null) return { text: \"\u8BF7\u4F7F\u7528 \u5F00/\u5173\uFF08\u6216 on/off\uFF09\" };\n\n const body: {\n openid: string;\n as_group_admin?: boolean;\n allowlist_enabled?: boolean;\n require_approval?: boolean;\n } = {\n openid: ctx.inbound.userId,\n as_group_admin: asGroupAdminField(ctx),\n };\n if (which === \"\u767D\u540D\u5355\" || which === \"allowlist\") body.allowlist_enabled = onOff;\n else body.require_approval = onOff;\n\n try {\n const { data } = await postJoinSettings(ep, body);\n if (data.success === false) {\n if (data.error === \"not_admin\") {\n return { text: \"\u65E0\u6743\u9650\uFF08\u7FA4\u7BA1\u9700 configs/qq_link.json \u4E2D treat_group_admins_as_admins=true\uFF09\" };\n }\n if (data.error === \"immutable_field\") {\n return { text: data.note || \"\u8BE5\u5B57\u6BB5\u4E0D\u53EF\u7ECF\u7FA4\u804A\u4FEE\u6539\" };\n }\n return { text: `\u4FDD\u5B58\u5931\u8D25\uFF1A${data.error || \"unknown\"}` };\n }\n return buildJoinSettingsPanel({\n settings: settingsFromResponse(data),\n backend: ctx.inbound.backend,\n adminOpenids: admins,\n prefix: \"\u5DF2\u4FDD\u5B58\",\n });\n } catch (e) {\n return { text: `\u4FDD\u5B58\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\nexport const pendingHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n if (!isAdmin(ctx)) return { text: \"\u4EC5\u7BA1\u7406\u5458\u53EF\u67E5\u770B\u5F85\u5BA1\u5217\u8868\uFF08\u914D\u7F6E qq_admin_openids\uFF09\" };\n const ep = dbEp(ctx);\n if (!ep) return { text: \"\u5F85\u5BA1\uFF1A\u672A\u914D\u7F6E db\" };\n try {\n const data = await fetchJoinPending(ep, ctx.inbound.userId, asGroupAdminField(ctx));\n if (data.error) {\n if (data.error === \"not_admin\") {\n return { text: \"\u65E0\u6743\u9650\uFF08\u7FA4\u7BA1\u9700 treat_group_admins_as_admins=true\uFF09\" };\n }\n return { text: `\u5F85\u5BA1\u5931\u8D25\uFF1A${data.error}` };\n }\n const list = data.pending ?? [];\n if (list.length === 0) return { text: \"\u6682\u65E0\u5F85\u5BA1\u5165\u670D\u7533\u8BF7\" };\n const lines = list.map((r, i) => `${i + 1}. ${r.player_name || \"?\"} (${r.id})`);\n return { text: `\u5F85\u5BA1 ${list.length} \u6761\\n${lines.join(\"\\n\")}` };\n } catch (e) {\n return { text: `\u5F85\u5BA1\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\nexport const approveHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n if (!isAdmin(ctx)) return { text: \"\u4EC5\u7BA1\u7406\u5458\u53EF\u5BA1\u6279\" };\n const ep = dbEp(ctx);\n if (!ep) return { text: \"\u672A\u914D\u7F6E db\" };\n const id = ctx.inbound.text.replace(/^\\/?(approve|\u901A\u8FC7)\\s*/i, \"\").trim();\n if (!id) return { text: \"\u7528\u6CD5\uFF1A\u901A\u8FC7 <\u7533\u8BF7id>\" };\n try {\n const { data } = await postJoinDecide(ep, {\n id,\n decision: \"approve\",\n decided_by: ctx.inbound.userId,\n as_group_admin: asGroupAdminField(ctx),\n });\n if (data.success === false && data.error === \"not_admin\") {\n return { text: \"\u65E0\u6743\u9650\uFF08\u7FA4\u7BA1\u9700 treat_group_admins_as_admins=true\uFF09\" };\n }\n return { text: data.success === false ? `\u5931\u8D25\uFF1A${data.error}` : `\u5DF2\u901A\u8FC7\u300C${data.player_name || id}\u300D` };\n } catch (e) {\n return { text: `\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\nexport const rejectHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n if (!isAdmin(ctx)) return { text: \"\u4EC5\u7BA1\u7406\u5458\u53EF\u5BA1\u6279\" };\n const ep = dbEp(ctx);\n if (!ep) return { text: \"\u672A\u914D\u7F6E db\" };\n const id = ctx.inbound.text.replace(/^\\/?(reject|\u62D2\u7EDD)\\s*/i, \"\").trim();\n if (!id) return { text: \"\u7528\u6CD5\uFF1A\u62D2\u7EDD <\u7533\u8BF7id>\" };\n try {\n const { data } = await postJoinDecide(ep, {\n id,\n decision: \"reject\",\n decided_by: ctx.inbound.userId,\n as_group_admin: asGroupAdminField(ctx),\n });\n if (data.success === false && data.error === \"not_admin\") {\n return { text: \"\u65E0\u6743\u9650\uFF08\u7FA4\u7BA1\u9700 treat_group_admins_as_admins=true\uFF09\" };\n }\n return { text: data.success === false ? `\u5931\u8D25\uFF1A${data.error}` : `\u5DF2\u62D2\u7EDD\u300C${data.player_name || id}\u300D` };\n } catch (e) {\n return { text: `\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\n/** \u9891\u9053 + \u8F7B\u91CF\u81EA\u68C0\uFF08\u4EBA\u4EBA\u53EF\u7528\uFF09 */\nexport const channelHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const id = String(ctx.runtimeInfo.bridgeChannelId ?? \"\").trim();\n const lines: string[] = [\n \"\u3010\u804A\u5929\u4E92\u901A\u3011\",\n id ? `\u9891\u9053\uFF1A${id}` : \"\u9891\u9053\uFF1A\u672A\u914D\u7F6E\uFF08\u8BF7\u8BBE qq_config.json \u2192 bridge_channel_id \u5E76\u91CD\u542F db/qq/BDS\uFF09\",\n `\u540E\u7AEF\uFF1A${ctx.inbound.backend}${ctx.runtimeInfo.sandbox ? \" \u00B7 sandbox\" : \"\"}`,\n ];\n const ep = dbEp(ctx);\n if (!ep) {\n lines.push(\"db\uFF1A\u672A\u914D\u7F6E db_host/db_port\");\n } else {\n try {\n const st = await fetchSfmcStatus(ep);\n const bds = st.processes?.bds;\n const db = st.processes?.db;\n lines.push(`db-server\uFF1A${db?.state === \"stopped\" || db?.running === false ? \"\u672A\u8FD0\u884C\" : db?.uptimeText || \"\u53EF\u8FBE\"}${db?.pid ? ` (PID ${db.pid})` : \"\"}`);\n lines.push(\n `BDS\uFF1A${bds?.state === \"running\" || bds?.running === true ? `\u8FD0\u884C\u4E2D \u00B7 ${bds.uptimeText || \"\u2014\"}` : \"\u672A\u8FD0\u884C\"}`\n );\n } catch (e) {\n lines.push(`db\uFF1A\u4E0D\u53EF\u8FBE\uFF08${(e as Error).message}\uFF09`);\n }\n }\n lines.push(\"\u63D0\u793A\uFF1A\u5B98\u65B9\u4EC5 @\u673A\u5668\u4EBA \u7684\u975E\u6307\u4EE4\u6D88\u606F\u8FDB\u6E38\u620F\uFF1B\u6E38\u620F\u804A\u5929\u63A8\u7FA4\u8D70 MC\u2192QQ\u3002\");\n const text = lines.join(\"\\n\");\n return {\n text,\n markdown: text\n .split(\"\\n\")\n .map((l, i) => (i === 0 ? `## ${l.replace(/\u3010|\u3011/g, \"\")}` : `- ${l}`))\n .join(\"\\n\"),\n };\n};\n\n/** \u7BA1\u7406\u4FA7\u66F4\u5B8C\u6574\u7684\u81EA\u68C0 */\nexport const doctorHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n if (!isAdmin(ctx)) return { text: \"\u4EC5\u7BA1\u7406\u5458\u53EF\u6267\u884C\u81EA\u68C0\" };\n const base = await channelHandler(ctx);\n const extra: string[] = [\"\", \"\u3010\u7BA1\u7406\u81EA\u68C0\u3011\"];\n const admins = ctx.runtimeInfo.adminOpenids ?? [];\n extra.push(`\u7BA1\u7406\u5458 openid \u6570\uFF1A${admins.length}${admins.length === 0 ? \"\uFF08\u7A7A\u5219\u65E0\u6CD5\u5BA1\u6279/\u8E22\u4EBA\uFF09\" : \"\"}`);\n extra.push(`\u7FA4 openid\uFF1A${ctx.runtimeInfo.groupOpenid ? \"\u5DF2\u914D\u7F6E\" : \"\u672A\u914D\u7F6E\"}`);\n if (ctx.inbound.backend === \"official\") {\n extra.push(`\u51ED\u8BC1\uFF1A${ctx.runtimeInfo.officialCreds ? \"\u5DF2\u6CE8\u5165\" : \"\u7F3A\u5931\"}`);\n }\n const text = `${base.text}\\n${extra.join(\"\\n\")}`;\n return { text, markdown: `${base.markdown ?? base.text}\\n\\n### \u7BA1\u7406\u81EA\u68C0\\n\\n${extra.filter(Boolean).map((l) => `- ${l}`).join(\"\\n\")}` };\n};\n\nexport const kickHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n if (!isAdmin(ctx)) return { text: \"\u4EC5\u7BA1\u7406\u5458\u53EF\u8E22\u4EBA\uFF08\u914D\u7F6E qq_admin_openids\uFF09\" };\n const ep = dbEp(ctx);\n if (!ep) return { text: \"\u8E22\u4EBA\uFF1A\u672A\u914D\u7F6E db\" };\n const target = ctx.inbound.text.replace(/^\\/?(\u8E22\u4EBA|kick)\\s*/i, \"\").trim();\n if (!target) return { text: \"\u7528\u6CD5\uFF1A\u8E22\u4EBA <\u73A9\u5BB6\u540D>\" };\n try {\n const { data } = await postAdminKick(ep, {\n openid: ctx.inbound.userId,\n target_name: target,\n reason: \"QQ \u7BA1\u7406\u5458\u8E22\u51FA\",\n as_group_admin: asGroupAdminField(ctx),\n });\n if (!data.success) {\n if (data.error === \"not_admin\") {\n return { text: \"\u65E0\u6743\u9650\uFF08\u7FA4\u7BA1\u9700 treat_group_admins_as_admins=true\uFF09\" };\n }\n return { text: `\u8E22\u4EBA\u5165\u961F\u5931\u8D25\uFF1A${data.error || \"unknown\"}` };\n }\n return { text: `\u5DF2\u5C06\u300C${target}\u300D\u8E22\u4EBA\u8BF7\u6C42\u5165\u961F\uFF0C\u7B49\u5F85 BDS \u6267\u884C\u3002` };\n } catch (e) {\n return { text: `\u8E22\u4EBA\u5931\u8D25\uFF1A${(e as Error).message}` };\n }\n};\n\n/** \u6CE8\u518C\u5185\u7F6E\u6307\u4EE4\uFF08\u542B\u8FD0\u7EF4\u4E0E\u7ED1\u5B9A / \u5165\u670D\uFF09 */\nexport function registerBuiltinCommands(registry: CommandRegistry): void {\n registry.register({\n name: \"menu\",\n aliases: [\"\u83DC\u5355\", \"help\", \"\u5E2E\u52A9\", \"/help\", \"/\u83DC\u5355\", \"/menu\"],\n description: \"\u663E\u793A\u6307\u4EE4\u83DC\u5355\",\n handler: createMenuHandler(registry),\n });\n registry.register({\n name: \"ping\",\n aliases: [\"/ping\"],\n description: \"\u8FDE\u901A\u6027\u63A2\u6D4B\",\n handler: pingHandler,\n });\n registry.register({\n name: \"whoami\",\n aliases: [\"/whoami\", \"\u6211\u7684\u7ED1\u5B9A\"],\n description: \"\u67E5\u770B QQ id \u4E0E MC \u7ED1\u5B9A\",\n handler: whoamiHandler,\n });\n registry.register({\n name: \"status\",\n aliases: [\"\u72B6\u6001\", \"/status\", \"/\u72B6\u6001\"],\n description: \"\u670D\u52A1\u5668\u72B6\u6001\u6458\u8981\",\n handler: statusHandler,\n });\n registry.register({\n name: \"online\",\n aliases: [\"\u5728\u7EBF\", \"/online\", \"/\u5728\u7EBF\"],\n description: \"\u5728\u7EBF\u73A9\u5BB6\u540D\u5355\",\n handler: onlineHandler,\n });\n registry.register({\n name: \"bind\",\n aliases: [\"\u7ED1\u5B9A\", \"/bind\", \"/\u7ED1\u5B9A\"],\n description: \"\u7533\u8BF7 QQ\u2194MC \u7ED1\u5B9A\u7801\",\n handler: bindHandler,\n });\n registry.register({\n name: \"unbind\",\n aliases: [\"\u89E3\u7ED1\", \"/unbind\", \"/\u89E3\u7ED1\"],\n description: \"\u89E3\u9664 QQ\u2194MC \u7ED1\u5B9A\",\n handler: unbindHandler,\n });\n registry.register({\n name: \"join\",\n aliases: [\"\u7533\u8BF7\u5165\u670D\", \"/join\", \"/\u7533\u8BF7\u5165\u670D\"],\n description: \"\u7533\u8BF7\u52A0\u5165\u670D\u52A1\u5668\u767D\u540D\u5355\",\n handler: joinHandler,\n });\n registry.register({\n name: \"channel\",\n aliases: [\"\u9891\u9053\", \"/channel\", \"/\u9891\u9053\"],\n description: \"\u804A\u5929\u4E92\u901A\u9891\u9053\u4E0E\u8FDE\u901A\u81EA\u68C0\",\n handler: channelHandler,\n });\n registry.register({\n name: \"admin\",\n aliases: [\"\u7BA1\u7406\", \"/admin\", \"/\u7BA1\u7406\"],\n description: \"\u7BA1\u7406\u5B50\u83DC\u5355\uFF08\u7BA1\u7406\u5458\uFF09\",\n handler: createAdminMenuHandler(registry),\n });\n // \u2014\u2014 \u4EE5\u4E0B\u4EC5\u51FA\u73B0\u5728\u300C\u7BA1\u7406\u300D\u5B50\u83DC\u5355\uFF1B\u89E6\u53D1\u8BCD\u4ECD\u53EF\u76F4\u63A5\u8C03\u7528 \u2014\u2014\n registry.register({\n name: \"doctor\",\n aliases: [\"\u81EA\u68C0\", \"/doctor\", \"/\u81EA\u68C0\"],\n description: \"\u7BA1\u7406\u4FA7\u8FDE\u901A/\u914D\u7F6E\u81EA\u68C0\",\n handler: doctorHandler,\n adminMenu: true,\n });\n registry.register({\n name: \"group\",\n aliases: [\"\u7FA4\u4FE1\u606F\", \"/group\", \"/\u7FA4\u4FE1\u606F\"],\n description: \"QQ \u7FA4 OpenAPI \u6458\u8981\",\n handler: groupInfoHandler,\n adminMenu: true,\n });\n registry.register({\n name: \"config\",\n aliases: [\"\u914D\u7F6E\", \"\u5165\u670D\u914D\u7F6E\", \"/config\", \"/\u914D\u7F6E\"],\n description: \"\u5165\u670D\u767D\u540D\u5355/\u5BA1\u6279\u5F00\u5173\uFF08\u7BA1\u7406\u5458\uFF09\",\n handler: joinConfigHandler,\n adminMenu: true,\n });\n registry.register({\n name: \"pending\",\n aliases: [\"\u5F85\u5BA1\", \"/pending\", \"/\u5F85\u5BA1\"],\n description: \"\u5F85\u5BA1\u5165\u670D\u5217\u8868\uFF08\u7BA1\u7406\u5458\uFF09\",\n handler: pendingHandler,\n adminMenu: true,\n });\n registry.register({\n name: \"approve\",\n aliases: [\"\u901A\u8FC7\", \"/approve\", \"/\u901A\u8FC7\"],\n description: \"\u901A\u8FC7\u5165\u670D\u7533\u8BF7\uFF08\u7BA1\u7406\u5458\uFF09\",\n handler: approveHandler,\n adminMenu: true,\n });\n registry.register({\n name: \"reject\",\n aliases: [\"\u62D2\u7EDD\", \"/reject\", \"/\u62D2\u7EDD\"],\n description: \"\u62D2\u7EDD\u5165\u670D\u7533\u8BF7\uFF08\u7BA1\u7406\u5458\uFF09\",\n handler: rejectHandler,\n adminMenu: true,\n });\n registry.register({\n name: \"kick\",\n aliases: [\"\u8E22\u4EBA\", \"/kick\", \"/\u8E22\u4EBA\"],\n description: \"\u8E22\u51FA\u6E38\u620F\u5185\u73A9\u5BB6\uFF08\u7BA1\u7406\u5458\uFF09\",\n handler: kickHandler,\n adminMenu: true,\n });\n}\n\n"],
5
- "mappings": "AAIA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,wBAAwB,4BAA4B;AAC7D,SAAS,yBAAyB;AAIlC,SAAS,aAAa,WAA2B;AAC/C,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS;AAC7C,QAAM,IAAI,KAAK,MAAM,KAAK,GAAI;AAC9B,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,MAAI,IAAI,EAAG,QAAO,GAAG,CAAC,KAAK,IAAI,EAAE;AACjC,MAAI,IAAI,EAAG,QAAO,GAAG,CAAC,KAAK,IAAI,EAAE;AACjC,SAAO,GAAG,CAAC;AACb;AAEA,SAAS,KAAK,KAAwC;AACpD,QAAM,OAAO,IAAI,YAAY;AAC7B,QAAM,OAAO,IAAI,YAAY;AAC7B,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,SAAO,EAAE,MAAM,KAAK;AACtB;AAEA,SAAS,QAAQ,KAA8B;AAC7C,QAAM,SAAS,IAAI,YAAY,gBAAgB,CAAC;AAChD,MAAI,OAAO,SAAS,KAAK,OAAO,SAAS,IAAI,QAAQ,MAAM,EAAG,QAAO;AAErE,SAAO,IAAI,QAAQ,iBAAiB;AACtC;AAEA,SAAS,kBAAkB,KAA8B;AACvD,SAAO,IAAI,QAAQ,iBAAiB;AACtC;AAGA,eAAe,kBAAkB,KAAwC;AACvE,QAAM,QAAQ,IAAI,YAAY;AAC9B,QAAM,MAAM,IAAI,YAAY,eAAe,IAAI,QAAQ;AACvD,MAAI,CAAC,SAAS,CAAC,OAAO,IAAI,QAAQ,YAAY,WAAY,QAAO,CAAC;AAClE,QAAM,QAAkB,CAAC;AACzB,MAAI;AACF,UAAM,CAAC,SAAS,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC5C,aAAa,OAAO,GAAG;AAAA,MACvB,iBAAiB,OAAO,GAAG;AAAA,IAC7B,CAAC;AACD,QAAI,QAAQ,MAAM,QAAQ,QAAQ,OAAO,QAAQ,SAAS,UAAU;AAClE,YAAM,IAAI,QAAQ;AAClB,YAAM,KAAK,iBAAO,EAAE,cAAc,QAAG,sBAAS,EAAE,oBAAoB,QAAG,EAAE;AAAA,IAC3E,WAAW,CAAC,QAAQ,IAAI;AACtB,YAAM,OAAO,QAAQ,KAAK,QAAQ,SAAS,QAAQ,QAAQ,EAAE,IACzD,8EACA,wCAAU,QAAQ,SAAS,IAAI,MAAM,GAAG,EAAE,CAAC;AAC/C,YAAM,KAAK,IAAI;AAAA,IACjB;AACA,QAAI,SAAS,MAAM,SAAS,QAAQ,OAAO,SAAS,SAAS,UAAU;AACrE,YAAM,IAAI,SAAS;AACnB,YAAM;AAAA,QACJ,wCAAU,EAAE,eAAe,QAAG,kCAAW,EAAE,wBAAwB,OAAO,WAAM,QAAG,4BAAU,EAAE,oBAAoB,QAAG;AAAA,MACxH;AAAA,IACF;AAAA,EACF,SAAS,GAAG;AACV,UAAM,KAAK,uCAAU,EAAY,OAAO,EAAE;AAAA,EAC5C;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,UAA2C;AAC3E,SAAO,MAAqB;AAC1B,UAAM,OAAO,SAAS,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AAChE,WAAO,kBAAkB;AAAA,MACvB,OAAO;AAAA,MACP,UAAU;AAAA,MACV;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AACF;AAGO,SAAS,uBAAuB,UAA2C;AAChF,SAAO,CAAC,QAAuC;AAC7C,QAAI,CAAC,QAAQ,GAAG,GAAG;AACjB,aAAO,EAAE,MAAM,gLAA8C;AAAA,IAC/D;AACA,UAAM,OAAO,SAAS,UAAU;AAChC,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO,EAAE,MAAM,uCAAS;AAAA,IAC1B;AACA,WAAO,kBAAkB;AAAA,MACvB,OAAO;AAAA,MACP,UAAU;AAAA,MACV;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AACF;AAEO,MAAM,cAA8B,CAAC,QAAuC;AACjF,QAAM,EAAE,aAAa,WAAW,QAAQ,IAAI;AAC5C,QAAM,QAAQ,CAAC,QAAQ,WAAW,QAAQ,OAAO,IAAI,UAAU,aAAa,SAAS,CAAC,EAAE;AACxF,MAAI,QAAQ,YAAY,YAAY;AAClC,UAAM,KAAK,WAAW,YAAY,UAAU,SAAS,OAAO,EAAE;AAC9D,QAAI,YAAY,UAAW,OAAM,KAAK,OAAO,YAAY,SAAS,EAAE;AAAA,EACtE;AACA,SAAO,EAAE,MAAM,MAAM,KAAK,QAAK,EAAE;AACnC;AAEO,MAAM,gBAAgC,OAAO,QAAgD;AAClG,QAAM,EAAE,QAAQ,IAAI;AACpB,QAAM,QAAQ,CAAC,gBAAM,QAAQ,QAAQ,IAAI,MAAM,QAAQ,MAAM,IAAI,SAAS,QAAQ,OAAO,EAAE;AAC3F,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,IAAI;AACN,QAAI;AACF,YAAM,KAAK,MAAM,YAAY,IAAI,QAAQ,MAAM;AAC/C,UAAI,GAAG,SAAS,GAAG,SAAS;AAC1B,cAAM,KAAK,8BAAU,GAAG,QAAQ,eAAe,GAAG,KAAK,GAAG,QAAQ,eAAe,GAAG,GAAG;AAAA,MACzF,OAAO;AACL,cAAM,KAAK,qGAAqB;AAAA,MAClC;AAAA,IACF,QAAQ;AACN,YAAM,KAAK,8EAAuB;AAAA,IACpC;AAAA,EACF;AACA,SAAO,EAAE,MAAM,MAAM,KAAK,IAAI,EAAE;AAClC;AAEO,MAAM,gBAAgC,OAAO,QAAgD;AAClG,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,iDAA6B;AACrD,MAAI;AACF,UAAM,KAAK,MAAM,gBAAgB,EAAE;AACnC,UAAM,IAAI,MAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,OAAO,SAAS;AACxD,UAAM,MAAM,GAAG,OAAO,OAAO,OAAO,OAAO,GAAG,MAAM,GAAG,IAAI;AAC3D,UAAM,OAAO,GAAG,OAAO,aAAa,OAAO,GAAG,MAAM,UAAU,IAAI;AAClE,UAAM,MACJ,OAAO,GAAG,cAAc,WAAW,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,IAAI,IAAI,GAAG,aAAa,GAAI,CAAC,CAAC,YAAO;AAC1G,UAAM,OAAO,GAAG;AAChB,UAAM,MAAM,GAAG,WAAW;AAC1B,UAAM,KAAK,GAAG,WAAW;AACzB,UAAM,SAAS,MAAM,cAAc;AACnC,UAAM,UACJ,KAAK,UAAU,YACX,2BAAS,IAAI,cAAc,QAAG,GAAG,IAAI,MAAM,SAAS,IAAI,GAAG,MAAM,EAAE,KACnE;AACN,UAAM,MACJ,MAAM,UAAU,OACZ,GAAG,KAAK,OAAO,UAAU,QAAG,IAAI,KAAK,OAAO,WAAW,QAAG,QAAQ,KAAK,OAAO,eAAe,QAAG,OAChG;AACN,UAAM,MACJ,MAAM,OAAO,OAAO,GAAG,KAAK,IAAI,SAAS,QAAG,gBAAQ,KAAK,IAAI,SAAS,QAAG,KAAK;AAChF,UAAM,UAAU,OACZ,GAAG,KAAK,YAAY,QAAG,SAAM,KAAK,YAAY,QAAG,IAAI,KAAK,QAAQ,QAAG,IAAI,KAAK,WAAW,EAAE,GAAG,KAAK,IACnG;AACJ,UAAM,OAAO,GAAG,OAAO;AAAA,EAAK,GAAG,IAAI,KAAK,MAAM,IAAI,uDAAe;AACjE,UAAM,UAAU,MAAM,kBAAkB,GAAG;AAC3C,UAAM,OAAO;AAAA,MACX;AAAA,MACA,qBAAM,CAAC;AAAA,MACP,2BAAO,GAAG;AAAA,MACV,qBAAM,IAAI;AAAA,MACV,qBAAM,OAAO;AAAA,MACb,iCAAQ,MAAM;AAAA,MACd,YAAO,OAAO;AAAA,MACd,qBAAM,GAAG;AAAA,MACT,YAAO,GAAG;AAAA,MACV,kBAAa,IAAI,cAAc,QAAG,GAAG,IAAI,MAAM,SAAS,GAAG,GAAG,MAAM,EAAE;AAAA,MACtE,GAAG;AAAA,MACH,qBAAM,GAAG,GAAG,IAAI;AAAA,IAClB,EAAE,KAAK,IAAI;AACX,UAAM,WAAW;AAAA,MACf;AAAA,MACA;AAAA,MACA,2BAAY,CAAC;AAAA,MACb,iCAAa,GAAG;AAAA,MAChB,2BAAY,IAAI;AAAA,MAChB,2BAAY,OAAO;AAAA,MACnB,uCAAc,MAAM;AAAA,MACpB,kBAAa,OAAO;AAAA,MACpB,2BAAY,GAAG;AAAA,MACf,kBAAa,GAAG;AAAA,MAChB,wBAAmB,IAAI,cAAc,QAAG,GAAG,IAAI,MAAM,SAAS,GAAG,GAAG,MAAM,EAAE;AAAA,MAC5E,GAAG,QAAQ,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;AAAA,MAC9B,2BAAY,GAAG;AAAA,MACf,OAAO;AAAA,IAAO,GAAG,QAAQ,oDAAY,KAAK,CAAC,MAAM;AAAA,IACnD,EACG,OAAO,CAAC,SAAS,SAAS,EAAE,EAC5B,KAAK,IAAI;AACZ,WAAO,EAAE,MAAM,SAAS;AAAA,EAC1B,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,4BAAc,EAAY,OAAO,GAAG;AAAA,EACrD;AACF;AAEA,MAAM,aAAa;AAEZ,MAAM,gBAAgC,OAAO,QAAgD;AAClG,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,iDAA6B;AACrD,MAAI;AACF,UAAM,KAAK,MAAM,gBAAgB,EAAE;AACnC,UAAM,OAAO,MAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,SAAS,CAAC;AACrD,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO,EAAE,MAAM,GAAG,QAAQ,uCAAS;AAAA,IACrC;AACA,UAAM,QAAQ,KAAK,MAAM,GAAG,UAAU;AACtC,UAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI;AACjF,UAAM,OAAO,KAAK,SAAS,aAAa;AAAA,qBAAS,KAAK,SAAS,UAAU,8BAAU;AACnF,WAAO,EAAE,MAAM,gBAAM,KAAK,MAAM;AAAA,EAAO,KAAK,GAAG,IAAI,GAAG;AAAA,EACxD,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,4BAAc,EAAY,OAAO,GAAG;AAAA,EACrD;AACF;AAEO,MAAM,cAA8B,OAAO,QAAgD;AAChG,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,uDAAyB;AACjD,MAAI;AACF,UAAM,EAAE,QAAQ,KAAK,IAAI,MAAM,gBAAgB,IAAI;AAAA,MACjD,QAAQ,IAAI,QAAQ;AAAA,MACpB,YAAY,IAAI,QAAQ;AAAA,IAC1B,CAAC;AACD,QAAI,WAAW,OAAO,KAAK,UAAU,iBAAiB;AACpD,aAAO;AAAA,QACL,MAAM,iDAAc,KAAK,eAAe,GAAG;AAAA,MAC7C;AAAA,IACF;AACA,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,MAAM;AAC/B,aAAO,EAAE,MAAM,6CAAU,KAAK,SAAS,QAAQ,MAAM,EAAE,GAAG;AAAA,IAC5D;AACA,WAAO;AAAA,MACL,MAAM,2BAAO,KAAK,IAAI;AAAA;AAAA,MACtB,UAAU,2BAAY,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IACjC;AAAA,EACF,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,iCAAS,EAAY,OAAO,GAAG;AAAA,EAChD;AACF;AAEO,MAAM,gBAAgC,OAAO,QAAgD;AAClG,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,uDAAyB;AACjD,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,eAAe,IAAI,EAAE,QAAQ,IAAI,QAAQ,OAAO,CAAC;AACxE,QAAI,KAAK,QAAS,QAAO,EAAE,MAAM,mDAAgB;AACjD,WAAO,EAAE,MAAM,yDAAY;AAAA,EAC7B,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,iCAAS,EAAY,OAAO,GAAG;AAAA,EAChD;AACF;AAEO,MAAM,mBAAmC,OAAO,QAAgD;AACrG,QAAM,QAAQ,MAAM,kBAAkB,GAAG;AACzC,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,MAAM,kIAAwC;AAAA,EACzD;AACA,SAAO,EAAE,MAAM,CAAC,yBAAU,GAAG,KAAK,EAAE,KAAK,IAAI,EAAE;AACjD;AAEO,MAAM,cAA8B,OAAO,QAAgD;AAChG,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,mEAA2B;AACnD,MAAI,aAAa,IAAI,QAAQ,KAAK,QAAQ,uBAAuB,EAAE,EAAE,KAAK;AAC1E,MAAI,CAAC,YAAY;AACf,QAAI;AACF,YAAM,KAAK,MAAM,YAAY,IAAI,IAAI,QAAQ,MAAM;AACnD,UAAI,GAAG,SAAS,GAAG,SAAS,YAAa,cAAa,OAAO,GAAG,QAAQ,WAAW;AAAA,IACrF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI,CAAC,YAAY;AACf,WAAO,EAAE,MAAM,gIAA4B;AAAA,EAC7C;AACA,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,gBAAgB,IAAI;AAAA,MACzC,QAAQ,IAAI,QAAQ;AAAA,MACpB,aAAa;AAAA,MACb,YAAY,IAAI,QAAQ;AAAA,IAC1B,CAAC;AACD,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,IAAI;AAC7B,UAAI,KAAK,UAAU,2BAA2B;AAC5C,eAAO,EAAE,MAAM,+IAA4B;AAAA,MAC7C;AACA,aAAO,EAAE,MAAM,iCAAQ,KAAK,SAAS,SAAS,GAAG;AAAA,IACnD;AACA,QAAI,KAAK,iBAAiB,KAAK,WAAW,YAAY;AACpD,aAAO;AAAA,QACL,MAAM,KAAK,OACP,SAAI,UAAU,SAAI,KAAK,IAAI,KAC3B,uCAAS,UAAU;AAAA,MACzB;AAAA,IACF;AACA,UAAM,SAAS,IAAI,YAAY,gBAAgB,CAAC;AAChD,UAAM,QAAQ,IAAI,YAAY;AAC9B,UAAM,MAAM,IAAI,YAAY,eAAe,IAAI,QAAQ;AACvD,QAAI,SAAS,OAAO,OAAO,SAAS,KAAK,IAAI,QAAQ,YAAY,YAAY;AAC3E,WAAK,iBAAiB,OAAO;AAAA,QAC3B,aAAa;AAAA,QACb,SAAS;AAAA,QACT,UAAU;AAAA;AAAA,iBAAmB,UAAU;AAAA,uBAAa,IAAI,QAAQ,OAAO,MAAM,GAAG,CAAC,CAAC;AAAA,oBAAgB,KAAK,EAAE;AAAA,QACzG,iBAAiB;AAAA,UACf;AAAA,YACE,IAAI,MAAM,KAAK,EAAE;AAAA,YACjB,OAAO;AAAA,YACP,MAAM,gBAAgB,KAAK,EAAE;AAAA,YAC7B,YAAY;AAAA,YACZ,OAAO;AAAA,YACP,YAAY,EAAE,MAAM,GAAG,kBAAkB,OAAO;AAAA,UAClD;AAAA,UACA;AAAA,YACE,IAAI,MAAM,KAAK,EAAE;AAAA,YACjB,OAAO;AAAA,YACP,MAAM,eAAe,KAAK,EAAE;AAAA,YAC5B,YAAY;AAAA,YACZ,OAAO;AAAA,YACP,YAAY,EAAE,MAAM,GAAG,kBAAkB,OAAO;AAAA,UAClD;AAAA,QACF;AAAA,MACF,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IAC1B;AACA,UAAM,OAAO,KAAK,OAAO;AAAA,EAAK,KAAK,IAAI,KAAK,OAAO,WAAW,IAAI,gGAAoC;AACtG,WAAO;AAAA,MACL,MAAM,mDAAW,UAAU,SAAI,IAAI;AAAA,MACnC,SACE,IAAI,QAAQ,YAAY,WAAW,OAAO,SAAS,IAC/C;AAAA,QACE,EAAE,IAAI,KAAK,OAAO,gBAAM,UAAU,IAAI,SAAS,YAAY,KAAK,EAAE,GAAG;AAAA,QACrE,EAAE,IAAI,KAAK,OAAO,gBAAM,UAAU,IAAI,SAAS,WAAW,KAAK,EAAE,GAAG;AAAA,MACtE,IACA;AAAA,IACR;AAAA,EACF,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,iCAAS,EAAY,OAAO,GAAG;AAAA,EAChD;AACF;AAEA,SAAS,WAAW,KAA6B;AAC/C,QAAM,IAAI,IAAI,KAAK,EAAE,YAAY;AACjC,MAAI,CAAC,UAAK,gBAAM,MAAM,QAAQ,KAAK,KAAK,EAAE,SAAS,CAAC,EAAG,QAAO;AAC9D,MAAI,CAAC,UAAK,gBAAM,OAAO,SAAS,KAAK,IAAI,EAAE,SAAS,CAAC,EAAG,QAAO;AAC/D,SAAO;AACT;AAGO,MAAM,oBAAoC,OAAO,QAAgD;AACtG,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,8IAA0C;AAC5E,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,0CAAY;AAEpC,QAAM,SAAS,IAAI,YAAY,gBAAgB,CAAC;AAChD,QAAM,OAAO,IAAI,QAAQ,KAAK,QAAQ,4BAA4B,EAAE,EAAE,KAAK;AAC3E,MAAI,CAAC,MAAM;AACT,QAAI;AACF,YAAM,OAAO,MAAM,kBAAkB,EAAE;AACvC,UAAI,KAAK,YAAY,MAAO,QAAO,EAAE,MAAM,iCAAQ,KAAK,SAAS,SAAS,GAAG;AAC7E,aAAO,uBAAuB;AAAA,QAC5B,UAAU,qBAAqB,IAAI;AAAA,QACnC,SAAS,IAAI,QAAQ;AAAA,QACrB,cAAc;AAAA,MAChB,CAAC;AAAA,IACH,SAAS,GAAG;AACV,aAAO,EAAE,MAAM,iCAAS,EAAY,OAAO,GAAG;AAAA,IAChD;AAAA,EACF;AAEA,MAAI,iCAAiC,KAAK,IAAI,GAAG;AAC/C,WAAO;AAAA,MACL,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,IAAI,wCAAwC,KAAK,IAAI;AAC3D,MAAI,CAAC,GAAG;AACN,WAAO,EAAE,MAAM,oIAA2B;AAAA,EAC5C;AACA,QAAM,QAAQ,EAAE,CAAC,EAAG,YAAY;AAChC,QAAM,QAAQ,WAAW,EAAE,CAAC,CAAE;AAC9B,MAAI,UAAU,KAAM,QAAO,EAAE,MAAM,4DAAoB;AAEvD,QAAM,OAKF;AAAA,IACF,QAAQ,IAAI,QAAQ;AAAA,IACpB,gBAAgB,kBAAkB,GAAG;AAAA,EACvC;AACA,MAAI,UAAU,wBAAS,UAAU,YAAa,MAAK,oBAAoB;AAAA,MAClE,MAAK,mBAAmB;AAE7B,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,iBAAiB,IAAI,IAAI;AAChD,QAAI,KAAK,YAAY,OAAO;AAC1B,UAAI,KAAK,UAAU,aAAa;AAC9B,eAAO,EAAE,MAAM,iHAAoE;AAAA,MACrF;AACA,UAAI,KAAK,UAAU,mBAAmB;AACpC,eAAO,EAAE,MAAM,KAAK,QAAQ,+DAAa;AAAA,MAC3C;AACA,aAAO,EAAE,MAAM,iCAAQ,KAAK,SAAS,SAAS,GAAG;AAAA,IACnD;AACA,WAAO,uBAAuB;AAAA,MAC5B,UAAU,qBAAqB,IAAI;AAAA,MACnC,SAAS,IAAI,QAAQ;AAAA,MACrB,cAAc;AAAA,MACd,QAAQ;AAAA,IACV,CAAC;AAAA,EACH,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,iCAAS,EAAY,OAAO,GAAG;AAAA,EAChD;AACF;AAEO,MAAM,iBAAiC,OAAO,QAAgD;AACnG,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,8GAAmC;AACrE,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,0CAAY;AACpC,MAAI;AACF,UAAM,OAAO,MAAM,iBAAiB,IAAI,IAAI,QAAQ,QAAQ,kBAAkB,GAAG,CAAC;AAClF,QAAI,KAAK,OAAO;AACd,UAAI,KAAK,UAAU,aAAa;AAC9B,eAAO,EAAE,MAAM,qFAA6C;AAAA,MAC9D;AACA,aAAO,EAAE,MAAM,iCAAQ,KAAK,KAAK,GAAG;AAAA,IACtC;AACA,UAAM,OAAO,KAAK,WAAW,CAAC;AAC9B,QAAI,KAAK,WAAW,EAAG,QAAO,EAAE,MAAM,mDAAW;AACjD,UAAM,QAAQ,KAAK,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,eAAe,GAAG,KAAK,EAAE,EAAE,GAAG;AAC9E,WAAO,EAAE,MAAM,gBAAM,KAAK,MAAM;AAAA,EAAO,MAAM,KAAK,IAAI,CAAC,GAAG;AAAA,EAC5D,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,iCAAS,EAAY,OAAO,GAAG;AAAA,EAChD;AACF;AAEO,MAAM,iBAAiC,OAAO,QAAgD;AACnG,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,6CAAU;AAC5C,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,wBAAS;AACjC,QAAM,KAAK,IAAI,QAAQ,KAAK,QAAQ,wBAAwB,EAAE,EAAE,KAAK;AACrE,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,kDAAe;AACvC,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,eAAe,IAAI;AAAA,MACxC;AAAA,MACA,UAAU;AAAA,MACV,YAAY,IAAI,QAAQ;AAAA,MACxB,gBAAgB,kBAAkB,GAAG;AAAA,IACvC,CAAC;AACD,QAAI,KAAK,YAAY,SAAS,KAAK,UAAU,aAAa;AACxD,aAAO,EAAE,MAAM,qFAA6C;AAAA,IAC9D;AACA,WAAO,EAAE,MAAM,KAAK,YAAY,QAAQ,qBAAM,KAAK,KAAK,KAAK,2BAAO,KAAK,eAAe,EAAE,SAAI;AAAA,EAChG,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,qBAAO,EAAY,OAAO,GAAG;AAAA,EAC9C;AACF;AAEO,MAAM,gBAAgC,OAAO,QAAgD;AAClG,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,6CAAU;AAC5C,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,wBAAS;AACjC,QAAM,KAAK,IAAI,QAAQ,KAAK,QAAQ,uBAAuB,EAAE,EAAE,KAAK;AACpE,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,kDAAe;AACvC,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,eAAe,IAAI;AAAA,MACxC;AAAA,MACA,UAAU;AAAA,MACV,YAAY,IAAI,QAAQ;AAAA,MACxB,gBAAgB,kBAAkB,GAAG;AAAA,IACvC,CAAC;AACD,QAAI,KAAK,YAAY,SAAS,KAAK,UAAU,aAAa;AACxD,aAAO,EAAE,MAAM,qFAA6C;AAAA,IAC9D;AACA,WAAO,EAAE,MAAM,KAAK,YAAY,QAAQ,qBAAM,KAAK,KAAK,KAAK,2BAAO,KAAK,eAAe,EAAE,SAAI;AAAA,EAChG,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,qBAAO,EAAY,OAAO,GAAG;AAAA,EAC9C;AACF;AAGO,MAAM,iBAAiC,OAAO,QAAgD;AACnG,QAAM,KAAK,OAAO,IAAI,YAAY,mBAAmB,EAAE,EAAE,KAAK;AAC9D,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA,KAAK,qBAAM,EAAE,KAAK;AAAA,IAClB,qBAAM,IAAI,QAAQ,OAAO,GAAG,IAAI,YAAY,UAAU,kBAAe,EAAE;AAAA,EACzE;AACA,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,IAAI;AACP,UAAM,KAAK,4CAAwB;AAAA,EACrC,OAAO;AACL,QAAI;AACF,YAAM,KAAK,MAAM,gBAAgB,EAAE;AACnC,YAAM,MAAM,GAAG,WAAW;AAC1B,YAAM,KAAK,GAAG,WAAW;AACzB,YAAM,KAAK,kBAAa,IAAI,UAAU,aAAa,IAAI,YAAY,QAAQ,uBAAQ,IAAI,cAAc,cAAI,GAAG,IAAI,MAAM,SAAS,GAAG,GAAG,MAAM,EAAE,EAAE;AAC/I,YAAM;AAAA,QACJ,YAAO,KAAK,UAAU,aAAa,KAAK,YAAY,OAAO,2BAAS,IAAI,cAAc,QAAG,KAAK,oBAAK;AAAA,MACrG;AAAA,IACF,SAAS,GAAG;AACV,YAAM,KAAK,mCAAW,EAAY,OAAO,QAAG;AAAA,IAC9C;AAAA,EACF;AACA,QAAM,KAAK,kLAAsC;AACjD,QAAM,OAAO,MAAM,KAAK,IAAI;AAC5B,SAAO;AAAA,IACL;AAAA,IACA,UAAU,KACP,MAAM,IAAI,EACV,IAAI,CAAC,GAAG,MAAO,MAAM,IAAI,MAAM,EAAE,QAAQ,QAAQ,EAAE,CAAC,KAAK,KAAK,CAAC,EAAG,EAClE,KAAK,IAAI;AAAA,EACd;AACF;AAGO,MAAM,gBAAgC,OAAO,QAAgD;AAClG,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,yDAAY;AAC9C,QAAM,OAAO,MAAM,eAAe,GAAG;AACrC,QAAM,QAAkB,CAAC,IAAI,sCAAQ;AACrC,QAAM,SAAS,IAAI,YAAY,gBAAgB,CAAC;AAChD,QAAM,KAAK,yCAAgB,OAAO,MAAM,GAAG,OAAO,WAAW,IAAI,kEAAgB,EAAE,EAAE;AACrF,QAAM,KAAK,sBAAY,IAAI,YAAY,cAAc,uBAAQ,oBAAK,EAAE;AACpE,MAAI,IAAI,QAAQ,YAAY,YAAY;AACtC,UAAM,KAAK,qBAAM,IAAI,YAAY,gBAAgB,uBAAQ,cAAI,EAAE;AAAA,EACjE;AACA,QAAM,OAAO,GAAG,KAAK,IAAI;AAAA,EAAK,MAAM,KAAK,IAAI,CAAC;AAC9C,SAAO,EAAE,MAAM,UAAU,GAAG,KAAK,YAAY,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA,EAAmB,MAAM,OAAO,OAAO,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,GAAG;AACnI;AAEO,MAAM,cAA8B,OAAO,QAAgD;AAChG,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,sFAA+B;AACjE,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,EAAE,MAAM,0CAAY;AACpC,QAAM,SAAS,IAAI,QAAQ,KAAK,QAAQ,qBAAqB,EAAE,EAAE,KAAK;AACtE,MAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,sDAAc;AAC1C,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,cAAc,IAAI;AAAA,MACvC,QAAQ,IAAI,QAAQ;AAAA,MACpB,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,gBAAgB,kBAAkB,GAAG;AAAA,IACvC,CAAC;AACD,QAAI,CAAC,KAAK,SAAS;AACjB,UAAI,KAAK,UAAU,aAAa;AAC9B,eAAO,EAAE,MAAM,qFAA6C;AAAA,MAC9D;AACA,aAAO,EAAE,MAAM,6CAAU,KAAK,SAAS,SAAS,GAAG;AAAA,IACrD;AACA,WAAO,EAAE,MAAM,qBAAM,MAAM,sFAAqB;AAAA,EAClD,SAAS,GAAG;AACV,WAAO,EAAE,MAAM,iCAAS,EAAY,OAAO,GAAG;AAAA,EAChD;AACF;AAGO,SAAS,wBAAwB,UAAiC;AACvE,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,QAAQ,gBAAM,SAAS,iBAAO,OAAO;AAAA,IACrD,aAAa;AAAA,IACb,SAAS,kBAAkB,QAAQ;AAAA,EACrC,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,OAAO;AAAA,IACjB,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,WAAW,0BAAM;AAAA,IAC3B,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,WAAW,eAAK;AAAA,IAChC,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,WAAW,eAAK;AAAA,IAChC,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,SAAS,eAAK;AAAA,IAC9B,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,WAAW,eAAK;AAAA,IAChC,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,4BAAQ,SAAS,2BAAO;AAAA,IAClC,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,YAAY,eAAK;AAAA,IACjC,aAAa;AAAA,IACb,SAAS;AAAA,EACX,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,UAAU,eAAK;AAAA,IAC/B,aAAa;AAAA,IACb,SAAS,uBAAuB,QAAQ;AAAA,EAC1C,CAAC;AAED,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,WAAW,eAAK;AAAA,IAChC,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,sBAAO,UAAU,qBAAM;AAAA,IACjC,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,4BAAQ,WAAW,eAAK;AAAA,IACxC,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,YAAY,eAAK;AAAA,IACjC,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,YAAY,eAAK;AAAA,IACjC,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,WAAW,eAAK;AAAA,IAChC,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACD,WAAS,SAAS;AAAA,IAChB,MAAM;AAAA,IACN,SAAS,CAAC,gBAAM,SAAS,eAAK;AAAA,IAC9B,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,EACb,CAAC;AACH;",
4
+ "sourcesContent": ["/**\n * commands/handlers.ts \u2014 \u5185\u7F6E menu / ping / whoami / status / online / bind / group\n */\n\nimport { getGroupBotState, getGroupInfo } from \"@sfmc-bds/sdk/node/qq-official\";\nimport { log } from \"../log.js\";\nimport {\n fetchBindMe,\n fetchContent,\n fetchQqEventSettings,\n fetchSfmcStatus,\n postBindRequest,\n postBindUnbind,\n postQqEventSettings,\n type DbEndpoint,\n type QqEventSettings,\n type SfmcStatusResponse,\n} from \"./db-api.js\";\nimport { formatAccountCard } from \"./account-format.js\";\nimport { formatModuleLines, formatPackLines, formatPackMarkdown } from \"./content-format.js\";\nimport { formatCard, formatCommandMenu } from \"./menu-format.js\";\nimport type { CommandRegistry } from \"./registry.js\";\nimport type { CommandContext, CommandHandler, CommandResult } from \"./types.js\";\n\nfunction formatUptime(startedAt: number): string {\n const ms = Math.max(0, Date.now() - startedAt);\n const s = Math.floor(ms / 1000);\n const m = Math.floor(s / 60);\n const h = Math.floor(m / 60);\n if (h > 0) return `${h}h ${m % 60}m`;\n if (m > 0) return `${m}m ${s % 60}s`;\n return `${s}s`;\n}\n\nfunction dbEp(ctx: CommandContext): DbEndpoint | null {\n const host = ctx.runtimeInfo.dbHost;\n const port = ctx.runtimeInfo.dbPort;\n if (!host || !port) return null;\n return { host, port };\n}\n\nfunction isAdmin(ctx: CommandContext): boolean {\n return ctx.adminAuthorized === true;\n}\n\nfunction failure(error: unknown): CommandResult {\n log.warn(`QQ \u64CD\u4F5C\u5931\u8D25: ${String(error)}`);\n return { text: \"\u64CD\u4F5C\u6682\u65F6\u672A\u5B8C\u6210\uFF0C\u8BF7\u7A0D\u540E\u67E5\u8BE2\u72B6\u6001\u6216\u8054\u7CFB\u7BA1\u7406\u5458\uFF1B\u8BF7\u52FF\u8FDE\u7EED\u91CD\u590D\u63D0\u4EA4\u4FEE\u6539\u3002\" };\n}\n\nfunction asGroupAdminField(ctx: CommandContext): boolean {\n return ctx.inbound.isGroupAdmin === true;\n}\n\n/** \u62C9\u53D6\u5B98\u65B9\u7FA4 info + bot_state\uFF1B\u5931\u8D25\u8FD4\u56DE\u63D0\u793A\u884C */\nasync function fetchQqGroupLines(ctx: CommandContext): Promise<string[]> {\n const creds = ctx.runtimeInfo.officialCreds;\n const gid = ctx.runtimeInfo.groupOpenid || (ctx.inbound.scene !== \"c2c\" ? ctx.inbound.groupId : \"\");\n if (!creds || !gid || ctx.inbound.backend !== \"official\") return [];\n const lines: string[] = [];\n try {\n const [infoRes, stateRes] = await Promise.all([getGroupInfo(creds, gid), getGroupBotState(creds, gid)]);\n if (infoRes.ok && infoRes.json && typeof infoRes.json === \"object\") {\n const j = infoRes.json as Record<string, unknown>;\n lines.push(`QQ\u7FA4\uFF1A${j[\"group_name\"] ?? \"\u2014\"} \u00B7 \u6210\u5458 ${j[\"group_member_num\"] ?? \"\u2014\"}`);\n } else if (!infoRes.ok) {\n const hint = /11253/.test(infoRes.error || infoRes.body || \"\")\n ? \"\u7FA4\u4FE1\u606F\u63A5\u53E3\u672A\u5F00\u901A\u767D\u540D\u5355(11253)\"\n : `\u7FA4\u4FE1\u606F\u5931\u8D25\uFF1A${(infoRes.error || \"\").slice(0, 60)}`;\n lines.push(hint);\n }\n if (stateRes.ok && stateRes.json && typeof stateRes.json === \"object\") {\n const j = stateRes.json as Record<string, unknown>;\n lines.push(\n `\u673A\u5668\u4EBA\uFF1A\u89D2\u8272=${j[\"member_role\"] ?? \"\u2014\"} \u00B7 \u4E3B\u52A8\u63A8\u9001=${j[\"allow_proactive_msg\"] === true ? \"\u5F00\" : \"\u5173\"} \u00B7 \u6536\u6D88\u606F=${j[\"recv_msg_setting\"] ?? \"\u2014\"}`\n );\n }\n } catch (e) {\n lines.push(`\u7FA4\u4FE1\u606F\u5F02\u5E38\uFF1A${(e as Error).message}`);\n }\n return lines;\n}\n\nexport function createMenuHandler(registry: CommandRegistry): CommandHandler {\n return (ctx) =>\n formatCommandMenu({\n title: \"\u4E1C\u65B9\u72AC\u660E\u6E56\",\n home: true,\n subtitle: \"\u6B22\u8FCE\u56DE\u6765\uFF0C\u4ECA\u5929\u4E5F\u4E00\u8D77\u73A9\u5427 (\u2267\u2207\u2266)\uFF89\\n\\n\u67E5\u8BE2\u670D\u52A1\u5668\u4FE1\u606F\uFF0C\u6216\u7BA1\u7406\u4F60\u7684\u6E38\u620F\u8D26\u53F7\u3002\",\n cmds: registry\n .all()\n .filter((c) => c.group === \"home\" && c.name !== \"menu\" && (c.permission !== \"admin\" || isAdmin(ctx))),\n idPrefix: \"home\",\n footerMd: \"\",\n footerText: \"\",\n });\n}\n\nexport function createAdminMenuHandler(registry: CommandRegistry): CommandHandler {\n return (ctx) => {\n if (!isAdmin(ctx)) return { text: \"\u5F53\u524D\u6CA1\u6709\u7BA1\u7406\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002\" };\n return formatCommandMenu({\n title: \"\u670D\u52A1\u5668\u7BA1\u7406\",\n subtitle: \"\u7BA1\u7406\u670D\u52A1\u5668\u4E0E\u7FA4\u63A8\u9001\u3002\",\n cmds: registry.adminMenu(),\n idPrefix: \"admin\",\n footerMd: \"\",\n footerText: \"\",\n });\n };\n}\n\nfunction sectionHandler(registry: CommandRegistry, group: \"server\", title: string): CommandHandler {\n return () =>\n formatCommandMenu({\n title,\n subtitle: \"\u67E5\u770B\u8FD0\u884C\u72B6\u6001\u3001\u5728\u7EBF\u73A9\u5BB6\u548C\u8FDE\u63A5\u65B9\u5F0F\u3002\",\n cmds: registry.all().filter((c) => c.group === group),\n idPrefix: group,\n footerMd: \"\",\n footerText: \"\",\n });\n}\n\nfunction helpHandler(registry: CommandRegistry): CommandHandler {\n return (ctx) => {\n const trigger =\n ctx.inbound.backend === \"official\"\n ? \"\u7FA4\u5185\u5F00\u542F\u300C\u63A5\u6536\u6240\u6709\u6D88\u606F\u300D\u540E\u53EF\u76F4\u63A5\u53D1\u9001\u6307\u4EE4\uFF1B\u5426\u5219\u8BF7 @\u673A\u5668\u4EBA\u3002\u5355\u804A\u76F4\u63A5\u53D1\u9001\u3002\"\n : \"\u76F4\u63A5\u53D1\u9001\u547D\u4EE4\uFF0C\u6216\u5728\u83DC\u5355\u6253\u5F00\u540E 60 \u79D2\u5185\u56DE\u590D\u7F16\u53F7\u3002\";\n const sections = [\n [\"server\", \"\u670D\u52A1\u5668\"],\n [\"account\", \"\u6211\u7684\u8D26\u53F7\"],\n [\"admin\", \"\u7BA1\u7406\"],\n ] as const;\n const lines = [trigger];\n for (const [group, title] of sections) {\n const commands = registry.all().filter((c) => c.group === group && (c.permission !== \"admin\" || isAdmin(ctx)));\n if (!commands.length) continue;\n lines.push(\n \"\",\n `\u3010${title}\u3011`,\n ...commands.map((c) => `${c.name === \"ip\" ? \"ip\" : c.aliases[0] || c.name}\uFF1A${c.description}`)\n );\n }\n lines.push(\"\", \"\u53D1\u9001 \u83DC\u5355 \u8FD4\u56DE\u9996\u9875\uFF0C\u53D1\u9001 \u53D6\u6D88 \u53D6\u6D88\u5F85\u786E\u8BA4\u64CD\u4F5C\u3002\", \"\u539F\u6709\u82F1\u6587\u547D\u4EE4\u53CA /\u547D\u4EE4 \u65B9\u5F0F\u4ECD\u53EF\u4F7F\u7528\u3002\");\n return formatCard(\"\u4F7F\u7528\u5E2E\u52A9\", lines);\n };\n}\n\nexport const serverVersionHandler: CommandHandler = async (ctx) => {\n const ep = dbEp(ctx);\n if (ep) {\n try {\n const status = await fetchSfmcStatus(ep);\n const bds = status.processes?.bds;\n if (bds?.state === \"running\" && bds.version)\n return formatCard(\"\u7248\u672C\", [\"\u6E38\u620F\u7C7B\u578B\uFF1A\u57FA\u5CA9\u7248\", `\u5F53\u524D BDS \u7248\u672C\uFF1A${bds.version}`]);\n } catch (error) {\n log.warn(`BDS \u7248\u672C\u67E5\u8BE2\u5931\u8D25: ${String(error)}`);\n }\n }\n return {\n text: ctx.runtimeInfo.publicServer?.version\n ? `\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u5B9E\u9645 BDS \u7248\u672C\u3002\\n\u7BA1\u7406\u5458\u63D0\u4F9B\u7684\u5165\u670D\u8BF4\u660E\uFF1A${ctx.runtimeInfo.publicServer.version}`\n : \"\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u5B9E\u9645 BDS \u7248\u672C\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u786E\u8BA4\u5165\u670D\u7248\u672C\u3002\",\n };\n};\nexport const serverAddressHandler: CommandHandler = (ctx) => {\n const info = ctx.runtimeInfo.publicServer;\n return formatCard(\n \"\u8FDE\u63A5\u5730\u5740\",\n info?.address\n ? [\n \"\u6E38\u620F\u7C7B\u578B\uFF1A\u57FA\u5CA9\u7248\",\n `\u670D\u52A1\u5668\u5730\u5740\uFF1A${info.address}`,\n `\u7AEF\u53E3\uFF1A${info.port ?? 19132}`,\n \"\",\n \"\u5728\u6E38\u620F\u5185\u9009\u62E9\u300C\u6DFB\u52A0\u670D\u52A1\u5668\u300D\uFF0C\u586B\u5199\u4EE5\u4E0A\u4FE1\u606F\u3002\",\n ]\n : [\"\u6682\u672A\u516C\u5E03\u670D\u52A1\u5668\u5730\u5740\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u83B7\u53D6\u3002\"]\n );\n};\n\nexport const pingHandler: CommandHandler = (ctx) => ({\n text: `\u673A\u5668\u4EBA\u8FDE\u63A5\u6B63\u5E38\uFF0C\u5DF2\u8FD0\u884C ${formatUptime(ctx.startedAt)}`,\n});\n\nexport const whoamiHandler: CommandHandler = async (ctx) => {\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n const me = await fetchBindMe(ep, ctx.inbound.userId);\n if (me.success === false) return failure(\"\u7ED1\u5B9A\u67E5\u8BE2\u5931\u8D25\");\n return {\n ...formatAccountCard({\n bound: !!me.bound,\n ...(me.binding?.player_name ? { playerName: me.binding.player_name } : {}),\n ...(me.profile ? { profile: me.profile } : {}),\n }),\n buttons: me.bound\n ? [{ id: \"unbind\", label: \"\u89E3\u7ED1\", command: \"/unbind\" }]\n : [{ id: \"bind\", label: \"\u7ED1\u5B9A\", command: \"/bind\" }],\n };\n};\n\nexport const statusHandler: CommandHandler = async (ctx) => {\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n let st: SfmcStatusResponse;\n try {\n st = await fetchSfmcStatus(ep);\n } catch (error) {\n log.warn(`\u67E5\u670D\u72B6\u6001\u63A5\u53E3\u4E0D\u53EF\u7528: ${String(error)}`);\n return formatCard(\"\u670D\u52A1\u5668\u72B6\u6001\", [\"\u6682\u65F6\u65E0\u6CD5\u8FDE\u63A5\u72B6\u6001\u670D\u52A1\uFF0C\u65E0\u6CD5\u786E\u8BA4\u6E38\u620F\u670D\u52A1\u5668\u662F\u5426\u8FD0\u884C\u3002\", \"\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u8054\u7CFB\u7BA1\u7406\u5458\u3002\"]);\n }\n const state = st.processes?.bds;\n const running = state?.state === \"running\" || state?.running === true;\n const stopped = state?.state === \"stopped\" || state?.running === false;\n const onlineText = stopped\n ? \"0 \u4EBA\"\n : st.note || !Array.isArray(st.online)\n ? \"\u6570\u636E\u6682\u4E0D\u53EF\u786E\u8BA4\"\n : `${st.online.length} \u4EBA`;\n const age =\n typeof st.updatedAt === \"number\" ? `${Math.max(0, Math.floor((Date.now() - st.updatedAt) / 1000))} \u79D2\u524D` : \"\u672A\u77E5\";\n return {\n ...formatCard(\"\u670D\u52A1\u5668\u72B6\u6001\", [\n `\u8FD0\u884C\u72B6\u6001\uFF1A${running ? \"\u8FD0\u884C\u4E2D\" : stopped ? \"\u672A\u8FD0\u884C\" : \"\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\"}`,\n `\u5728\u7EBF\u73A9\u5BB6\uFF1A${onlineText}`,\n `\u4E16\u754C\u65E5\uFF1A${st.world?.day ?? \"\u672A\u77E5\"}`,\n `\u96BE\u5EA6\uFF1A${st.world?.difficulty ?? \"\u672A\u77E5\"}`,\n `\u6570\u636E\u66F4\u65B0\uFF1A${age}`,\n ...(st.note && running ? [\"\u5728\u7EBF\u6570\u636E\u6682\u4E0D\u53EF\u786E\u8BA4\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002\"] : []),\n ]),\n buttons: [\n { id: \"online\", label: \"\u5728\u7EBF\u73A9\u5BB6\", command: \"/online\" },\n { id: \"version\", label: \"\u7248\u672C\", command: \"/version\" },\n { id: \"ip\", label: \"\u8FDE\u63A5\u5730\u5740\", command: \"/ip\" },\n { id: \"refresh_status\", label: \"\u5237\u65B0\u72B6\u6001\", command: \"/status\" },\n ],\n };\n};\n\nexport const onlineHandler: CommandHandler = async (ctx) => {\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n const st = await fetchSfmcStatus(ep);\n if (st.processes?.bds?.state === \"stopped\") return formatCard(\"\u5728\u7EBF\u73A9\u5BB6\", [\"\u670D\u52A1\u5668\u672A\u8FD0\u884C\uFF0C\u5F53\u524D\u6CA1\u6709\u5728\u7EBF\u73A9\u5BB6\u3002\"]);\n if (!Array.isArray(st.online) || st.note) return { text: \"\u5728\u7EBF\u6570\u636E\u6682\u4E0D\u53EF\u786E\u8BA4\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002\" };\n if (!st.online.length) return formatCard(\"\u5728\u7EBF\u73A9\u5BB6\", [\"\u5F53\u524D\u6CA1\u6709\u5728\u7EBF\u73A9\u5BB6\u3002\"]);\n return {\n ...formatCard(\"\u5728\u7EBF\u73A9\u5BB6\", [\n `\u5F53\u524D\u5728\u7EBF ${st.online.length} \u4EBA`,\n \"\",\n ...st.online.map((p, i) => `${i + 1}. ${p.name || \"\u672A\u547D\u540D\u73A9\u5BB6\"}`),\n ]),\n };\n};\n\nexport const bindHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n try {\n const { status, data } = await postBindRequest(ep, {\n openid: ctx.inbound.userId,\n qq_backend: ctx.inbound.backend,\n });\n if (status === 409 || data.error === \"already_bound\") {\n return {\n text: `\u4F60\u5DF2\u7ED1\u5B9A MC \u73A9\u5BB6\u300C${data.player_name || \"?\"}\u300D\u3002\u5982\u9700\u6362\u7ED1\u8BF7\u5148\u53D1\u9001\u300C\u89E3\u7ED1\u300D\u3002`,\n };\n }\n if (!data.success || !data.code) {\n return failure(data.error);\n }\n // \u672A\u7ED1\u5B9A\u4E5F\u80FD\u8FDB\u670D\uFF0C\u4F46\u6E38\u620F\u5185\u4F1A\u88AB\u9501\u6210\u8BBF\u5BA2\uFF1B\u9A8C\u8BC1\u7801\u5FC5\u987B\u5728\u6E38\u620F\u804A\u5929\u91CC\u6838\u9500\u3002\n return formatCard(\"\u7ED1\u5B9A\u8D26\u53F7\", [\n `\u7ED1\u5B9A\u7801\uFF1A${data.code}`,\n \"\",\n \"\u8FDB\u5165\u670D\u52A1\u5668\u540E\u5B8C\u6210\u4E0B\u9762\u4E24\u6B65\uFF1A\",\n \"1. \u5728\u6E38\u620F\u5185\u6267\u884C /c:bind\",\n \"2. \u5728 60 \u79D2\u5185\u628A\u4EE5\u4E0A\u7EAF\u6570\u5B57\u9A8C\u8BC1\u7801\u53D1\u5230\u6E38\u620F\u804A\u5929\",\n \"\",\n \"\u7ED1\u5B9A\u6210\u529F\u540E\u5373\u53EF\u81EA\u7531\u6D3B\u52A8\u3002\",\n \"\u8D85\u65F6\u8BF7\u91CD\u65B0\u53D1\u9001\u300C\u7ED1\u5B9A\u300D\u83B7\u53D6\u9A8C\u8BC1\u7801\u3002\",\n ]);\n } catch (e) {\n return failure(e);\n }\n};\n\nexport const unbindHandler: CommandHandler = async (ctx) => {\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n const me = await fetchBindMe(ep, ctx.inbound.userId);\n if (me.success === false) return failure(\"\u7ED1\u5B9A\u67E5\u8BE2\u5931\u8D25\");\n if (!me.bound || !me.binding) return { text: \"\u5F53\u524D\u6CA1\u6709\u7ED1\u5B9A\u8BB0\u5F55\u3002\" };\n const original = me.binding;\n return {\n text: \"\u786E\u8BA4\u89E3\u7ED1\",\n confirmation: {\n summary: `\u5373\u5C06\u89E3\u9664\u4F60\u4E0E\u300C${original.player_name || \"\u672A\u547D\u540D\u89D2\u8272\"}\u300D\u7684\u7ED1\u5B9A\u3002\u4E4B\u540E\u9700\u8981\u91CD\u65B0\u7533\u8BF7\u9A8C\u8BC1\u7801\u624D\u80FD\u7ED1\u5B9A\u3002`,\n execute: async (confirmed) => {\n const current = await fetchBindMe(ep, confirmed.inbound.userId);\n if (current.success === false) return failure(\"\u7ED1\u5B9A\u6838\u9A8C\u5931\u8D25\");\n if (\n !current.bound ||\n current.binding?.player_xuid !== original.player_xuid ||\n current.binding?.bound_at !== original.bound_at\n ) {\n return { text: \"\u7ED1\u5B9A\u72B6\u6001\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u67E5\u8BE2\u300C\u6211\u7684\u8D26\u53F7\u300D\u540E\u518D\u64CD\u4F5C\u3002\" };\n }\n const { data } = await postBindUnbind(ep, { openid: confirmed.inbound.userId });\n if (data.success === false) return failure(data.error);\n return { text: data.unbound ? \"\u5DF2\u89E3\u9664 QQ \u4E0E\u6E38\u620F\u89D2\u8272\u7684\u7ED1\u5B9A\u3002\" : \"\u5F53\u524D\u6CA1\u6709\u7ED1\u5B9A\u8BB0\u5F55\u3002\" };\n },\n },\n };\n};\n\nexport const groupInfoHandler: CommandHandler = async (ctx: CommandContext): Promise<CommandResult> => {\n const lines = await fetchQqGroupLines(ctx);\n if (lines.length === 0) {\n return { text: \"\u7FA4\u4FE1\u606F\u4EC5\u5B98\u65B9\u540E\u7AEF\u53EF\u7528\uFF0C\u4E14\u9700\u914D\u7F6E official.group_openid / \u51ED\u8BC1\u3002\" };\n }\n return { text: [\"QQ \u7FA4\u4FE1\u606F\", ...lines].join(\"\\n\") };\n};\n\n/**\n * \u300C\u5165\u670D\u300D\u8BF4\u660E\u9875\u3002\n * \u4E0D\u518D\u8D70\u5165\u670D\u7533\u8BF7\u3002\u73A9\u5BB6\u76F4\u63A5\u8FDB\u670D\uFF1B\u672A\u7ED1\u5B9A\u4E3A\u8BBF\u5BA2\u4E14\u4E0D\u80FD\u79FB\u52A8\uFF0C\u7ED1\u5B9A\u5199\u5165\u81EA\u6709\u767D\u540D\u5355\u540E\u5373\u53EF\u6E38\u73A9\u3002\n */\nexport const entryGuideHandler: CommandHandler = (): CommandResult =>\n formatCard(\"\u8FDB\u670D\u8BF4\u660E\", [\n \"\u76F4\u63A5\u8FDB\u5165\u670D\u52A1\u5668\u5373\u53EF\u3002\",\n \"\",\n \"\u672A\u7ED1\u5B9A\u7684\u89D2\u8272\u53EF\u4EE5\u8FDB\u670D\uFF0C\u4F46\u65E0\u6CD5\u79FB\u52A8\uFF0C\u6743\u9650\u4E3A\u8BBF\u5BA2\u3002\",\n \"\u804A\u5929\u680F\u4F1A\u63D0\u793A\u7ED1\u5B9A\u6B65\u9AA4\u3002\",\n \"\u5728 QQ \u53D1\u9001\u300C\u7ED1\u5B9A\u300D\u83B7\u53D6\u9A8C\u8BC1\u7801\uFF0C\u8FDB\u670D\u540E\u6267\u884C /c:bind\uFF0C\u518D\u628A\u9A8C\u8BC1\u7801\u53D1\u5230\u6E38\u620F\u804A\u5929\u3002\",\n \"\u7ED1\u5B9A\u6210\u529F\u540E\u5373\u53EF\u6B63\u5E38\u6E38\u73A9\u3002\",\n ]);\n\n/**\n * \u65E7\u7684\u5165\u670D\u7533\u8BF7\u3001\u5BA1\u6279\u548C\u767D\u540D\u5355\u5F00\u5173\u3002\n * \u4FDD\u7559\u8FD9\u4E9B\u89E6\u53D1\u8BCD\uFF0C\u8BA9\u65E7\u6309\u94AE\u548C\u4E60\u60EF\u547D\u4EE4\u6709\u660E\u786E\u56DE\u590D\uFF1B\u4E0D\u518D\u521B\u5EFA\u7533\u8BF7\uFF0C\u4E5F\u4E0D\u518D\u6539\u5BA1\u6279\u5F00\u5173\u3002\n */\nexport const retiredJoinFlowHandler: CommandHandler = (): CommandResult => ({\n text: \"\u5165\u670D\u7533\u8BF7\u5DF2\u5173\u95ED\u3002\u76F4\u63A5\u8FDB\u5165\u670D\u52A1\u5668\uFF0C\u5728\u6E38\u620F\u5185\u6309\u804A\u5929\u63D0\u793A\u5B8C\u6210\u7ED1\u5B9A\u540E\u5373\u53EF\u6E38\u73A9\u3002\u7ED1\u5B9A\u6210\u529F\u4F1A\u5199\u5165\u767D\u540D\u5355\u5E76\u89E3\u9664\u8BBF\u5BA2\u9650\u5236\u3002\",\n});\n\nconst EVENT_SWITCHES = [\n [\"enabled\", \"\u603B\u5F00\u5173\"],\n [\"start\", \"\u542F\u52A8\"],\n [\"stop\", \"\u505C\u670D\"],\n [\"crash\", \"\u5F02\u5E38\u9000\u51FA\"],\n [\"join\", \"\u4E0A\u7EBF\"],\n [\"leave\", \"\u4E0B\u7EBF\"],\n [\"death\", \"\u6B7B\u4EA1\"],\n] as const;\n\nfunction eventSettingsPanel(settings: QqEventSettings, prefix = \"\"): CommandResult {\n const rows: Array<[string, string]> = [\n ...EVENT_SWITCHES.map(([field, label]): [string, string] => [label, settings[field] ? \"\u5F00\" : \"\u5173\"]),\n [\"\u805A\u5408\u95F4\u9694\", `${settings.window_sec} \u79D2`],\n ];\n const textRows = rows.map(([label, value]) => `\u2502 ${label}${\"\u3000\".repeat(4 - label.length)} \u2502 ${value} \u2502`);\n const buttons = EVENT_SWITCHES.map(([field, label]) => ({\n id: `events_${field}`,\n label: `${label} ${settings[field] ? \"\u5173\" : \"\u5F00\"}`,\n command: `/events ${label} ${settings[field] ? \"\u5173\" : \"\u5F00\"}`,\n }));\n buttons.push({ id: \"events_window\", label: \"\u805A\u5408\u95F4\u9694\", command: \"/events \u95F4\u9694\" });\n return {\n text: [\n \"\u63A8\u9001\u8BBE\u7F6E\",\n ...(prefix ? [prefix] : []),\n \"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\",\n \"\u2502 \u9879\u76EE\u3000\u3000 \u2502 \u72B6\u6001\u3000 \u2502\",\n \"\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\",\n ...textRows,\n \"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\",\n `\u73A9\u5BB6\u4E8B\u4EF6\u7EA6 ${settings.window_sec} \u79D2\u5408\u5E76\u53D1\u9001\uFF1B\u542F\u505C\u4E0E\u5F02\u5E38\u9000\u51FA\u5373\u65F6\u53D1\u9001\u3002`,\n ].join(\"\\n\"),\n markdown: [\n \"## \u63A8\u9001\u8BBE\u7F6E\",\n ...(prefix ? [\"\", prefix] : []),\n \"\",\n \"| \u9879\u76EE | \u72B6\u6001 |\",\n \"| --- | --- |\",\n ...rows.map(([label, value]) => `| ${label} | **${value}** |`),\n \"\",\n `_\u73A9\u5BB6\u4E8B\u4EF6\u7EA6 ${settings.window_sec} \u79D2\u5408\u5E76\u53D1\u9001\uFF1B\u542F\u505C\u4E0E\u5F02\u5E38\u9000\u51FA\u5373\u65F6\u53D1\u9001_`,\n ].join(\"\\n\"),\n buttons,\n };\n}\n\nexport const eventSettingsHandler: CommandHandler = async (ctx): Promise<CommandResult> => {\n if (!isAdmin(ctx)) return { text: \"\u5F53\u524D\u6CA1\u6709\u7BA1\u7406\u6743\u9650\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002\" };\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n const rest = ctx.inbound.text.replace(/^\\/?(?:events|\u4E8B\u4EF6\u63A8\u9001|\u4E8B\u4EF6\u914D\u7F6E)\\s*/i, \"\").trim();\n try {\n if (!rest) {\n const data = await fetchQqEventSettings(ep);\n return data.success && data.settings ? eventSettingsPanel(data.settings) : failure(data.error);\n }\n if (rest === \"\u95F4\u9694\") {\n const data = await fetchQqEventSettings(ep);\n if (!data.success || !data.settings) return failure(data.error);\n return {\n ...formatCard(\"\u805A\u5408\u95F4\u9694\", [\n `\u5F53\u524D\uFF1A${data.settings.window_sec} \u79D2`,\n \"\u73A9\u5BB6\u8FDB\u51FA\u53CA\u6B7B\u4EA1\u901A\u77E5\u4F1A\u5728\u8FD9\u6BB5\u65F6\u95F4\u5185\u5408\u5E76\u3002\",\n \"\u4E5F\u53EF\u53D1\u9001\u300C\u4E8B\u4EF6\u63A8\u9001 \u95F4\u9694 \u79D2\u6570\u300D\uFF0C\u8303\u56F4 5\u2013600 \u79D2\u3002\",\n ]),\n buttons: [30, 60, 120].map((seconds) => ({\n id: `events_window_${seconds}`,\n label: `${seconds} \u79D2`,\n command: `/events \u95F4\u9694 ${seconds}`,\n })),\n };\n }\n const interval = /^\u95F4\u9694\\s+(\\d+)$/.exec(rest);\n if (interval) {\n const seconds = Number(interval[1]);\n if (!Number.isInteger(seconds) || seconds < 5 || seconds > 600) return { text: \"\u805A\u5408\u95F4\u9694\u9700\u4E3A 5\u2013600 \u79D2\u7684\u6574\u6570\u3002\" };\n const data = await postQqEventSettings(ep, {\n openid: ctx.inbound.userId,\n as_group_admin: asGroupAdminField(ctx),\n field: \"window_sec\",\n value: seconds,\n });\n return data.success && data.settings ? eventSettingsPanel(data.settings, \"\u5DF2\u4FDD\u5B58\") : failure(data.error);\n }\n const match = /^(\u603B\u5F00\u5173|\u542F\u52A8|\u505C\u670D|\u5F02\u5E38\u9000\u51FA|\u4E0A\u7EBF|\u4E0B\u7EBF|\u6B7B\u4EA1)\\s+(\u5F00|\u5173)$/.exec(rest);\n if (!match) return { text: \"\u53D1\u9001\u300C\u4E8B\u4EF6\u63A8\u9001\u300D\u6253\u5F00\u5F00\u5173\u9762\u677F\uFF0C\u6216\u9009\u62E9\u9762\u677F\u4E2D\u7684\u64CD\u4F5C\u3002\" };\n const item = EVENT_SWITCHES.find(([, label]) => label === match[1]);\n if (!item) return { text: \"\u6CA1\u6709\u8FD9\u4E2A\u4E8B\u4EF6\u5F00\u5173\u3002\" };\n const [field] = item;\n const value = match[2] === \"\u5F00\";\n const execute: CommandHandler = async (confirmed) => {\n try {\n const data = await postQqEventSettings(ep, {\n openid: confirmed.inbound.userId,\n as_group_admin: asGroupAdminField(confirmed),\n field,\n value,\n });\n return data.success && data.settings ? eventSettingsPanel(data.settings, \"\u5DF2\u4FDD\u5B58\") : failure(data.error);\n } catch (error) {\n return failure(error);\n }\n };\n if (field === \"enabled\" && !value) {\n return {\n text: \"\u786E\u8BA4\u5173\u95ED\u4E8B\u4EF6\u63A8\u9001\",\n confirmation: { summary: \"\u5373\u5C06\u5173\u95ED\u5168\u90E8\u670D\u52A1\u5668\u4E8B\u4EF6\u7FA4\u63A8\u9001\u3002\", execute },\n };\n }\n return execute(ctx);\n } catch (error) {\n return failure(error);\n }\n};\n\n/** \u9891\u9053 + \u8F7B\u91CF\u81EA\u68C0\uFF08\u4EBA\u4EBA\u53EF\u7528\uFF09 */\nexport const channelHandler: CommandHandler = () => ({\n text: \"QQ\u7FA4\u6D88\u606F\u8FDB\u5165\u6E38\u620F\u5185\u53EA\u8BFB\u7684 QQ \u9891\u9053\u3002\u6E38\u620F\u5185\u5404\u9891\u9053\u53EF\u5206\u522B\u8BBE\u7F6E\u662F\u5426\u8F6C\u53D1\u5230 QQ\u3002\",\n});\n\nexport const doctorHandler: CommandHandler = async (ctx) => {\n if (!isAdmin(ctx)) return { text: \"\u5F53\u524D\u6CA1\u6709\u7BA1\u7406\u6743\u9650\u3002\" };\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n const st = await fetchSfmcStatus(ep);\n const qq = await fetchQqGroupLines(ctx);\n return {\n text: [\n \"\u7BA1\u7406\u81EA\u68C0\",\n `\u540E\u7AEF\uFF1A${ctx.inbound.backend}`,\n `QQ \u5165\u7AD9\u9891\u9053\uFF1A${ctx.runtimeInfo.bridgeChannelId || \"qq\"}`,\n `\u4E3B\u673A\uFF1A${st.host?.hostname || \"\u672A\u77E5\"} \u00B7 ${st.host?.platform || \"\u672A\u77E5\"}`,\n `CPU\uFF1A${st.host?.cpu?.model || \"\u672A\u77E5\"} \u00B7 ${st.host?.cpu?.cores ?? \"\u672A\u77E5\"} \u6838`,\n `\u5185\u5B58\uFF1A${st.host?.memory?.usedMb ?? \"\u672A\u77E5\"}/${st.host?.memory?.totalMb ?? \"\u672A\u77E5\"} MB`,\n `\u4E3B\u673A\u8FD0\u884C\uFF1A${st.host?.uptimeText || \"\u672A\u77E5\"}`,\n `BDS\uFF1A${st.processes?.bds?.state || \"\u672A\u77E5\"} \u00B7 PID ${st.processes?.bds?.pid ?? \"\u672A\u77E5\"} \u00B7 ${st.processes?.bds?.uptimeText || \"\u672A\u77E5\"}`,\n `\u6570\u636E\u5E93\uFF1APID ${st.processes?.db?.pid ?? \"\u672A\u77E5\"} \u00B7 ${st.processes?.db?.uptimeText || \"\u672A\u77E5\"}`,\n ...qq,\n ].join(\"\\n\"),\n };\n};\n\n/** \u67E5\u8BE2\u5DF2\u5B89\u88C5\u6A21\u5757\u3002\u53EF\u52A0\u5173\u952E\u5B57\uFF0C\u4F8B\u5982\u300C\u6A21\u5757 \u804A\u5929\u300D\u3002 */\nexport const modulesHandler: CommandHandler = async (ctx) => {\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n const keyword = ctx.inbound.text.replace(/^\\/?(\u6A21\u5757|modules)\\s*/i, \"\").trim();\n try {\n const data = await fetchContent(ep);\n if (data.success === false) return failure(data.error);\n return formatCard(\"\u6A21\u5757\", formatModuleLines(data.modules ?? [], keyword));\n } catch (error) {\n return failure(error);\n }\n};\n\n/** \u67E5\u8BE2\u4E16\u754C\u5DF2\u5B89\u88C5\u7684\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\u3002\u65E7\u5FEB\u7167\u6CA1\u6709 packs \u65F6\uFF0C\u628A\u5DF2\u542F\u7528\u8D44\u6E90\u5305\u5F53\u4F5C\u8D44\u6E90\u5305\u6BB5\u3002 */\nexport const packsHandler: CommandHandler = async (ctx) => {\n const ep = dbEp(ctx);\n if (!ep) return failure(\"db \u672A\u914D\u7F6E\");\n try {\n const data = await fetchContent(ep);\n if (data.success === false) return failure(data.error);\n const packs =\n data.packs ??\n (data.resource_packs ?? []).map((pack) => ({\n kind: \"resource\" as const,\n enabled: true,\n ...(pack.name ? { name: pack.name } : {}),\n ...(pack.pack_id ? { pack_id: pack.pack_id } : {}),\n ...(pack.version ? { version: pack.version } : {}),\n }));\n return {\n text: [\"\u4E16\u754C\u5305\", \"\", ...formatPackLines(packs, data.note)].join(\"\\n\"),\n markdown: formatPackMarkdown(packs, data.note),\n };\n } catch (error) {\n return failure(error);\n }\n};\n\n/** \u6CE8\u518C\u8868\u540C\u65F6\u9A71\u52A8\u83DC\u5355\u3001\u5E2E\u52A9\u548C\u6743\u9650\u3002 */\nexport function registerBuiltinCommands(registry: CommandRegistry): void {\n const add = (\n name: string,\n aliases: string[],\n description: string,\n handler: CommandHandler,\n group: \"home\" | \"server\" | \"account\" | \"join\" | \"help\" | \"admin\",\n admin = false\n ) =>\n registry.register({\n name,\n aliases,\n description,\n handler,\n group,\n permission: admin ? \"admin\" : \"player\",\n adminMenu: group === \"admin\",\n });\n add(\"menu\", [\"\u83DC\u5355\"], \"\u8FD4\u56DE\u9996\u9875\", createMenuHandler(registry), \"home\");\n add(\n \"server\",\n [\"\u670D\u52A1\u5668\"],\n \"\u67E5\u770B\u8FD0\u884C\u72B6\u6001\u3001\u5728\u7EBF\u73A9\u5BB6\u548C\u8FDE\u63A5\u65B9\u5F0F\",\n sectionHandler(registry, \"server\", \"\u670D\u52A1\u5668\u4FE1\u606F\"),\n \"home\"\n );\n add(\"account\", [\"\u6211\u7684\u8D26\u53F7\"], \"\u67E5\u770B\u4E0E\u7BA1\u7406\u6E38\u620F\u89D2\u8272\u7ED1\u5B9A\", whoamiHandler, \"home\");\n add(\n \"entry\",\n [\"\u5165\u670D\"],\n \"\u76F4\u63A5\u8FDB\u670D\uFF0C\u6E38\u620F\u5185\u7ED1\u5B9A\u540E\u5373\u53EF\u6E38\u73A9\",\n entryGuideHandler,\n \"home\"\n );\n add(\"help\", [\"\u5E2E\u52A9\"], \"\u67E5\u770B\u4F7F\u7528\u8BF4\u660E\u548C\u5E38\u7528\u547D\u4EE4\", helpHandler(registry), \"home\");\n add(\"admin\", [\"\u7BA1\u7406\"], \"\u7BA1\u7406\u83DC\u5355\", createAdminMenuHandler(registry), \"home\", true);\n add(\"status\", [\"\u67E5\u670D\", \"\u72B6\u6001\"], \"\u670D\u52A1\u5668\u8FD0\u884C\u72B6\u6001\", statusHandler, \"server\");\n add(\"online\", [\"\u5728\u7EBF\"], \"\u5B8C\u6574\u5728\u7EBF\u540D\u5355\", onlineHandler, \"server\");\n add(\"version\", [\"\u7248\u672C\"], \"\u57FA\u5CA9\u7248\u5165\u670D\u7248\u672C\", serverVersionHandler, \"server\");\n add(\"ip\", [\"\u5730\u5740\"], \"\u516C\u5F00\u670D\u52A1\u5668\u5730\u5740\u4E0E\u7AEF\u53E3\", serverAddressHandler, \"server\");\n add(\"modules\", [\"\u6A21\u5757\"], \"\u67E5\u770B\u5DF2\u5B89\u88C5\u6A21\u5757\", modulesHandler, \"server\");\n add(\"packs\", [\"\u8D44\u6E90\u5305\", \"\u884C\u4E3A\u5305\", \"\u4E16\u754C\u5305\"], \"\u67E5\u770B\u4E16\u754C\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\", packsHandler, \"server\");\n add(\"channel\", [\"\u9891\u9053\"], \"\u804A\u5929\u4E92\u901A\u72B6\u6001\", channelHandler, \"server\");\n add(\"ping\", [], \"\u673A\u5668\u4EBA\u8FDE\u901A\u6027\", pingHandler, \"server\");\n add(\"whoami\", [\"\u6211\u7684\u7ED1\u5B9A\"], \"\u67E5\u770B\u7ED1\u5B9A\u89D2\u8272\", whoamiHandler, \"account\");\n add(\"bind\", [\"\u7ED1\u5B9A\"], \"\u7533\u8BF7\u7ED1\u5B9A\u9A8C\u8BC1\u7801\", bindHandler, \"account\");\n add(\"unbind\", [\"\u89E3\u7ED1\"], \"\u786E\u8BA4\u89E3\u9664\u7ED1\u5B9A\", unbindHandler, \"account\");\n add(\n \"join\",\n [\"\u7533\u8BF7\u5165\u670D\", \"\u901A\u8FC7\", \"\u62D2\u7EDD\", \"\u5F85\u5BA1\", \"approve\", \"reject\", \"pending\", \"\u914D\u7F6E\", \"\u5165\u670D\u914D\u7F6E\", \"config\"],\n \"\u5165\u670D\u7533\u8BF7\u5DF2\u5173\u95ED\uFF0C\u8BF7\u76F4\u63A5\u8FDB\u670D\u5E76\u7ED1\u5B9A\",\n retiredJoinFlowHandler,\n \"help\"\n );\n add(\"doctor\", [\"\u81EA\u68C0\"], \"\u8FDE\u901A\u4E0E\u8FD0\u884C\u8BCA\u65AD\", doctorHandler, \"admin\", true);\n add(\"group\", [\"\u7FA4\u4FE1\u606F\"], \"\u5B98\u65B9 QQ \u7FA4\u4FE1\u606F\", groupInfoHandler, \"admin\", true);\n add(\"events\", [\"\u4E8B\u4EF6\u63A8\u9001\", \"\u4E8B\u4EF6\u914D\u7F6E\"], \"\u670D\u52A1\u5668\u4E8B\u4EF6\u63A8\u9001\u5F00\u5173\", eventSettingsHandler, \"admin\", true);\n}\n"],
5
+ "mappings": "AAIA,SAAS,kBAAkB,oBAAoB;AAC/C,SAAS,WAAW;AACpB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,yBAAyB;AAClC,SAAS,mBAAmB,iBAAiB,0BAA0B;AACvE,SAAS,YAAY,yBAAyB;AAI9C,SAAS,aAAa,WAA2B;AAC/C,QAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS;AAC7C,QAAM,IAAI,KAAK,MAAM,KAAK,GAAI;AAC9B,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,QAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAC3B,MAAI,IAAI,EAAG,QAAO,GAAG,CAAC,KAAK,IAAI,EAAE;AACjC,MAAI,IAAI,EAAG,QAAO,GAAG,CAAC,KAAK,IAAI,EAAE;AACjC,SAAO,GAAG,CAAC;AACb;AAEA,SAAS,KAAK,KAAwC;AACpD,QAAM,OAAO,IAAI,YAAY;AAC7B,QAAM,OAAO,IAAI,YAAY;AAC7B,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,SAAO,EAAE,MAAM,KAAK;AACtB;AAEA,SAAS,QAAQ,KAA8B;AAC7C,SAAO,IAAI,oBAAoB;AACjC;AAEA,SAAS,QAAQ,OAA+B;AAC9C,MAAI,KAAK,gCAAY,OAAO,KAAK,CAAC,EAAE;AACpC,SAAO,EAAE,MAAM,yMAAoC;AACrD;AAEA,SAAS,kBAAkB,KAA8B;AACvD,SAAO,IAAI,QAAQ,iBAAiB;AACtC;AAGA,eAAe,kBAAkB,KAAwC;AACvE,QAAM,QAAQ,IAAI,YAAY;AAC9B,QAAM,MAAM,IAAI,YAAY,gBAAgB,IAAI,QAAQ,UAAU,QAAQ,IAAI,QAAQ,UAAU;AAChG,MAAI,CAAC,SAAS,CAAC,OAAO,IAAI,QAAQ,YAAY,WAAY,QAAO,CAAC;AAClE,QAAM,QAAkB,CAAC;AACzB,MAAI;AACF,UAAM,CAAC,SAAS,QAAQ,IAAI,MAAM,QAAQ,IAAI,CAAC,aAAa,OAAO,GAAG,GAAG,iBAAiB,OAAO,GAAG,CAAC,CAAC;AACtG,QAAI,QAAQ,MAAM,QAAQ,QAAQ,OAAO,QAAQ,SAAS,UAAU;AAClE,YAAM,IAAI,QAAQ;AAClB,YAAM,KAAK,iBAAO,EAAE,YAAY,KAAK,QAAG,sBAAS,EAAE,kBAAkB,KAAK,QAAG,EAAE;AAAA,IACjF,WAAW,CAAC,QAAQ,IAAI;AACtB,YAAM,OAAO,QAAQ,KAAK,QAAQ,SAAS,QAAQ,QAAQ,EAAE,IACzD,8EACA,wCAAU,QAAQ,SAAS,IAAI,MAAM,GAAG,EAAE,CAAC;AAC/C,YAAM,KAAK,IAAI;AAAA,IACjB;AACA,QAAI,SAAS,MAAM,SAAS,QAAQ,OAAO,SAAS,SAAS,UAAU;AACrE,YAAM,IAAI,SAAS;AACnB,YAAM;AAAA,QACJ,wCAAU,EAAE,aAAa,KAAK,QAAG,kCAAW,EAAE,qBAAqB,MAAM,OAAO,WAAM,QAAG,4BAAU,EAAE,kBAAkB,KAAK,QAAG;AAAA,MACjI;AAAA,IACF;AAAA,EACF,SAAS,GAAG;AACV,UAAM,KAAK,uCAAU,EAAY,OAAO,EAAE;AAAA,EAC5C;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,UAA2C;AAC3E,SAAO,CAAC,QACN,kBAAkB;AAAA,IAChB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAM,SACH,IAAI,EACJ,OAAO,CAAC,MAAM,EAAE,UAAU,UAAU,EAAE,SAAS,WAAW,EAAE,eAAe,WAAW,QAAQ,GAAG,EAAE;AAAA,IACtG,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,EACd,CAAC;AACL;AAEO,SAAS,uBAAuB,UAA2C;AAChF,SAAO,CAAC,QAAQ;AACd,QAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,mGAAmB;AACrD,WAAO,kBAAkB;AAAA,MACvB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,MAAM,SAAS,UAAU;AAAA,MACzB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AACF;AAEA,SAAS,eAAe,UAA2B,OAAiB,OAA+B;AACjG,SAAO,MACL,kBAAkB;AAAA,IAChB;AAAA,IACA,UAAU;AAAA,IACV,MAAM,SAAS,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK;AAAA,IACpD,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,EACd,CAAC;AACL;AAEA,SAAS,YAAY,UAA2C;AAC9D,SAAO,CAAC,QAAQ;AACd,UAAM,UACJ,IAAI,QAAQ,YAAY,aACpB,yNACA;AACN,UAAM,WAAW;AAAA,MACf,CAAC,UAAU,oBAAK;AAAA,MAChB,CAAC,WAAW,0BAAM;AAAA,MAClB,CAAC,SAAS,cAAI;AAAA,IAChB;AACA,UAAM,QAAQ,CAAC,OAAO;AACtB,eAAW,CAAC,OAAO,KAAK,KAAK,UAAU;AACrC,YAAM,WAAW,SAAS,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,UAAU,EAAE,eAAe,WAAW,QAAQ,GAAG,EAAE;AAC7G,UAAI,CAAC,SAAS,OAAQ;AACtB,YAAM;AAAA,QACJ;AAAA,QACA,SAAI,KAAK;AAAA,QACT,GAAG,SAAS,IAAI,CAAC,MAAM,GAAG,EAAE,SAAS,OAAO,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,SAAI,EAAE,WAAW,EAAE;AAAA,MAC9F;AAAA,IACF;AACA,UAAM,KAAK,IAAI,sIAA6B,qGAAqB;AACjE,WAAO,WAAW,4BAAQ,KAAK;AAAA,EACjC;AACF;AAEO,MAAM,uBAAuC,OAAO,QAAQ;AACjE,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,IAAI;AACN,QAAI;AACF,YAAM,SAAS,MAAM,gBAAgB,EAAE;AACvC,YAAM,MAAM,OAAO,WAAW;AAC9B,UAAI,KAAK,UAAU,aAAa,IAAI;AAClC,eAAO,WAAW,gBAAM,CAAC,oDAAY,sCAAa,IAAI,OAAO,EAAE,CAAC;AAAA,IACpE,SAAS,OAAO;AACd,UAAI,KAAK,6CAAe,OAAO,KAAK,CAAC,EAAE;AAAA,IACzC;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,IAAI,YAAY,cAAc,UAChC;AAAA,oEAAgC,IAAI,YAAY,aAAa,OAAO,KACpE;AAAA,EACN;AACF;AACO,MAAM,uBAAuC,CAAC,QAAQ;AAC3D,QAAM,OAAO,IAAI,YAAY;AAC7B,SAAO;AAAA,IACL;AAAA,IACA,MAAM,UACF;AAAA,MACE;AAAA,MACA,uCAAS,KAAK,OAAO;AAAA,MACrB,qBAAM,KAAK,QAAQ,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,IACF,IACA,CAAC,oHAAqB;AAAA,EAC5B;AACF;AAEO,MAAM,cAA8B,CAAC,SAAS;AAAA,EACnD,MAAM,sEAAe,aAAa,IAAI,SAAS,CAAC;AAClD;AAEO,MAAM,gBAAgC,OAAO,QAAQ;AAC1D,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,QAAM,KAAK,MAAM,YAAY,IAAI,IAAI,QAAQ,MAAM;AACnD,MAAI,GAAG,YAAY,MAAO,QAAO,QAAQ,sCAAQ;AACjD,SAAO;AAAA,IACL,GAAG,kBAAkB;AAAA,MACnB,OAAO,CAAC,CAAC,GAAG;AAAA,MACZ,GAAI,GAAG,SAAS,cAAc,EAAE,YAAY,GAAG,QAAQ,YAAY,IAAI,CAAC;AAAA,MACxE,GAAI,GAAG,UAAU,EAAE,SAAS,GAAG,QAAQ,IAAI,CAAC;AAAA,IAC9C,CAAC;AAAA,IACD,SAAS,GAAG,QACR,CAAC,EAAE,IAAI,UAAU,OAAO,gBAAM,SAAS,UAAU,CAAC,IAClD,CAAC,EAAE,IAAI,QAAQ,OAAO,gBAAM,SAAS,QAAQ,CAAC;AAAA,EACpD;AACF;AAEO,MAAM,gBAAgC,OAAO,QAAQ;AAC1D,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,MAAI;AACJ,MAAI;AACF,SAAK,MAAM,gBAAgB,EAAE;AAAA,EAC/B,SAAS,OAAO;AACd,QAAI,KAAK,2DAAc,OAAO,KAAK,CAAC,EAAE;AACtC,WAAO,WAAW,kCAAS,CAAC,0JAA6B,0EAAc,CAAC;AAAA,EAC1E;AACA,QAAM,QAAQ,GAAG,WAAW;AAC5B,QAAM,UAAU,OAAO,UAAU,aAAa,OAAO,YAAY;AACjE,QAAM,UAAU,OAAO,UAAU,aAAa,OAAO,YAAY;AACjE,QAAM,aAAa,UACf,aACA,GAAG,QAAQ,CAAC,MAAM,QAAQ,GAAG,MAAM,IACjC,+CACA,GAAG,GAAG,OAAO,MAAM;AACzB,QAAM,MACJ,OAAO,GAAG,cAAc,WAAW,GAAG,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,IAAI,IAAI,GAAG,aAAa,GAAI,CAAC,CAAC,kBAAQ;AAC3G,SAAO;AAAA,IACL,GAAG,WAAW,kCAAS;AAAA,MACrB,iCAAQ,UAAU,uBAAQ,UAAU,uBAAQ,sCAAQ;AAAA,MACpD,iCAAQ,UAAU;AAAA,MAClB,2BAAO,GAAG,OAAO,OAAO,cAAI;AAAA,MAC5B,qBAAM,GAAG,OAAO,cAAc,cAAI;AAAA,MAClC,iCAAQ,GAAG;AAAA,MACX,GAAI,GAAG,QAAQ,UAAU,CAAC,kGAAkB,IAAI,CAAC;AAAA,IACnD,CAAC;AAAA,IACD,SAAS;AAAA,MACP,EAAE,IAAI,UAAU,OAAO,4BAAQ,SAAS,UAAU;AAAA,MAClD,EAAE,IAAI,WAAW,OAAO,gBAAM,SAAS,WAAW;AAAA,MAClD,EAAE,IAAI,MAAM,OAAO,4BAAQ,SAAS,MAAM;AAAA,MAC1C,EAAE,IAAI,kBAAkB,OAAO,4BAAQ,SAAS,UAAU;AAAA,IAC5D;AAAA,EACF;AACF;AAEO,MAAM,gBAAgC,OAAO,QAAQ;AAC1D,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,QAAM,KAAK,MAAM,gBAAgB,EAAE;AACnC,MAAI,GAAG,WAAW,KAAK,UAAU,UAAW,QAAO,WAAW,4BAAQ,CAAC,kGAAkB,CAAC;AAC1F,MAAI,CAAC,MAAM,QAAQ,GAAG,MAAM,KAAK,GAAG,KAAM,QAAO,EAAE,MAAM,mGAAmB;AAC5E,MAAI,CAAC,GAAG,OAAO,OAAQ,QAAO,WAAW,4BAAQ,CAAC,wDAAW,CAAC;AAC9D,SAAO;AAAA,IACL,GAAG,WAAW,4BAAQ;AAAA,MACpB,4BAAQ,GAAG,OAAO,MAAM;AAAA,MACxB;AAAA,MACA,GAAG,GAAG,OAAO,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,QAAQ,gCAAO,EAAE;AAAA,IAC7D,CAAC;AAAA,EACH;AACF;AAEO,MAAM,cAA8B,OAAO,QAAgD;AAChG,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,MAAI;AACF,UAAM,EAAE,QAAQ,KAAK,IAAI,MAAM,gBAAgB,IAAI;AAAA,MACjD,QAAQ,IAAI,QAAQ;AAAA,MACpB,YAAY,IAAI,QAAQ;AAAA,IAC1B,CAAC;AACD,QAAI,WAAW,OAAO,KAAK,UAAU,iBAAiB;AACpD,aAAO;AAAA,QACL,MAAM,iDAAc,KAAK,eAAe,GAAG;AAAA,MAC7C;AAAA,IACF;AACA,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,MAAM;AAC/B,aAAO,QAAQ,KAAK,KAAK;AAAA,IAC3B;AAEA,WAAO,WAAW,4BAAQ;AAAA,MACxB,2BAAO,KAAK,IAAI;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,SAAS,GAAG;AACV,WAAO,QAAQ,CAAC;AAAA,EAClB;AACF;AAEO,MAAM,gBAAgC,OAAO,QAAQ;AAC1D,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,QAAM,KAAK,MAAM,YAAY,IAAI,IAAI,QAAQ,MAAM;AACnD,MAAI,GAAG,YAAY,MAAO,QAAO,QAAQ,sCAAQ;AACjD,MAAI,CAAC,GAAG,SAAS,CAAC,GAAG,QAAS,QAAO,EAAE,MAAM,yDAAY;AACzD,QAAM,WAAW,GAAG;AACpB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,cAAc;AAAA,MACZ,SAAS,6CAAU,SAAS,eAAe,gCAAO;AAAA,MAClD,SAAS,OAAO,cAAc;AAC5B,cAAM,UAAU,MAAM,YAAY,IAAI,UAAU,QAAQ,MAAM;AAC9D,YAAI,QAAQ,YAAY,MAAO,QAAO,QAAQ,sCAAQ;AACtD,YACE,CAAC,QAAQ,SACT,QAAQ,SAAS,gBAAgB,SAAS,eAC1C,QAAQ,SAAS,aAAa,SAAS,UACvC;AACA,iBAAO,EAAE,MAAM,mJAA2B;AAAA,QAC5C;AACA,cAAM,EAAE,KAAK,IAAI,MAAM,eAAe,IAAI,EAAE,QAAQ,UAAU,QAAQ,OAAO,CAAC;AAC9E,YAAI,KAAK,YAAY,MAAO,QAAO,QAAQ,KAAK,KAAK;AACrD,eAAO,EAAE,MAAM,KAAK,UAAU,iFAAqB,yDAAY;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,mBAAmC,OAAO,QAAgD;AACrG,QAAM,QAAQ,MAAM,kBAAkB,GAAG;AACzC,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,MAAM,wIAA8C;AAAA,EAC/D;AACA,SAAO,EAAE,MAAM,CAAC,yBAAU,GAAG,KAAK,EAAE,KAAK,IAAI,EAAE;AACjD;AAMO,MAAM,oBAAoC,MAC/C,WAAW,4BAAQ;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAMI,MAAM,yBAAyC,OAAsB;AAAA,EAC1E,MAAM;AACR;AAEA,MAAM,iBAAiB;AAAA,EACrB,CAAC,WAAW,oBAAK;AAAA,EACjB,CAAC,SAAS,cAAI;AAAA,EACd,CAAC,QAAQ,cAAI;AAAA,EACb,CAAC,SAAS,0BAAM;AAAA,EAChB,CAAC,QAAQ,cAAI;AAAA,EACb,CAAC,SAAS,cAAI;AAAA,EACd,CAAC,SAAS,cAAI;AAChB;AAEA,SAAS,mBAAmB,UAA2B,SAAS,IAAmB;AACjF,QAAM,OAAgC;AAAA,IACpC,GAAG,eAAe,IAAI,CAAC,CAAC,OAAO,KAAK,MAAwB,CAAC,OAAO,SAAS,KAAK,IAAI,WAAM,QAAG,CAAC;AAAA,IAChG,CAAC,4BAAQ,GAAG,SAAS,UAAU,SAAI;AAAA,EACrC;AACA,QAAM,WAAW,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,MAAM,UAAK,KAAK,GAAG,SAAI,OAAO,IAAI,MAAM,MAAM,CAAC,WAAM,KAAK,SAAI;AACtG,QAAM,UAAU,eAAe,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO;AAAA,IACtD,IAAI,UAAU,KAAK;AAAA,IACnB,OAAO,GAAG,KAAK,IAAI,SAAS,KAAK,IAAI,WAAM,QAAG;AAAA,IAC9C,SAAS,WAAW,KAAK,IAAI,SAAS,KAAK,IAAI,WAAM,QAAG;AAAA,EAC1D,EAAE;AACF,UAAQ,KAAK,EAAE,IAAI,iBAAiB,OAAO,4BAAQ,SAAS,uBAAa,CAAC;AAC1E,SAAO;AAAA,IACL,MAAM;AAAA,MACJ;AAAA,MACA,GAAI,SAAS,CAAC,MAAM,IAAI,CAAC;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA,kCAAS,SAAS,UAAU;AAAA,IAC9B,EAAE,KAAK,IAAI;AAAA,IACX,UAAU;AAAA,MACR;AAAA,MACA,GAAI,SAAS,CAAC,IAAI,MAAM,IAAI,CAAC;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,MAAM,KAAK,KAAK,QAAQ,KAAK,MAAM;AAAA,MAC7D;AAAA,MACA,mCAAU,SAAS,UAAU;AAAA,IAC/B,EAAE,KAAK,IAAI;AAAA,IACX;AAAA,EACF;AACF;AAEO,MAAM,uBAAuC,OAAO,QAAgC;AACzF,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,mGAAmB;AACrD,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,QAAM,OAAO,IAAI,QAAQ,KAAK,QAAQ,gCAAgC,EAAE,EAAE,KAAK;AAC/E,MAAI;AACF,QAAI,CAAC,MAAM;AACT,YAAM,OAAO,MAAM,qBAAqB,EAAE;AAC1C,aAAO,KAAK,WAAW,KAAK,WAAW,mBAAmB,KAAK,QAAQ,IAAI,QAAQ,KAAK,KAAK;AAAA,IAC/F;AACA,QAAI,SAAS,gBAAM;AACjB,YAAM,OAAO,MAAM,qBAAqB,EAAE;AAC1C,UAAI,CAAC,KAAK,WAAW,CAAC,KAAK,SAAU,QAAO,QAAQ,KAAK,KAAK;AAC9D,aAAO;AAAA,QACL,GAAG,WAAW,4BAAQ;AAAA,UACpB,qBAAM,KAAK,SAAS,UAAU;AAAA,UAC9B;AAAA,UACA;AAAA,QACF,CAAC;AAAA,QACD,SAAS,CAAC,IAAI,IAAI,GAAG,EAAE,IAAI,CAAC,aAAa;AAAA,UACvC,IAAI,iBAAiB,OAAO;AAAA,UAC5B,OAAO,GAAG,OAAO;AAAA,UACjB,SAAS,wBAAc,OAAO;AAAA,QAChC,EAAE;AAAA,MACJ;AAAA,IACF;AACA,UAAM,WAAW,eAAe,KAAK,IAAI;AACzC,QAAI,UAAU;AACZ,YAAM,UAAU,OAAO,SAAS,CAAC,CAAC;AAClC,UAAI,CAAC,OAAO,UAAU,OAAO,KAAK,UAAU,KAAK,UAAU,IAAK,QAAO,EAAE,MAAM,iFAAqB;AACpG,YAAM,OAAO,MAAM,oBAAoB,IAAI;AAAA,QACzC,QAAQ,IAAI,QAAQ;AAAA,QACpB,gBAAgB,kBAAkB,GAAG;AAAA,QACrC,OAAO;AAAA,QACP,OAAO;AAAA,MACT,CAAC;AACD,aAAO,KAAK,WAAW,KAAK,WAAW,mBAAmB,KAAK,UAAU,oBAAK,IAAI,QAAQ,KAAK,KAAK;AAAA,IACtG;AACA,UAAM,QAAQ,sCAAsC,KAAK,IAAI;AAC7D,QAAI,CAAC,MAAO,QAAO,EAAE,MAAM,yJAA4B;AACvD,UAAM,OAAO,eAAe,KAAK,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAM,CAAC,CAAC;AAClE,QAAI,CAAC,KAAM,QAAO,EAAE,MAAM,yDAAY;AACtC,UAAM,CAAC,KAAK,IAAI;AAChB,UAAM,QAAQ,MAAM,CAAC,MAAM;AAC3B,UAAM,UAA0B,OAAO,cAAc;AACnD,UAAI;AACF,cAAM,OAAO,MAAM,oBAAoB,IAAI;AAAA,UACzC,QAAQ,UAAU,QAAQ;AAAA,UAC1B,gBAAgB,kBAAkB,SAAS;AAAA,UAC3C;AAAA,UACA;AAAA,QACF,CAAC;AACD,eAAO,KAAK,WAAW,KAAK,WAAW,mBAAmB,KAAK,UAAU,oBAAK,IAAI,QAAQ,KAAK,KAAK;AAAA,MACtG,SAAS,OAAO;AACd,eAAO,QAAQ,KAAK;AAAA,MACtB;AAAA,IACF;AACA,QAAI,UAAU,aAAa,CAAC,OAAO;AACjC,aAAO;AAAA,QACL,MAAM;AAAA,QACN,cAAc,EAAE,SAAS,8FAAmB,QAAQ;AAAA,MACtD;AAAA,IACF;AACA,WAAO,QAAQ,GAAG;AAAA,EACpB,SAAS,OAAO;AACd,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;AAGO,MAAM,iBAAiC,OAAO;AAAA,EACnD,MAAM;AACR;AAEO,MAAM,gBAAgC,OAAO,QAAQ;AAC1D,MAAI,CAAC,QAAQ,GAAG,EAAG,QAAO,EAAE,MAAM,yDAAY;AAC9C,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,QAAM,KAAK,MAAM,gBAAgB,EAAE;AACnC,QAAM,KAAK,MAAM,kBAAkB,GAAG;AACtC,SAAO;AAAA,IACL,MAAM;AAAA,MACJ;AAAA,MACA,qBAAM,IAAI,QAAQ,OAAO;AAAA,MACzB,oCAAW,IAAI,YAAY,mBAAmB,IAAI;AAAA,MAClD,qBAAM,GAAG,MAAM,YAAY,cAAI,SAAM,GAAG,MAAM,YAAY,cAAI;AAAA,MAC9D,YAAO,GAAG,MAAM,KAAK,SAAS,cAAI,SAAM,GAAG,MAAM,KAAK,SAAS,cAAI;AAAA,MACnE,qBAAM,GAAG,MAAM,QAAQ,UAAU,cAAI,IAAI,GAAG,MAAM,QAAQ,WAAW,cAAI;AAAA,MACzE,iCAAQ,GAAG,MAAM,cAAc,cAAI;AAAA,MACnC,YAAO,GAAG,WAAW,KAAK,SAAS,cAAI,aAAU,GAAG,WAAW,KAAK,OAAO,cAAI,SAAM,GAAG,WAAW,KAAK,cAAc,cAAI;AAAA,MAC1H,+BAAW,GAAG,WAAW,IAAI,OAAO,cAAI,SAAM,GAAG,WAAW,IAAI,cAAc,cAAI;AAAA,MAClF,GAAG;AAAA,IACL,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAGO,MAAM,iBAAiC,OAAO,QAAQ;AAC3D,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,QAAM,UAAU,IAAI,QAAQ,KAAK,QAAQ,wBAAwB,EAAE,EAAE,KAAK;AAC1E,MAAI;AACF,UAAM,OAAO,MAAM,aAAa,EAAE;AAClC,QAAI,KAAK,YAAY,MAAO,QAAO,QAAQ,KAAK,KAAK;AACrD,WAAO,WAAW,gBAAM,kBAAkB,KAAK,WAAW,CAAC,GAAG,OAAO,CAAC;AAAA,EACxE,SAAS,OAAO;AACd,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;AAGO,MAAM,eAA+B,OAAO,QAAQ;AACzD,QAAM,KAAK,KAAK,GAAG;AACnB,MAAI,CAAC,GAAI,QAAO,QAAQ,uBAAQ;AAChC,MAAI;AACF,UAAM,OAAO,MAAM,aAAa,EAAE;AAClC,QAAI,KAAK,YAAY,MAAO,QAAO,QAAQ,KAAK,KAAK;AACrD,UAAM,QACJ,KAAK,UACJ,KAAK,kBAAkB,CAAC,GAAG,IAAI,CAAC,UAAU;AAAA,MACzC,MAAM;AAAA,MACN,SAAS;AAAA,MACT,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,MACvC,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,MAChD,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IAClD,EAAE;AACJ,WAAO;AAAA,MACL,MAAM,CAAC,sBAAO,IAAI,GAAG,gBAAgB,OAAO,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI;AAAA,MACjE,UAAU,mBAAmB,OAAO,KAAK,IAAI;AAAA,IAC/C;AAAA,EACF,SAAS,OAAO;AACd,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;AAGO,SAAS,wBAAwB,UAAiC;AACvE,QAAM,MAAM,CACV,MACA,SACA,aACA,SACA,OACA,QAAQ,UAER,SAAS,SAAS;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,QAAQ,UAAU;AAAA,IAC9B,WAAW,UAAU;AAAA,EACvB,CAAC;AACH,MAAI,QAAQ,CAAC,cAAI,GAAG,4BAAQ,kBAAkB,QAAQ,GAAG,MAAM;AAC/D;AAAA,IACE;AAAA,IACA,CAAC,oBAAK;AAAA,IACN;AAAA,IACA,eAAe,UAAU,UAAU,gCAAO;AAAA,IAC1C;AAAA,EACF;AACA,MAAI,WAAW,CAAC,0BAAM,GAAG,sEAAe,eAAe,MAAM;AAC7D;AAAA,IACE;AAAA,IACA,CAAC,cAAI;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,QAAQ,CAAC,cAAI,GAAG,sEAAe,YAAY,QAAQ,GAAG,MAAM;AAChE,MAAI,SAAS,CAAC,cAAI,GAAG,4BAAQ,uBAAuB,QAAQ,GAAG,QAAQ,IAAI;AAC3E,MAAI,UAAU,CAAC,gBAAM,cAAI,GAAG,8CAAW,eAAe,QAAQ;AAC9D,MAAI,UAAU,CAAC,cAAI,GAAG,wCAAU,eAAe,QAAQ;AACvD,MAAI,WAAW,CAAC,cAAI,GAAG,8CAAW,sBAAsB,QAAQ;AAChE,MAAI,MAAM,CAAC,cAAI,GAAG,gEAAc,sBAAsB,QAAQ;AAC9D,MAAI,WAAW,CAAC,cAAI,GAAG,8CAAW,gBAAgB,QAAQ;AAC1D,MAAI,SAAS,CAAC,sBAAO,sBAAO,oBAAK,GAAG,sEAAe,cAAc,QAAQ;AACzE,MAAI,WAAW,CAAC,cAAI,GAAG,wCAAU,gBAAgB,QAAQ;AACzD,MAAI,QAAQ,CAAC,GAAG,wCAAU,aAAa,QAAQ;AAC/C,MAAI,UAAU,CAAC,0BAAM,GAAG,wCAAU,eAAe,SAAS;AAC1D,MAAI,QAAQ,CAAC,cAAI,GAAG,8CAAW,aAAa,SAAS;AACrD,MAAI,UAAU,CAAC,cAAI,GAAG,wCAAU,eAAe,SAAS;AACxD;AAAA,IACE;AAAA,IACA,CAAC,4BAAQ,gBAAM,gBAAM,gBAAM,WAAW,UAAU,WAAW,gBAAM,4BAAQ,QAAQ;AAAA,IACjF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,UAAU,CAAC,cAAI,GAAG,8CAAW,eAAe,SAAS,IAAI;AAC7D,MAAI,SAAS,CAAC,oBAAK,GAAG,sCAAa,kBAAkB,SAAS,IAAI;AAClE,MAAI,UAAU,CAAC,4BAAQ,0BAAM,GAAG,0DAAa,sBAAsB,SAAS,IAAI;AAClF;",
6
6
  "names": []
7
7
  }
@@ -4,12 +4,12 @@ import { CommandRegistry } from "./registry.js";
4
4
  import { createLlbotReplyPort } from "./reply-llbot.js";
5
5
  import { createOfficialReplyPort } from "./reply-official.js";
6
6
  import { CommandRouter } from "./router.js";
7
- import { CommandRouter as CommandRouter2 } from "./router.js";
8
- import { renderOfficial, renderLlbot } from "./render.js";
9
- import { normalizeTrigger, CommandRegistry as CommandRegistry2 } from "./registry.js";
10
- import { PendingChoiceStore as PendingChoiceStore2 } from "./pending.js";
11
7
  import { registerBuiltinCommands as registerBuiltinCommands2 } from "./handlers.js";
12
- import { syncMenuAndPanel, buildMenuItems, buildPanelItems } from "./menu-panel-sync.js";
8
+ import { buildMenuItems, buildPanelItems, syncMenuAndPanel } from "./menu-panel-sync.js";
9
+ import { PendingChoiceStore as PendingChoiceStore2 } from "./pending.js";
10
+ import { CommandRegistry as CommandRegistry2, normalizeTrigger } from "./registry.js";
11
+ import { renderLlbot, renderOfficial } from "./render.js";
12
+ import { CommandRouter as CommandRouter2 } from "./router.js";
13
13
  function createCommandRouter(opts) {
14
14
  const registry = new CommandRegistry();
15
15
  registerBuiltinCommands(registry);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/commands/index.ts"],
4
- "sourcesContent": ["/**\n * commands/index.ts \u2014 \u7EC4\u88C5\u9ED8\u8BA4 Router\n */\n\nimport { registerBuiltinCommands } from \"./handlers.js\";\nimport { PendingChoiceStore } from \"./pending.js\";\nimport { CommandRegistry } from \"./registry.js\";\nimport { createLlbotReplyPort, type LlbotReplyConfig } from \"./reply-llbot.js\";\nimport { createOfficialReplyPort } from \"./reply-official.js\";\nimport { CommandRouter } from \"./router.js\";\nimport type { CommandContext, ReplyPort } from \"./types.js\";\nimport type { QqOfficialCredentials } from \"@sfmc-bds/sdk/node/qq-official\";\n\nexport type { CommandResult, InboundMessage, ReplyPort } from \"./types.js\";\nexport { CommandRouter } from \"./router.js\";\nexport { renderOfficial, renderLlbot } from \"./render.js\";\nexport { normalizeTrigger, CommandRegistry } from \"./registry.js\";\nexport { PendingChoiceStore } from \"./pending.js\";\nexport { registerBuiltinCommands } from \"./handlers.js\";\nexport { syncMenuAndPanel, buildMenuItems, buildPanelItems } from \"./menu-panel-sync.js\";\n\nexport function createCommandRouter(opts: {\n reply: ReplyPort;\n runtimeInfo: CommandContext[\"runtimeInfo\"];\n startedAt?: number;\n}): CommandRouter {\n const registry = new CommandRegistry();\n registerBuiltinCommands(registry);\n return new CommandRouter({\n registry,\n pending: new PendingChoiceStore(),\n reply: opts.reply,\n startedAt: opts.startedAt ?? Date.now(),\n runtimeInfo: opts.runtimeInfo,\n });\n}\n\nexport function createOfficialCommandRouter(\n creds: QqOfficialCredentials,\n runtimeInfo: CommandContext[\"runtimeInfo\"],\n startedAt?: number\n): CommandRouter {\n const opts: Parameters<typeof createCommandRouter>[0] = {\n reply: createOfficialReplyPort(creds),\n runtimeInfo,\n };\n if (startedAt !== undefined) opts.startedAt = startedAt;\n return createCommandRouter(opts);\n}\n\nexport function createLlbotCommandRouter(\n cfg: LlbotReplyConfig,\n runtimeInfo: CommandContext[\"runtimeInfo\"] = {},\n startedAt?: number\n): CommandRouter {\n const opts: Parameters<typeof createCommandRouter>[0] = {\n reply: createLlbotReplyPort(cfg),\n runtimeInfo,\n };\n if (startedAt !== undefined) opts.startedAt = startedAt;\n return createCommandRouter(opts);\n}\n"],
5
- "mappings": "AAIA,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,4BAAmD;AAC5D,SAAS,+BAA+B;AACxC,SAAS,qBAAqB;AAK9B,SAAS,iBAAAA,sBAAqB;AAC9B,SAAS,gBAAgB,mBAAmB;AAC5C,SAAS,kBAAkB,mBAAAC,wBAAuB;AAClD,SAAS,sBAAAC,2BAA0B;AACnC,SAAS,2BAAAC,gCAA+B;AACxC,SAAS,kBAAkB,gBAAgB,uBAAuB;AAE3D,SAAS,oBAAoB,MAIlB;AAChB,QAAM,WAAW,IAAI,gBAAgB;AACrC,0BAAwB,QAAQ;AAChC,SAAO,IAAI,cAAc;AAAA,IACvB;AAAA,IACA,SAAS,IAAI,mBAAmB;AAAA,IAChC,OAAO,KAAK;AAAA,IACZ,WAAW,KAAK,aAAa,KAAK,IAAI;AAAA,IACtC,aAAa,KAAK;AAAA,EACpB,CAAC;AACH;AAEO,SAAS,4BACd,OACA,aACA,WACe;AACf,QAAM,OAAkD;AAAA,IACtD,OAAO,wBAAwB,KAAK;AAAA,IACpC;AAAA,EACF;AACA,MAAI,cAAc,OAAW,MAAK,YAAY;AAC9C,SAAO,oBAAoB,IAAI;AACjC;AAEO,SAAS,yBACd,KACA,cAA6C,CAAC,GAC9C,WACe;AACf,QAAM,OAAkD;AAAA,IACtD,OAAO,qBAAqB,GAAG;AAAA,IAC/B;AAAA,EACF;AACA,MAAI,cAAc,OAAW,MAAK,YAAY;AAC9C,SAAO,oBAAoB,IAAI;AACjC;",
6
- "names": ["CommandRouter", "CommandRegistry", "PendingChoiceStore", "registerBuiltinCommands"]
4
+ "sourcesContent": ["/**\n * commands/index.ts \u2014 \u7EC4\u88C5\u9ED8\u8BA4 Router\n */\n\nimport type { QqOfficialCredentials } from \"@sfmc-bds/sdk/node/qq-official\";\nimport { registerBuiltinCommands } from \"./handlers.js\";\nimport { PendingChoiceStore } from \"./pending.js\";\nimport { CommandRegistry } from \"./registry.js\";\nimport { createLlbotReplyPort, type LlbotReplyConfig } from \"./reply-llbot.js\";\nimport { createOfficialReplyPort } from \"./reply-official.js\";\nimport { CommandRouter } from \"./router.js\";\nimport type { CommandContext, ReplyPort } from \"./types.js\";\n\nexport { registerBuiltinCommands } from \"./handlers.js\";\nexport { buildMenuItems, buildPanelItems, syncMenuAndPanel } from \"./menu-panel-sync.js\";\nexport { PendingChoiceStore } from \"./pending.js\";\nexport { CommandRegistry, normalizeTrigger } from \"./registry.js\";\nexport { renderLlbot, renderOfficial } from \"./render.js\";\nexport { CommandRouter } from \"./router.js\";\nexport type { CommandResult, InboundMessage, ReplyPort } from \"./types.js\";\n\nexport function createCommandRouter(opts: {\n reply: ReplyPort;\n runtimeInfo: CommandContext[\"runtimeInfo\"];\n startedAt?: number;\n}): CommandRouter {\n const registry = new CommandRegistry();\n registerBuiltinCommands(registry);\n return new CommandRouter({\n registry,\n pending: new PendingChoiceStore(),\n reply: opts.reply,\n startedAt: opts.startedAt ?? Date.now(),\n runtimeInfo: opts.runtimeInfo,\n });\n}\n\nexport function createOfficialCommandRouter(\n creds: QqOfficialCredentials,\n runtimeInfo: CommandContext[\"runtimeInfo\"],\n startedAt?: number\n): CommandRouter {\n const opts: Parameters<typeof createCommandRouter>[0] = {\n reply: createOfficialReplyPort(creds),\n runtimeInfo,\n };\n if (startedAt !== undefined) opts.startedAt = startedAt;\n return createCommandRouter(opts);\n}\n\nexport function createLlbotCommandRouter(\n cfg: LlbotReplyConfig,\n runtimeInfo: CommandContext[\"runtimeInfo\"] = {},\n startedAt?: number\n): CommandRouter {\n const opts: Parameters<typeof createCommandRouter>[0] = {\n reply: createLlbotReplyPort(cfg),\n runtimeInfo,\n };\n if (startedAt !== undefined) opts.startedAt = startedAt;\n return createCommandRouter(opts);\n}\n"],
5
+ "mappings": "AAKA,SAAS,+BAA+B;AACxC,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,4BAAmD;AAC5D,SAAS,+BAA+B;AACxC,SAAS,qBAAqB;AAG9B,SAAS,2BAAAA,gCAA+B;AACxC,SAAS,gBAAgB,iBAAiB,wBAAwB;AAClE,SAAS,sBAAAC,2BAA0B;AACnC,SAAS,mBAAAC,kBAAiB,wBAAwB;AAClD,SAAS,aAAa,sBAAsB;AAC5C,SAAS,iBAAAC,sBAAqB;AAGvB,SAAS,oBAAoB,MAIlB;AAChB,QAAM,WAAW,IAAI,gBAAgB;AACrC,0BAAwB,QAAQ;AAChC,SAAO,IAAI,cAAc;AAAA,IACvB;AAAA,IACA,SAAS,IAAI,mBAAmB;AAAA,IAChC,OAAO,KAAK;AAAA,IACZ,WAAW,KAAK,aAAa,KAAK,IAAI;AAAA,IACtC,aAAa,KAAK;AAAA,EACpB,CAAC;AACH;AAEO,SAAS,4BACd,OACA,aACA,WACe;AACf,QAAM,OAAkD;AAAA,IACtD,OAAO,wBAAwB,KAAK;AAAA,IACpC;AAAA,EACF;AACA,MAAI,cAAc,OAAW,MAAK,YAAY;AAC9C,SAAO,oBAAoB,IAAI;AACjC;AAEO,SAAS,yBACd,KACA,cAA6C,CAAC,GAC9C,WACe;AACf,QAAM,OAAkD;AAAA,IACtD,OAAO,qBAAqB,GAAG;AAAA,IAC/B;AAAA,EACF;AACA,MAAI,cAAc,OAAW,MAAK,YAAY;AAC9C,SAAO,oBAAoB,IAAI;AACjC;",
6
+ "names": ["registerBuiltinCommands", "PendingChoiceStore", "CommandRegistry", "CommandRouter"]
7
7
  }
@@ -1,145 +1,50 @@
1
- import {
2
- ackInteraction,
3
- sendC2cMessage,
4
- sendGroupMessage
5
- } from "@sfmc-bds/sdk/node/qq-official";
1
+ import { ackInteraction } from "@sfmc-bds/sdk/node/qq-official";
6
2
  import { log } from "../log.js";
7
- import { postJoinDecide, postJoinSettings } from "./db-api.js";
8
- import {
9
- buildJoinSettingsPanel,
10
- parseCfgInteractionData,
11
- settingsFromResponse
12
- } from "./join-settings-ui.js";
13
- import { renderOfficial } from "./render.js";
14
- const recentIds = /* @__PURE__ */ new Map();
15
- const DEDUP_MS = 6e4;
16
- function remember(id) {
17
- const now = Date.now();
18
- for (const [k, t] of recentIds) {
19
- if (now - t > DEDUP_MS) recentIds.delete(k);
20
- }
21
- if (recentIds.has(id)) return false;
22
- recentIds.set(id, now);
23
- return true;
24
- }
25
- function extractUserOpenid(d) {
26
- return String(
27
- d.user_openid || d.member_openid || d.author?.member_openid || d.author?.user_openid || d.author?.id || ""
28
- ).trim();
29
- }
30
- function extractData(d) {
31
- const raw = d.data;
32
- if (typeof raw === "string") return raw.trim();
33
- const nested = d;
34
- for (const key of ["button_data", "button", "event_data"]) {
35
- const v = nested[key];
36
- if (typeof v === "string") return v.trim();
37
- if (v && typeof v === "object" && "data" in v) {
38
- return String(v.data ?? "").trim();
39
- }
40
- }
41
- return "";
42
- }
43
- async function replyGroup(opts, groupOpenid, text, panel) {
44
- if (!groupOpenid) return;
45
- if (panel) {
46
- const rendered = renderOfficial(panel);
47
- const res = await sendGroupMessage(opts.creds, {
48
- groupOpenid,
49
- msgType: rendered.msgType,
50
- ...rendered.msgType === 2 ? { markdown: rendered.markdown ?? panel.text } : { content: rendered.content ?? panel.text },
51
- ...rendered.keyboardButtons ? { keyboardButtons: rendered.keyboardButtons } : {}
52
- });
53
- if (res.ok) return;
54
- log.warn(`\u914D\u7F6E\u9762\u677F Markdown \u53D1\u9001\u5931\u8D25\uFF0C\u964D\u7EA7\u6587\u672C: ${res.error}`);
55
- }
56
- await sendGroupMessage(opts.creds, { groupOpenid, content: text });
57
- }
3
+ import { parseCfgInteractionData } from "./join-settings-ui.js";
58
4
  function createInteractionRouter(opts) {
5
+ const recent = /* @__PURE__ */ new Map();
59
6
  return {
60
7
  async handle(raw) {
61
8
  const d = raw ?? {};
62
- const interactionId = String(d.id ?? "").trim();
63
- if (!interactionId) {
64
- log.warn("INTERACTION \u7F3A\u5C11 id\uFF0C\u8DF3\u8FC7");
65
- return;
66
- }
67
- if (!remember(interactionId)) {
68
- log.info(`INTERACTION \u53BB\u91CD\u8DF3\u8FC7 id=${interactionId}`);
69
- return;
70
- }
71
- const ack = await ackInteraction(opts.creds, interactionId);
72
- if (!ack.ok) {
73
- log.warn(`ackInteraction \u5931\u8D25: ${ack.error}`);
74
- }
75
- const userId = extractUserOpenid(d);
76
- const data = extractData(d);
77
- const groupOpenid = String(d.group_openid ?? "").trim();
78
- log.info(`INTERACTION data=${data || "?"} user=${userId || "?"} group=${groupOpenid || "?"}`);
79
- const cfg = parseCfgInteractionData(data);
80
- if (cfg) {
81
- if (!opts.adminOpenids.includes(userId)) {
82
- await replyGroup(opts, groupOpenid, "\u4F60\u6CA1\u6709\u914D\u7F6E\u6743\u9650\u3002");
83
- return;
84
- }
85
- try {
86
- const body = { openid: userId };
87
- if (cfg.field === "allowlist_enabled") body.allowlist_enabled = cfg.value;
88
- else body.require_approval = cfg.value;
89
- const { data: result } = await postJoinSettings(opts.db, body);
90
- if (result.success === false) {
91
- await replyGroup(opts, groupOpenid, `\u4FDD\u5B58\u5931\u8D25\uFF1A${result.error || result.note || "unknown"}`);
92
- return;
93
- }
94
- const panel = buildJoinSettingsPanel({
95
- settings: settingsFromResponse(result),
96
- backend: "official",
97
- adminOpenids: opts.adminOpenids,
98
- prefix: "\u5DF2\u4FDD\u5B58"
99
- });
100
- await replyGroup(opts, groupOpenid, panel.text, panel);
101
- } catch (e) {
102
- log.warn(`cfg settings \u5931\u8D25: ${e.message}`);
103
- await replyGroup(opts, groupOpenid, `\u4FDD\u5B58\u5931\u8D25\uFF1A${e.message}`);
104
- }
105
- return;
106
- }
107
- const m = /^(join):(approve|reject):(.+)$/.exec(data);
108
- if (!m) {
109
- log.warn(`\u672A\u77E5 INTERACTION data: ${data.slice(0, 80)}`);
110
- return;
111
- }
112
- const decision = m[2] === "approve" ? "approve" : "reject";
113
- const requestId = String(m[3] ?? "").trim();
114
- if (!requestId) return;
115
- if (!opts.adminOpenids.includes(userId)) {
116
- if (groupOpenid) {
117
- await sendGroupMessage(opts.creds, {
118
- groupOpenid,
119
- content: "\u4F60\u6CA1\u6709\u5BA1\u6279\u6743\u9650\u3002"
120
- });
121
- }
122
- return;
123
- }
9
+ const id = String(d["id"] ?? "");
10
+ if (!id) return;
11
+ for (const [key, time] of recent) if (Date.now() - time > 6e4) recent.delete(key);
12
+ if (recent.has(id)) return;
13
+ recent.set(id, Date.now());
124
14
  try {
125
- const { data: result } = await postJoinDecide(opts.db, {
126
- id: requestId,
127
- decision,
128
- decided_by: userId
129
- });
130
- const name = result.player_name || "?";
131
- const text = result.success === false ? `\u5BA1\u6279\u5931\u8D25\uFF1A${result.error || "unknown"}` : decision === "approve" ? `\u5DF2\u901A\u8FC7\u300C${name}\u300D\u5165\u670D\u7533\u8BF7\uFF08\u7B49\u5F85 BDS \u5199\u5165\u767D\u540D\u5355\uFF09` : `\u5DF2\u62D2\u7EDD\u300C${name}\u300D\u5165\u670D\u7533\u8BF7`;
132
- if (groupOpenid) {
133
- await sendGroupMessage(opts.creds, { groupOpenid, content: text });
15
+ const ack = await ackInteraction(opts.creds, id);
16
+ if (!ack.ok) log.warn(`\u6309\u94AE\u5E94\u7B54\u5931\u8D25: ${ack.error}`);
17
+ } catch (error) {
18
+ log.warn(`\u6309\u94AE\u5E94\u7B54\u5931\u8D25: ${String(error)}`);
19
+ }
20
+ const author = d["author"] ?? {};
21
+ const user = String(
22
+ d["user_openid"] || d["member_openid"] || author["member_openid"] || author["user_openid"] || author["id"] || ""
23
+ );
24
+ const group = String(d["group_openid"] ?? "");
25
+ if (!user || !group || group !== opts.groupOpenid) return;
26
+ let data = "";
27
+ for (const key of ["data", "button_data", "button", "event_data"]) {
28
+ const value = d[key];
29
+ if (typeof value === "string") {
30
+ data = value.trim();
31
+ break;
134
32
  }
135
- const applicant = String(result.applicant_openid ?? "").trim();
136
- if (result.success !== false && applicant) {
137
- const tip = decision === "approve" ? `\u4F60\u7684\u5165\u670D\u7533\u8BF7\u300C${name}\u300D\u5DF2\u901A\u8FC7\uFF0C\u8BF7\u7B49\u5F85\u670D\u52A1\u5668\u5199\u5165\u767D\u540D\u5355\u3002` : `\u4F60\u7684\u5165\u670D\u7533\u8BF7\u300C${name}\u300D\u5DF2\u62D2\u7EDD\u3002`;
138
- await sendC2cMessage(opts.creds, { userOpenid: applicant, content: tip }).catch(() => void 0);
33
+ if (value && typeof value === "object" && "data" in value) {
34
+ data = String(value.data);
35
+ break;
139
36
  }
140
- } catch (e) {
141
- log.warn(`join decide \u5931\u8D25: ${e.message}`);
142
37
  }
38
+ const cfg = parseCfgInteractionData(data);
39
+ const join = /^join:(approve|reject):(.+)$/.exec(data);
40
+ const command = cfg ? `/config ${cfg.field === "allowlist_enabled" ? "\u767D\u540D\u5355" : "\u5BA1\u6279"} ${cfg.value ? "\u5F00" : "\u5173"}` : join ? `/${join[1]} ${join[2]}` : "/help";
41
+ await opts.commandRouter.handle({
42
+ backend: "official",
43
+ groupId: group,
44
+ userId: user,
45
+ userName: "\u7FA4\u6210\u5458",
46
+ text: command
47
+ });
143
48
  }
144
49
  };
145
50
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/commands/interaction-router.ts"],
4
- "sourcesContent": ["/**\n * commands/interaction-router.ts \u2014 \u5B98\u65B9 INTERACTION_CREATE \u5206\u53D1\n *\n * data \u7EA6\u5B9A\uFF1A\n * join:approve:<id> / join:reject:<id>\n * cfg:allowlist|approval:on|off\n */\n\nimport {\n ackInteraction,\n sendC2cMessage,\n sendGroupMessage,\n type QqOfficialCredentials,\n} from \"@sfmc-bds/sdk/node/qq-official\";\nimport { log } from \"../log.js\";\nimport { postJoinDecide, postJoinSettings, type DbEndpoint } from \"./db-api.js\";\nimport {\n buildJoinSettingsPanel,\n parseCfgInteractionData,\n settingsFromResponse,\n} from \"./join-settings-ui.js\";\nimport { renderOfficial } from \"./render.js\";\n\nexport type InteractionPayload = {\n id?: string;\n data?: string;\n group_openid?: string;\n chat_type?: number;\n /** \u70B9\u51FB\u4EBA */\n user_openid?: string;\n member_openid?: string;\n author?: { id?: string; member_openid?: string; user_openid?: string };\n};\n\nexport type InteractionRouterOpts = {\n creds: QqOfficialCredentials;\n db: DbEndpoint;\n adminOpenids: string[];\n};\n\nconst recentIds = new Map<string, number>();\nconst DEDUP_MS = 60_000;\n\nfunction remember(id: string): boolean {\n const now = Date.now();\n for (const [k, t] of recentIds) {\n if (now - t > DEDUP_MS) recentIds.delete(k);\n }\n if (recentIds.has(id)) return false;\n recentIds.set(id, now);\n return true;\n}\n\nfunction extractUserOpenid(d: InteractionPayload): string {\n return String(\n d.user_openid ||\n d.member_openid ||\n d.author?.member_openid ||\n d.author?.user_openid ||\n d.author?.id ||\n \"\"\n ).trim();\n}\n\nfunction extractData(d: InteractionPayload): string {\n const raw = d.data;\n if (typeof raw === \"string\") return raw.trim();\n // \u90E8\u5206\u4E8B\u4EF6\u628A button \u5D4C\u5728 nested \u5B57\u6BB5\n const nested = d as Record<string, unknown>;\n for (const key of [\"button_data\", \"button\", \"event_data\"]) {\n const v = nested[key];\n if (typeof v === \"string\") return v.trim();\n if (v && typeof v === \"object\" && \"data\" in (v as object)) {\n return String((v as { data?: string }).data ?? \"\").trim();\n }\n }\n return \"\";\n}\n\nasync function replyGroup(\n opts: InteractionRouterOpts,\n groupOpenid: string,\n text: string,\n panel?: ReturnType<typeof buildJoinSettingsPanel>\n): Promise<void> {\n if (!groupOpenid) return;\n if (panel) {\n const rendered = renderOfficial(panel);\n const res = await sendGroupMessage(opts.creds, {\n groupOpenid,\n msgType: rendered.msgType,\n ...(rendered.msgType === 2\n ? { markdown: rendered.markdown ?? panel.text }\n : { content: rendered.content ?? panel.text }),\n ...(rendered.keyboardButtons ? { keyboardButtons: rendered.keyboardButtons } : {}),\n });\n if (res.ok) return;\n log.warn(`\u914D\u7F6E\u9762\u677F Markdown \u53D1\u9001\u5931\u8D25\uFF0C\u964D\u7EA7\u6587\u672C: ${res.error}`);\n }\n await sendGroupMessage(opts.creds, { groupOpenid, content: text });\n}\n\nexport function createInteractionRouter(opts: InteractionRouterOpts) {\n return {\n async handle(raw: unknown): Promise<void> {\n const d = (raw ?? {}) as InteractionPayload;\n const interactionId = String(d.id ?? \"\").trim();\n if (!interactionId) {\n log.warn(\"INTERACTION \u7F3A\u5C11 id\uFF0C\u8DF3\u8FC7\");\n return;\n }\n if (!remember(interactionId)) {\n log.info(`INTERACTION \u53BB\u91CD\u8DF3\u8FC7 id=${interactionId}`);\n return;\n }\n\n // \u5148 ack\uFF0C\u907F\u514D\u5BA2\u6237\u7AEF\u4E00\u76F4 loading\n const ack = await ackInteraction(opts.creds, interactionId);\n if (!ack.ok) {\n log.warn(`ackInteraction \u5931\u8D25: ${ack.error}`);\n }\n\n const userId = extractUserOpenid(d);\n const data = extractData(d);\n const groupOpenid = String(d.group_openid ?? \"\").trim();\n log.info(`INTERACTION data=${data || \"?\"} user=${userId || \"?\"} group=${groupOpenid || \"?\"}`);\n\n const cfg = parseCfgInteractionData(data);\n if (cfg) {\n if (!opts.adminOpenids.includes(userId)) {\n await replyGroup(opts, groupOpenid, \"\u4F60\u6CA1\u6709\u914D\u7F6E\u6743\u9650\u3002\");\n return;\n }\n try {\n const body: {\n openid: string;\n allowlist_enabled?: boolean;\n require_approval?: boolean;\n } = { openid: userId };\n if (cfg.field === \"allowlist_enabled\") body.allowlist_enabled = cfg.value;\n else body.require_approval = cfg.value;\n\n const { data: result } = await postJoinSettings(opts.db, body);\n if (result.success === false) {\n await replyGroup(opts, groupOpenid, `\u4FDD\u5B58\u5931\u8D25\uFF1A${result.error || result.note || \"unknown\"}`);\n return;\n }\n const panel = buildJoinSettingsPanel({\n settings: settingsFromResponse(result),\n backend: \"official\",\n adminOpenids: opts.adminOpenids,\n prefix: \"\u5DF2\u4FDD\u5B58\",\n });\n await replyGroup(opts, groupOpenid, panel.text, panel);\n } catch (e) {\n log.warn(`cfg settings \u5931\u8D25: ${(e as Error).message}`);\n await replyGroup(opts, groupOpenid, `\u4FDD\u5B58\u5931\u8D25\uFF1A${(e as Error).message}`);\n }\n return;\n }\n\n const m = /^(join):(approve|reject):(.+)$/.exec(data);\n if (!m) {\n log.warn(`\u672A\u77E5 INTERACTION data: ${data.slice(0, 80)}`);\n return;\n }\n const decision = m[2] === \"approve\" ? (\"approve\" as const) : (\"reject\" as const);\n const requestId = String(m[3] ?? \"\").trim();\n if (!requestId) return;\n\n if (!opts.adminOpenids.includes(userId)) {\n if (groupOpenid) {\n await sendGroupMessage(opts.creds, {\n groupOpenid,\n content: \"\u4F60\u6CA1\u6709\u5BA1\u6279\u6743\u9650\u3002\",\n });\n }\n return;\n }\n\n try {\n const { data: result } = await postJoinDecide(opts.db, {\n id: requestId,\n decision,\n decided_by: userId,\n });\n const name = result.player_name || \"?\";\n const text =\n result.success === false\n ? `\u5BA1\u6279\u5931\u8D25\uFF1A${result.error || \"unknown\"}`\n : decision === \"approve\"\n ? `\u5DF2\u901A\u8FC7\u300C${name}\u300D\u5165\u670D\u7533\u8BF7\uFF08\u7B49\u5F85 BDS \u5199\u5165\u767D\u540D\u5355\uFF09`\n : `\u5DF2\u62D2\u7EDD\u300C${name}\u300D\u5165\u670D\u7533\u8BF7`;\n if (groupOpenid) {\n await sendGroupMessage(opts.creds, { groupOpenid, content: text });\n }\n // \u901A\u77E5\u7533\u8BF7\u4EBA\uFF08\u5355\u804A\uFF1B\u5931\u8D25\u5FFD\u7565\uFF09\n const applicant = String(result.applicant_openid ?? \"\").trim();\n if (result.success !== false && applicant) {\n const tip =\n decision === \"approve\"\n ? `\u4F60\u7684\u5165\u670D\u7533\u8BF7\u300C${name}\u300D\u5DF2\u901A\u8FC7\uFF0C\u8BF7\u7B49\u5F85\u670D\u52A1\u5668\u5199\u5165\u767D\u540D\u5355\u3002`\n : `\u4F60\u7684\u5165\u670D\u7533\u8BF7\u300C${name}\u300D\u5DF2\u62D2\u7EDD\u3002`;\n await sendC2cMessage(opts.creds, { userOpenid: applicant, content: tip }).catch(() => undefined);\n }\n } catch (e) {\n log.warn(`join decide \u5931\u8D25: ${(e as Error).message}`);\n }\n },\n };\n}\n\nexport type InteractionRouter = ReturnType<typeof createInteractionRouter>;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { ackInteraction, type QqOfficialCredentials } from \"@sfmc-bds/sdk/node/qq-official\";\nimport { log } from \"../log.js\";\nimport { parseCfgInteractionData } from \"./join-settings-ui.js\";\nimport type { CommandRouter } from \"./router.js\";\n\nexport type InteractionRouterOpts = { creds: QqOfficialCredentials; commandRouter: CommandRouter; groupOpenid: string };\nexport function createInteractionRouter(opts: InteractionRouterOpts) {\n const recent = new Map<string, number>();\n return {\n async handle(raw: unknown): Promise<void> {\n const d = (raw ?? {}) as Record<string, unknown>;\n const id = String(d[\"id\"] ?? \"\");\n if (!id) return;\n for (const [key, time] of recent) if (Date.now() - time > 60_000) recent.delete(key);\n if (recent.has(id)) return;\n recent.set(id, Date.now());\n try {\n const ack = await ackInteraction(opts.creds, id);\n if (!ack.ok) log.warn(`\u6309\u94AE\u5E94\u7B54\u5931\u8D25: ${ack.error}`);\n } catch (error) {\n log.warn(`\u6309\u94AE\u5E94\u7B54\u5931\u8D25: ${String(error)}`);\n }\n const author = (d[\"author\"] ?? {}) as Record<string, unknown>;\n const user = String(\n d[\"user_openid\"] || d[\"member_openid\"] || author[\"member_openid\"] || author[\"user_openid\"] || author[\"id\"] || \"\"\n );\n const group = String(d[\"group_openid\"] ?? \"\");\n if (!user || !group || group !== opts.groupOpenid) return;\n let data = \"\";\n for (const key of [\"data\", \"button_data\", \"button\", \"event_data\"]) {\n const value = d[key];\n if (typeof value === \"string\") {\n data = value.trim();\n break;\n }\n if (value && typeof value === \"object\" && \"data\" in value) {\n data = String(value.data);\n break;\n }\n }\n const cfg = parseCfgInteractionData(data);\n const join = /^join:(approve|reject):(.+)$/.exec(data);\n const command = cfg\n ? `/config ${cfg.field === \"allowlist_enabled\" ? \"\u767D\u540D\u5355\" : \"\u5BA1\u6279\"} ${cfg.value ? \"\u5F00\" : \"\u5173\"}`\n : join\n ? `/${join[1]} ${join[2]}`\n : \"/help\";\n // \u65E7\u56DE\u8C03\u6CA1\u6709\u53EF\u9760\u7FA4\u89D2\u8272\u4FE1\u606F\uFF0C\u670D\u52A1\u7AEF\u4EC5\u6309\u660E\u786E\u7BA1\u7406\u5458\u8EAB\u4EFD\u6388\u6743\u3002\n await opts.commandRouter.handle({\n backend: \"official\",\n groupId: group,\n userId: user,\n userName: \"\u7FA4\u6210\u5458\",\n text: command,\n });\n },\n };\n}\nexport type InteractionRouter = ReturnType<typeof createInteractionRouter>;\n"],
5
+ "mappings": "AAAA,SAAS,sBAAkD;AAC3D,SAAS,WAAW;AACpB,SAAS,+BAA+B;AAIjC,SAAS,wBAAwB,MAA6B;AACnE,QAAM,SAAS,oBAAI,IAAoB;AACvC,SAAO;AAAA,IACL,MAAM,OAAO,KAA6B;AACxC,YAAM,IAAK,OAAO,CAAC;AACnB,YAAM,KAAK,OAAO,EAAE,IAAI,KAAK,EAAE;AAC/B,UAAI,CAAC,GAAI;AACT,iBAAW,CAAC,KAAK,IAAI,KAAK,OAAQ,KAAI,KAAK,IAAI,IAAI,OAAO,IAAQ,QAAO,OAAO,GAAG;AACnF,UAAI,OAAO,IAAI,EAAE,EAAG;AACpB,aAAO,IAAI,IAAI,KAAK,IAAI,CAAC;AACzB,UAAI;AACF,cAAM,MAAM,MAAM,eAAe,KAAK,OAAO,EAAE;AAC/C,YAAI,CAAC,IAAI,GAAI,KAAI,KAAK,yCAAW,IAAI,KAAK,EAAE;AAAA,MAC9C,SAAS,OAAO;AACd,YAAI,KAAK,yCAAW,OAAO,KAAK,CAAC,EAAE;AAAA,MACrC;AACA,YAAM,SAAU,EAAE,QAAQ,KAAK,CAAC;AAChC,YAAM,OAAO;AAAA,QACX,EAAE,aAAa,KAAK,EAAE,eAAe,KAAK,OAAO,eAAe,KAAK,OAAO,aAAa,KAAK,OAAO,IAAI,KAAK;AAAA,MAChH;AACA,YAAM,QAAQ,OAAO,EAAE,cAAc,KAAK,EAAE;AAC5C,UAAI,CAAC,QAAQ,CAAC,SAAS,UAAU,KAAK,YAAa;AACnD,UAAI,OAAO;AACX,iBAAW,OAAO,CAAC,QAAQ,eAAe,UAAU,YAAY,GAAG;AACjE,cAAM,QAAQ,EAAE,GAAG;AACnB,YAAI,OAAO,UAAU,UAAU;AAC7B,iBAAO,MAAM,KAAK;AAClB;AAAA,QACF;AACA,YAAI,SAAS,OAAO,UAAU,YAAY,UAAU,OAAO;AACzD,iBAAO,OAAO,MAAM,IAAI;AACxB;AAAA,QACF;AAAA,MACF;AACA,YAAM,MAAM,wBAAwB,IAAI;AACxC,YAAM,OAAO,+BAA+B,KAAK,IAAI;AACrD,YAAM,UAAU,MACZ,WAAW,IAAI,UAAU,sBAAsB,uBAAQ,cAAI,IAAI,IAAI,QAAQ,WAAM,QAAG,KACpF,OACE,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KACtB;AAEN,YAAM,KAAK,cAAc,OAAO;AAAA,QAC9B,SAAS;AAAA,QACT,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -30,36 +30,13 @@ function formatJoinSettingsMarkdown(s, prefix) {
30
30
  ];
31
31
  return lines.join("\n");
32
32
  }
33
- function buildJoinSettingsButtons(s, backend, adminOpenids = []) {
33
+ function buildJoinSettingsButtons(s, _backend, _adminOpenids = []) {
34
34
  const alOn = s.allowlist_enabled !== false;
35
35
  const apOn = s.require_approval !== false;
36
36
  const alTarget = !alOn;
37
37
  const apTarget = !apOn;
38
38
  const alWord = alTarget ? "\u5F00" : "\u5173";
39
39
  const apWord = apTarget ? "\u5F00" : "\u5173";
40
- const permission = adminOpenids.length > 0 ? { type: 0, specify_user_ids: adminOpenids } : { type: 2 };
41
- if (backend === "official") {
42
- return [
43
- {
44
- id: "cfg_al",
45
- label: `\u767D\u540D\u5355\xB7${alWord}`,
46
- command: `cfg:allowlist:${alTarget ? "on" : "off"}`,
47
- actionType: 1,
48
- style: alTarget ? 1 : 0,
49
- visitedLabel: `\u767D\u540D\u5355\xB7${alWord}`,
50
- permission
51
- },
52
- {
53
- id: "cfg_ap",
54
- label: `\u5BA1\u6279\xB7${apWord}`,
55
- command: `cfg:approval:${apTarget ? "on" : "off"}`,
56
- actionType: 1,
57
- style: apTarget ? 1 : 0,
58
- visitedLabel: `\u5BA1\u6279\xB7${apWord}`,
59
- permission
60
- }
61
- ];
62
- }
63
40
  return [
64
41
  {
65
42
  id: "cfg_al",