@sfmc-bds/qq-bridge 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/content-format.js +3 -3
- package/dist/commands/content-format.js.map +2 -2
- package/dist/commands/db-api.js.map +1 -1
- package/dist/commands/handlers.js +7 -13
- package/dist/commands/handlers.js.map +2 -2
- package/dist/commands/menu-format.js +1 -1
- package/dist/commands/menu-format.js.map +1 -1
- package/dist/commands/message-text.js.map +2 -2
- package/dist/commands/reply-official.js.map +1 -1
- package/dist/console.js +1 -1
- package/dist/console.js.map +2 -2
- package/dist/dbserver.js +6 -3
- package/dist/dbserver.js.map +2 -2
- package/dist/index.js +4 -7
- package/dist/index.js.map +2 -2
- package/dist/official/events.js +6 -7
- package/dist/official/events.js.map +2 -2
- package/dist/onebot.js.map +1 -1
- package/package.json +3 -3
|
@@ -58,16 +58,16 @@ function markdownTable(rows) {
|
|
|
58
58
|
}
|
|
59
59
|
function formatPackMarkdown(packs, worldNote) {
|
|
60
60
|
if (worldNote === "bds_unconfigured") {
|
|
61
|
-
return ["## \
|
|
61
|
+
return ["## \u8D44\u6E90\u5305", "", "\u672A\u914D\u7F6E BDS \u8DEF\u5F84\uFF0C\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u4E16\u754C\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\u3002"].join("\n");
|
|
62
62
|
}
|
|
63
63
|
if (worldNote === "world_unread") {
|
|
64
|
-
return ["## \
|
|
64
|
+
return ["## \u8D44\u6E90\u5305", "", "\u4E16\u754C\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\u6682\u65F6\u8BFB\u4E0D\u51FA\u6765\u3002"].join("\n");
|
|
65
65
|
}
|
|
66
66
|
const sections = [
|
|
67
67
|
{ kind: "behavior", title: "\u884C\u4E3A\u5305", empty: "\u4E16\u754C\u91CC\u6CA1\u6709\u884C\u4E3A\u5305\u3002" },
|
|
68
68
|
{ kind: "resource", title: "\u8D44\u6E90\u5305", empty: "\u4E16\u754C\u91CC\u6CA1\u6709\u8D44\u6E90\u5305\u3002" }
|
|
69
69
|
];
|
|
70
|
-
const lines = ["## \
|
|
70
|
+
const lines = ["## \u8D44\u6E90\u5305", ""];
|
|
71
71
|
for (const section of sections) {
|
|
72
72
|
const group = packs.filter((pack) => (pack.kind ?? "resource") === section.kind);
|
|
73
73
|
const enabled = group.filter((pack) => pack.enabled !== false);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/content-format.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * content-format.ts \u2014 \u628A\u6A21\u5757 / \
|
|
5
|
-
"mappings": "AAyBO,SAAS,cAAc,KAAwB,SAA0B;AAC9E,QAAM,IAAI,QAAQ,KAAK,EAAE,YAAY;AACrC,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,OAAO,OAAO,IAAI,gBAAgB,IAAI,MAAM,EAAE,EAAE,YAAY;AAClE,
|
|
4
|
+
"sourcesContent": ["/**\n * content-format.ts \u2014 \u628A\u6A21\u5757 / \u8D44\u6E90\u5305\u5FEB\u7167\u6392\u6210 QQ \u4FE1\u606F\u5361\u6B63\u6587\u3002\n *\n * \u300C\u6A21\u5757\u300D\u5217\u51FA\u542F\u505C\u548C\u662F\u5426\u81EA\u5E26\u8D44\u6E90\u5305\u3002\n * \u300C\u8D44\u6E90\u5305\u300D\u7684 Markdown \u7528\u8868\u683C\u5206\u5217\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\uFF1B\u7EAF\u6587\u672C\u4ECD\u4FDD\u7559\u539F\u6765\u7684\u9010\u884C\u5217\u8868\uFF0C\u4F9B Markdown \u53D1\u9001\u5931\u8D25\u65F6\u964D\u7EA7\u3002\n */\n\nexport type ContentModuleView = {\n id: string;\n display_name?: string;\n enabled?: boolean;\n has_resource_pack?: boolean;\n};\n\n/** \u4E00\u6761\u8D44\u6E90\u5305\u3002kind \u7F3A\u7701\u65F6\u6309\u8D44\u6E90\u5305\u5904\u7406\uFF0C\u517C\u5BB9\u8FD8\u6CA1\u5206\u5F00\u8FD4\u56DE\u7684\u65E7\u5FEB\u7167\u3002 */\nexport type WorldPackView = {\n kind?: \"behavior\" | \"resource\";\n name?: string;\n folder_name?: string;\n pack_id?: string;\n version?: string;\n enabled?: boolean;\n};\n\n/** \u5173\u952E\u5B57\u5339\u914D\u6A21\u5757\u540D\u6216 id\u3002\u7A7A\u5173\u952E\u5B57\u8868\u793A\u5168\u90E8\u3002 */\nexport function moduleMatches(mod: ContentModuleView, keyword: string): boolean {\n const q = keyword.trim().toLowerCase();\n if (!q) return true;\n const name = String(mod.display_name || mod.id || \"\").toLowerCase();\n return (\n name.includes(q) ||\n String(mod.id || \"\")\n .toLowerCase()\n .includes(q)\n );\n}\n\n/** \u6A21\u5757\u67E5\u8BE2\u6B63\u6587\u3002\u5DF2\u542F\u7528\u6392\u5728\u524D\u9762\uFF0C\u4FBF\u4E8E\u5728\u7FA4\u91CC\u626B\u4E00\u773C\u5F53\u524D\u5728\u8DD1\u4EC0\u4E48\u3002 */\nexport function formatModuleLines(modules: ContentModuleView[], keyword = \"\"): string[] {\n const matched = modules.filter((mod) => moduleMatches(mod, keyword));\n if (!matched.length) {\n return keyword ? [`\u6CA1\u6709\u540D\u79F0\u5305\u542B\u300C${keyword}\u300D\u7684\u6A21\u5757\u3002`] : [\"\u5F53\u524D\u6CA1\u6709\u5DF2\u5B89\u88C5\u6A21\u5757\u3002\"];\n }\n const enabled = matched.filter((mod) => mod.enabled !== false);\n const disabled = matched.filter((mod) => mod.enabled === false);\n const lines = [`\u5DF2\u542F\u7528 ${enabled.length}\uFF0C\u672A\u542F\u7528 ${disabled.length}`];\n const render = (mod: ContentModuleView) => {\n const name = mod.display_name || mod.id || \"\u672A\u547D\u540D\u6A21\u5757\";\n const state = mod.enabled === false ? \"\u5173\" : \"\u5F00\";\n const pack = mod.has_resource_pack ? \" \u00B7 \u542B\u8D44\u6E90\u5305\" : \"\";\n return `${name}\uFF08${state}${pack}\uFF09`;\n };\n if (enabled.length) {\n lines.push(\"\", \"\u3010\u5DF2\u542F\u7528\u3011\", ...enabled.map(render));\n }\n if (disabled.length) {\n lines.push(\"\", \"\u3010\u672A\u542F\u7528\u3011\", ...disabled.map(render));\n }\n return lines;\n}\n\n/** \u5355\u6761\u8D44\u6E90\u5305\uFF1A\u771F\u5B9E\u540D\u79F0\u4F18\u5148\uFF0C\u8BED\u8A00\u952E\u6B8B\u7559\u65F6\u9000\u56DE\u6587\u4EF6\u5939\u540D\u3002 */\nfunction formatWorldPackLine(pack: WorldPackView): string {\n const resolved = String(pack.name || \"\").trim();\n const folder = String(pack.folder_name || \"\").trim();\n const name =\n !resolved || resolved.startsWith(\"pack.\") || resolved === \"pack\" ? folder || pack.pack_id || \"\u672A\u547D\u540D\" : resolved;\n const folderBit = folder && folder !== name ? `${folder} \u00B7 ` : \"\";\n const version = pack.version ? ` v${pack.version}` : \"\";\n const state = pack.enabled === false ? \"\u5173\" : \"\u5F00\";\n return `${folderBit}${name}${version}\uFF08${state}\uFF09`;\n}\n\n/** \u8868\u683C\u5355\u5143\u683C\uFF1A\u53BB\u6389\u57FA\u5CA9\u7248\u989C\u8272\u7801\uFF0C\u5E76\u8F6C\u4E49\u4F1A\u62C6\u5217\u7684\u7AD6\u7EBF\u3002 */\nfunction markdownCell(value: string): string {\n const text = value\n .replace(/\u00A7[0-9a-zA-Z]/g, \"\")\n .replace(/\\|/g, \"\\\\|\")\n .replace(/\\r?\\n/g, \" \")\n .trim();\n return text || \"\u2014\";\n}\n\n/** \u4E0E\u7EAF\u6587\u672C\u5217\u8868\u540C\u4E00\u5957\u540D\u79F0\u56DE\u9000\uFF1A\u8BED\u8A00\u952E\u6B8B\u7559\u65F6\u7528\u6587\u4EF6\u5939\u540D\u3002 */\nfunction packFields(pack: WorldPackView): { state: string; name: string; version: string } {\n const resolved = String(pack.name || \"\").trim();\n const folder = String(pack.folder_name || \"\").trim();\n const name =\n !resolved || resolved.startsWith(\"pack.\") || resolved === \"pack\" ? folder || pack.pack_id || \"\u672A\u547D\u540D\" : resolved;\n return {\n state: pack.enabled === false ? \"\u5173\" : \"\u5F00\",\n name: markdownCell(name),\n version: markdownCell(pack.version || \"\u2014\"),\n };\n}\n\nfunction markdownTable(rows: Array<{ state: string; name: string; version: string }>): string[] {\n return [\n \"| \u72B6\u6001 | \u540D\u79F0 | \u7248\u672C |\",\n \"| --- | --- | --- |\",\n ...rows.map((row) => `| ${row.state} | ${row.name} | ${row.version} |`),\n ];\n}\n\n/**\n * \u8D44\u6E90\u5305\u7684 Markdown \u6B63\u6587\u3002\u884C\u4E3A\u5305\u3001\u8D44\u6E90\u5305\u5404\u4E00\u5F20\u8868\uFF0C\u5DF2\u542F\u7528\u6392\u5728\u524D\u9762\u3002\n * \u8BFB\u4E0D\u5230\u4E16\u754C\u65F6\u53EA\u7ED9\u8BF4\u660E\uFF0C\u4E0D\u8F93\u51FA\u7A7A\u8868\u3002\n */\nexport function formatPackMarkdown(packs: WorldPackView[], worldNote?: string): string {\n if (worldNote === \"bds_unconfigured\") {\n return [\"## \u8D44\u6E90\u5305\", \"\", \"\u672A\u914D\u7F6E BDS \u8DEF\u5F84\uFF0C\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u4E16\u754C\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\u3002\"].join(\"\\n\");\n }\n if (worldNote === \"world_unread\") {\n return [\"## \u8D44\u6E90\u5305\", \"\", \"\u4E16\u754C\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\u6682\u65F6\u8BFB\u4E0D\u51FA\u6765\u3002\"].join(\"\\n\");\n }\n const sections: Array<{ kind: \"behavior\" | \"resource\"; title: string; empty: string }> = [\n { kind: \"behavior\", title: \"\u884C\u4E3A\u5305\", empty: \"\u4E16\u754C\u91CC\u6CA1\u6709\u884C\u4E3A\u5305\u3002\" },\n { kind: \"resource\", title: \"\u8D44\u6E90\u5305\", empty: \"\u4E16\u754C\u91CC\u6CA1\u6709\u8D44\u6E90\u5305\u3002\" },\n ];\n const lines = [\"## \u8D44\u6E90\u5305\", \"\"];\n for (const section of sections) {\n const group = packs.filter((pack) => (pack.kind ?? \"resource\") === section.kind);\n const enabled = group.filter((pack) => pack.enabled !== false);\n const disabled = group.filter((pack) => pack.enabled === false);\n lines.push(`### ${section.title}`, \"\");\n if (!group.length) {\n lines.push(section.empty, \"\");\n continue;\n }\n lines.push(`\u5DF2\u542F\u7528 ${enabled.length}\uFF0C\u672A\u542F\u7528 ${disabled.length}`, \"\");\n lines.push(...markdownTable([...enabled, ...disabled].map(packFields)), \"\");\n }\n return lines.join(\"\\n\").trimEnd();\n}\n\n/**\n * \u8D44\u6E90\u5305\u67E5\u8BE2\u6B63\u6587\u3002\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\u5206\u5F00\u5C55\u793A\uFF0C\u5DF2\u542F\u7528\u6392\u5728\u524D\u9762\u3002\n * worldNote \u6765\u81EA db-server\uFF1A\u672A\u914D\u7F6E BDS \u6216\u4E16\u754C\u76EE\u5F55\u8BFB\u5931\u8D25\u65F6\u53EA\u8BF4\u660E\u539F\u56E0\u3002\n */\nexport function formatPackLines(packs: WorldPackView[], worldNote?: string): string[] {\n if (worldNote === \"bds_unconfigured\") return [\"\u672A\u914D\u7F6E BDS \u8DEF\u5F84\uFF0C\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u4E16\u754C\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\u3002\"];\n if (worldNote === \"world_unread\") return [\"\u4E16\u754C\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305\u6682\u65F6\u8BFB\u4E0D\u51FA\u6765\u3002\"];\n const sections: Array<{ kind: \"behavior\" | \"resource\"; title: string; empty: string }> = [\n { kind: \"behavior\", title: \"\u3010\u884C\u4E3A\u5305\u3011\", empty: \"\u4E16\u754C\u91CC\u6CA1\u6709\u884C\u4E3A\u5305\u3002\" },\n { kind: \"resource\", title: \"\u3010\u8D44\u6E90\u5305\u3011\", empty: \"\u4E16\u754C\u91CC\u6CA1\u6709\u8D44\u6E90\u5305\u3002\" },\n ];\n const lines: string[] = [];\n for (const section of sections) {\n const group = packs.filter((pack) => (pack.kind ?? \"resource\") === section.kind);\n const enabled = group.filter((pack) => pack.enabled !== false);\n const disabled = group.filter((pack) => pack.enabled === false);\n if (lines.length) lines.push(\"\");\n lines.push(section.title);\n if (!group.length) {\n lines.push(section.empty);\n continue;\n }\n lines.push(`\u5DF2\u542F\u7528 ${enabled.length}\uFF0C\u672A\u542F\u7528 ${disabled.length}`);\n lines.push(...enabled.map(formatWorldPackLine), ...disabled.map(formatWorldPackLine));\n }\n return lines;\n}\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/db-api.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * commands/db-api.ts \u2014 qq-bridge \u8C03 db-server \u5E73\u53F0 API\uFF08status / bind\uFF09\n */\n\nimport { request as httpRequest, type RequestOptions } from \"node:http\";\n\nexport type DbEndpoint = { host: string; port: number };\n\nconst TIMEOUT_MS = 5_000;\n\nfunction requestJson<T>(\n ep: DbEndpoint,\n method: string,\n pathAndQuery: string,\n body?: unknown\n): Promise<{ status: number; data: T }> {\n const payload = body === undefined ? undefined : JSON.stringify(body);\n const options: RequestOptions = {\n hostname: ep.host,\n port: ep.port,\n path: pathAndQuery,\n method,\n headers: {\n Accept: \"application/json\",\n ...(payload\n ? {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": Buffer.byteLength(payload),\n }\n : {}),\n },\n timeout: TIMEOUT_MS,\n };\n return new Promise((resolve, reject) => {\n const req = httpRequest(options, (res) => {\n let buf = \"\";\n res.setEncoding(\"utf-8\");\n res.on(\"data\", (c: string) => {\n buf += c;\n });\n res.on(\"end\", () => {\n const status = res.statusCode ?? 0;\n if (status >= 500 || status === 401 || status === 404) {\n reject(new Error(`db-server HTTP ${status}`));\n return;\n }\n try {\n resolve({ status, data: JSON.parse(buf) as T });\n } catch {\n reject(new Error(`db-server \u975E JSON (${status})`));\n }\n });\n });\n req.on(\"timeout\", () => req.destroy(new Error(`db-server \u8D85\u65F6 ${TIMEOUT_MS}ms`)));\n req.on(\"error\", reject);\n if (payload) req.write(payload);\n req.end();\n });\n}\n\nexport type SfmcHostStatus = {\n hostname?: string;\n platform?: string;\n arch?: string;\n release?: string;\n uptimeSec?: number;\n uptimeText?: string;\n cpu?: { model?: string; cores?: number };\n memory?: { totalMb?: number; freeMb?: number; usedMb?: number; usedPercent?: number };\n loadavg?: [number, number, number];\n};\n\nexport type SfmcProcessStatus = {\n version?: string;\n pid?: number;\n running?: boolean;\n uptimeSec?: number | null;\n uptimeText?: string;\n state?: \"running\" | \"stopped\";\n};\n\nexport type SfmcStatusResponse = {\n online?: Array<{ id?: string; name?: string }>;\n world?: { day?: number; difficulty?: string } | null;\n updatedAt?: number;\n note?: string;\n host?: SfmcHostStatus | null;\n processes?: {\n db?: SfmcProcessStatus;\n bds?: SfmcProcessStatus;\n } | null;\n};\n\nexport async function fetchSfmcStatus(ep: DbEndpoint): Promise<SfmcStatusResponse> {\n const { data } = await requestJson<SfmcStatusResponse>(ep, \"GET\", \"/api/sfmc/status\");\n return data;\n}\n\nexport type QqEventSettings = {\n enabled: boolean;\n join: boolean;\n leave: boolean;\n death: boolean;\n crash: boolean;\n start: boolean;\n stop: boolean;\n window_sec: number;\n};\n\nexport type QqEventSettingsResponse = {\n success: boolean;\n settings?: QqEventSettings;\n error?: string;\n};\n\nexport async function fetchQqEventSettings(ep: DbEndpoint): Promise<QqEventSettingsResponse> {\n const { data } = await requestJson<QqEventSettingsResponse>(ep, \"GET\", \"/api/sfmc/qq/events/settings\");\n return data;\n}\n\nexport async function postQqEventSettings(\n ep: DbEndpoint,\n body: { openid: string; as_group_admin: boolean; field: keyof QqEventSettings; value: boolean | number }\n): Promise<QqEventSettingsResponse> {\n const { data } = await requestJson<QqEventSettingsResponse>(ep, \"POST\", \"/api/sfmc/qq/events/settings\", body);\n return data;\n}\n\nexport type JoinRequestResponse = {\n success?: boolean;\n id?: string;\n player_name?: string;\n status?: string;\n auto_approved?: boolean;\n admin_notify?: boolean;\n note?: string;\n error?: string;\n};\n\nexport async function postJoinRequest(\n ep: DbEndpoint,\n body: { openid: string; player_name: string; qq_backend: string }\n): Promise<{ status: number; data: JoinRequestResponse }> {\n return requestJson(ep, \"POST\", \"/api/sfmc/qq/join/request\", body);\n}\n\nexport type JoinSettingsResponse = {\n success?: boolean;\n allowlist_enabled?: boolean;\n require_approval?: boolean;\n treat_group_admins_as_admins?: boolean;\n error?: string;\n note?: string;\n};\n\nexport async function fetchJoinSettings(ep: DbEndpoint): Promise<JoinSettingsResponse> {\n const { data } = await requestJson<JoinSettingsResponse>(ep, \"GET\", \"/api/sfmc/qq/join/settings\");\n return data;\n}\n\nexport async function postJoinSettings(\n ep: DbEndpoint,\n body: {\n openid: string;\n as_group_admin?: boolean;\n allowlist_enabled?: boolean;\n require_approval?: boolean;\n }\n): Promise<{ status: number; data: JoinSettingsResponse }> {\n return requestJson(ep, \"POST\", \"/api/sfmc/qq/join/settings\", body);\n}\n\nexport type JoinDecideResponse = {\n success?: boolean;\n id?: string;\n status?: string;\n player_name?: string;\n applicant_openid?: string;\n error?: string;\n};\n\nexport async function postJoinDecide(\n ep: DbEndpoint,\n body: {\n id: string;\n decision: \"approve\" | \"reject\";\n decided_by: string;\n as_group_admin?: boolean;\n }\n): Promise<{ status: number; data: JoinDecideResponse }> {\n return requestJson(ep, \"POST\", \"/api/sfmc/qq/join/decide\", body);\n}\n\nexport async function fetchJoinPending(\n ep: DbEndpoint,\n openid: string,\n asGroupAdmin = false\n): Promise<{\n success?: boolean;\n pending?: Array<{ id?: string; player_name?: string; applicant_openid?: string }>;\n error?: string;\n}> {\n const q =\n `/api/sfmc/qq/join/pending?openid=${encodeURIComponent(openid)}` + (asGroupAdmin ? \"&as_group_admin=true\" : \"\");\n const { data } = await requestJson<Awaited<ReturnType<typeof fetchJoinPending>>>(ep, \"GET\", q);\n return data;\n}\n\nexport type BindMeResponse = {\n success?: boolean;\n bound?: boolean;\n binding?: {\n player_name?: string;\n player_xuid?: string;\n qq_user_openid?: string;\n bound_at?: number;\n } | null;\n /** \u5DF2\u7ED1\u5B9A\u65F6\u9644\u5E26\u7ECF\u6D4E\u4F59\u989D\u548C\u5728\u7EBF\u65F6\u957F\u3002\u65E7 db \u6CA1\u6709\u8FD9\u4E2A\u5B57\u6BB5\u3002 */\n profile?: {\n unit?: string;\n balance?: number | null;\n today_text?: string;\n month_text?: string;\n total_text?: string;\n } | null;\n};\n\nexport async function fetchBindMe(ep: DbEndpoint, openid: string): Promise<BindMeResponse> {\n const q = `/api/sfmc/qq/bind/me?openid=${encodeURIComponent(openid)}`;\n const { data } = await requestJson<BindMeResponse>(ep, \"GET\", q);\n return data;\n}\n\nexport type BindRequestResponse = {\n success?: boolean;\n code?: string;\n expires_at?: number;\n ttl_ms?: number;\n error?: string;\n player_name?: string;\n};\n\nexport async function postBindRequest(\n ep: DbEndpoint,\n body: { openid: string; qq_backend: string }\n): Promise<{ status: number; data: BindRequestResponse }> {\n return requestJson<BindRequestResponse>(ep, \"POST\", \"/api/sfmc/qq/bind/request\", body);\n}\n\nexport type BindUnbindResponse = {\n success?: boolean;\n unbound?: boolean;\n error?: string;\n};\n\nexport type ContentSnapshotResponse = {\n success?: boolean;\n error?: string;\n note?: \"bds_unconfigured\" | \"world_unread\";\n modules?: Array<{\n id: string;\n display_name?: string;\n enabled?: boolean;\n has_resource_pack?: boolean;\n }>;\n /** \u884C\u4E3A\u5305\u4E0E\u8D44\u6E90\u5305\u3002name \u5DF2\u662F\u89E3\u6790\u540E\u7684\u663E\u793A\u540D\u3002 */\n packs?: Array<{\n kind?: \"behavior\" | \"resource\";\n name?: string;\n folder_name?: string;\n pack_id?: string;\n version?: string;\n enabled?: boolean;\n }>;\n resource_packs?: Array<{\n name?: string;\n pack_id?: string;\n version?: string;\n }>;\n};\n\n/** \u67E5\u8BE2\u6E38\u620F\u673A\u4E0A\u7684\u6A21\u5757\u4E0E\u4E16\u754C\u884C\u4E3A\u5305\u3001\u8D44\u6E90\u5305\u3002\u5F53\u524D\u7ED9 QQ\u300C\u6A21\u5757\u300D\u300C\
|
|
4
|
+
"sourcesContent": ["/**\n * commands/db-api.ts \u2014 qq-bridge \u8C03 db-server \u5E73\u53F0 API\uFF08status / bind\uFF09\n */\n\nimport { request as httpRequest, type RequestOptions } from \"node:http\";\n\nexport type DbEndpoint = { host: string; port: number };\n\nconst TIMEOUT_MS = 5_000;\n\nfunction requestJson<T>(\n ep: DbEndpoint,\n method: string,\n pathAndQuery: string,\n body?: unknown\n): Promise<{ status: number; data: T }> {\n const payload = body === undefined ? undefined : JSON.stringify(body);\n const options: RequestOptions = {\n hostname: ep.host,\n port: ep.port,\n path: pathAndQuery,\n method,\n headers: {\n Accept: \"application/json\",\n ...(payload\n ? {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": Buffer.byteLength(payload),\n }\n : {}),\n },\n timeout: TIMEOUT_MS,\n };\n return new Promise((resolve, reject) => {\n const req = httpRequest(options, (res) => {\n let buf = \"\";\n res.setEncoding(\"utf-8\");\n res.on(\"data\", (c: string) => {\n buf += c;\n });\n res.on(\"end\", () => {\n const status = res.statusCode ?? 0;\n if (status >= 500 || status === 401 || status === 404) {\n reject(new Error(`db-server HTTP ${status}`));\n return;\n }\n try {\n resolve({ status, data: JSON.parse(buf) as T });\n } catch {\n reject(new Error(`db-server \u975E JSON (${status})`));\n }\n });\n });\n req.on(\"timeout\", () => req.destroy(new Error(`db-server \u8D85\u65F6 ${TIMEOUT_MS}ms`)));\n req.on(\"error\", reject);\n if (payload) req.write(payload);\n req.end();\n });\n}\n\nexport type SfmcHostStatus = {\n hostname?: string;\n platform?: string;\n arch?: string;\n release?: string;\n uptimeSec?: number;\n uptimeText?: string;\n cpu?: { model?: string; cores?: number };\n memory?: { totalMb?: number; freeMb?: number; usedMb?: number; usedPercent?: number };\n loadavg?: [number, number, number];\n};\n\nexport type SfmcProcessStatus = {\n version?: string;\n pid?: number;\n running?: boolean;\n uptimeSec?: number | null;\n uptimeText?: string;\n state?: \"running\" | \"stopped\";\n};\n\nexport type SfmcStatusResponse = {\n online?: Array<{ id?: string; name?: string }>;\n world?: { day?: number; difficulty?: string } | null;\n updatedAt?: number;\n note?: string;\n host?: SfmcHostStatus | null;\n processes?: {\n db?: SfmcProcessStatus;\n bds?: SfmcProcessStatus;\n } | null;\n};\n\nexport async function fetchSfmcStatus(ep: DbEndpoint): Promise<SfmcStatusResponse> {\n const { data } = await requestJson<SfmcStatusResponse>(ep, \"GET\", \"/api/sfmc/status\");\n return data;\n}\n\nexport type QqEventSettings = {\n enabled: boolean;\n join: boolean;\n leave: boolean;\n death: boolean;\n crash: boolean;\n start: boolean;\n stop: boolean;\n window_sec: number;\n};\n\nexport type QqEventSettingsResponse = {\n success: boolean;\n settings?: QqEventSettings;\n error?: string;\n};\n\nexport async function fetchQqEventSettings(ep: DbEndpoint): Promise<QqEventSettingsResponse> {\n const { data } = await requestJson<QqEventSettingsResponse>(ep, \"GET\", \"/api/sfmc/qq/events/settings\");\n return data;\n}\n\nexport async function postQqEventSettings(\n ep: DbEndpoint,\n body: { openid: string; as_group_admin: boolean; field: keyof QqEventSettings; value: boolean | number }\n): Promise<QqEventSettingsResponse> {\n const { data } = await requestJson<QqEventSettingsResponse>(ep, \"POST\", \"/api/sfmc/qq/events/settings\", body);\n return data;\n}\n\nexport type JoinRequestResponse = {\n success?: boolean;\n id?: string;\n player_name?: string;\n status?: string;\n auto_approved?: boolean;\n admin_notify?: boolean;\n note?: string;\n error?: string;\n};\n\nexport async function postJoinRequest(\n ep: DbEndpoint,\n body: { openid: string; player_name: string; qq_backend: string }\n): Promise<{ status: number; data: JoinRequestResponse }> {\n return requestJson(ep, \"POST\", \"/api/sfmc/qq/join/request\", body);\n}\n\nexport type JoinSettingsResponse = {\n success?: boolean;\n allowlist_enabled?: boolean;\n require_approval?: boolean;\n treat_group_admins_as_admins?: boolean;\n error?: string;\n note?: string;\n};\n\nexport async function fetchJoinSettings(ep: DbEndpoint): Promise<JoinSettingsResponse> {\n const { data } = await requestJson<JoinSettingsResponse>(ep, \"GET\", \"/api/sfmc/qq/join/settings\");\n return data;\n}\n\nexport async function postJoinSettings(\n ep: DbEndpoint,\n body: {\n openid: string;\n as_group_admin?: boolean;\n allowlist_enabled?: boolean;\n require_approval?: boolean;\n }\n): Promise<{ status: number; data: JoinSettingsResponse }> {\n return requestJson(ep, \"POST\", \"/api/sfmc/qq/join/settings\", body);\n}\n\nexport type JoinDecideResponse = {\n success?: boolean;\n id?: string;\n status?: string;\n player_name?: string;\n applicant_openid?: string;\n error?: string;\n};\n\nexport async function postJoinDecide(\n ep: DbEndpoint,\n body: {\n id: string;\n decision: \"approve\" | \"reject\";\n decided_by: string;\n as_group_admin?: boolean;\n }\n): Promise<{ status: number; data: JoinDecideResponse }> {\n return requestJson(ep, \"POST\", \"/api/sfmc/qq/join/decide\", body);\n}\n\nexport async function fetchJoinPending(\n ep: DbEndpoint,\n openid: string,\n asGroupAdmin = false\n): Promise<{\n success?: boolean;\n pending?: Array<{ id?: string; player_name?: string; applicant_openid?: string }>;\n error?: string;\n}> {\n const q =\n `/api/sfmc/qq/join/pending?openid=${encodeURIComponent(openid)}` + (asGroupAdmin ? \"&as_group_admin=true\" : \"\");\n const { data } = await requestJson<Awaited<ReturnType<typeof fetchJoinPending>>>(ep, \"GET\", q);\n return data;\n}\n\nexport type BindMeResponse = {\n success?: boolean;\n bound?: boolean;\n binding?: {\n player_name?: string;\n player_xuid?: string;\n qq_user_openid?: string;\n bound_at?: number;\n } | null;\n /** \u5DF2\u7ED1\u5B9A\u65F6\u9644\u5E26\u7ECF\u6D4E\u4F59\u989D\u548C\u5728\u7EBF\u65F6\u957F\u3002\u65E7 db \u6CA1\u6709\u8FD9\u4E2A\u5B57\u6BB5\u3002 */\n profile?: {\n unit?: string;\n balance?: number | null;\n today_text?: string;\n month_text?: string;\n total_text?: string;\n } | null;\n};\n\nexport async function fetchBindMe(ep: DbEndpoint, openid: string): Promise<BindMeResponse> {\n const q = `/api/sfmc/qq/bind/me?openid=${encodeURIComponent(openid)}`;\n const { data } = await requestJson<BindMeResponse>(ep, \"GET\", q);\n return data;\n}\n\nexport type BindRequestResponse = {\n success?: boolean;\n code?: string;\n expires_at?: number;\n ttl_ms?: number;\n error?: string;\n player_name?: string;\n};\n\nexport async function postBindRequest(\n ep: DbEndpoint,\n body: { openid: string; qq_backend: string }\n): Promise<{ status: number; data: BindRequestResponse }> {\n return requestJson<BindRequestResponse>(ep, \"POST\", \"/api/sfmc/qq/bind/request\", body);\n}\n\nexport type BindUnbindResponse = {\n success?: boolean;\n unbound?: boolean;\n error?: string;\n};\n\nexport type ContentSnapshotResponse = {\n success?: boolean;\n error?: string;\n note?: \"bds_unconfigured\" | \"world_unread\";\n modules?: Array<{\n id: string;\n display_name?: string;\n enabled?: boolean;\n has_resource_pack?: boolean;\n }>;\n /** \u884C\u4E3A\u5305\u4E0E\u8D44\u6E90\u5305\u3002name \u5DF2\u662F\u89E3\u6790\u540E\u7684\u663E\u793A\u540D\u3002 */\n packs?: Array<{\n kind?: \"behavior\" | \"resource\";\n name?: string;\n folder_name?: string;\n pack_id?: string;\n version?: string;\n enabled?: boolean;\n }>;\n resource_packs?: Array<{\n name?: string;\n pack_id?: string;\n version?: string;\n }>;\n};\n\n/** \u67E5\u8BE2\u6E38\u620F\u673A\u4E0A\u7684\u6A21\u5757\u4E0E\u4E16\u754C\u884C\u4E3A\u5305\u3001\u8D44\u6E90\u5305\u3002\u5F53\u524D\u7ED9 QQ\u300C\u6A21\u5757\u300D\u300C\u8D44\u6E90\u5305\u300D\u4F7F\u7528\u3002 */\nexport async function fetchContent(ep: DbEndpoint): Promise<ContentSnapshotResponse> {\n const { data } = await requestJson<ContentSnapshotResponse>(ep, \"GET\", \"/api/sfmc/content\");\n return data;\n}\n\nexport async function postBindUnbind(\n ep: DbEndpoint,\n body: { openid: string }\n): Promise<{ status: number; data: BindUnbindResponse }> {\n return requestJson<BindUnbindResponse>(ep, \"POST\", \"/api/sfmc/qq/bind/unbind\", body);\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getGroupBotState, getGroupInfo } from "@sfmc-bds/sdk/node/qq-official";
|
|
2
2
|
import { log } from "../log.js";
|
|
3
|
+
import { formatAccountCard } from "./account-format.js";
|
|
4
|
+
import { formatModuleLines, formatPackLines, formatPackMarkdown } from "./content-format.js";
|
|
3
5
|
import {
|
|
4
6
|
fetchBindMe,
|
|
5
7
|
fetchContent,
|
|
@@ -9,8 +11,6 @@ import {
|
|
|
9
11
|
postBindUnbind,
|
|
10
12
|
postQqEventSettings
|
|
11
13
|
} from "./db-api.js";
|
|
12
|
-
import { formatAccountCard } from "./account-format.js";
|
|
13
|
-
import { formatModuleLines, formatPackLines, formatPackMarkdown } from "./content-format.js";
|
|
14
14
|
import { formatCard, formatCommandMenu } from "./menu-format.js";
|
|
15
15
|
function formatUptime(startedAt) {
|
|
16
16
|
const ms = Math.max(0, Date.now() - startedAt);
|
|
@@ -398,7 +398,7 @@ const eventSettingsHandler = async (ctx) => {
|
|
|
398
398
|
}
|
|
399
399
|
};
|
|
400
400
|
const channelHandler = () => ({
|
|
401
|
-
text: "QQ\u7FA4\u6D88\u606F\u8FDB\u5165\u6E38\u620F\u5185\
|
|
401
|
+
text: "QQ\u7FA4\u6D88\u606F\u8FDB\u5165\u6E38\u620F\u5185\u5DF2\u5F00\u542F\u300CQQ\u300D\u6D88\u606F\u6765\u6E90\u7684\u9891\u9053\u3002\u6E38\u620F\u5185\u5404\u9891\u9053\u53EF\u5206\u522B\u8BBE\u7F6E\u662F\u5426\u8F6C\u53D1\u5230 QQ\u3002"
|
|
402
402
|
});
|
|
403
403
|
const doctorHandler = async (ctx) => {
|
|
404
404
|
if (!isAdmin(ctx)) return { text: "\u5F53\u524D\u6CA1\u6709\u7BA1\u7406\u6743\u9650\u3002" };
|
|
@@ -410,7 +410,7 @@ const doctorHandler = async (ctx) => {
|
|
|
410
410
|
text: [
|
|
411
411
|
"\u7BA1\u7406\u81EA\u68C0",
|
|
412
412
|
`\u540E\u7AEF\uFF1A${ctx.inbound.backend}`,
|
|
413
|
-
|
|
413
|
+
"QQ \u5165\u7AD9\uFF1A\u5199\u5165\u6D88\u606F\u6765\u6E90\u4E3A QQ \u7684\u6E38\u620F\u9891\u9053",
|
|
414
414
|
`\u4E3B\u673A\uFF1A${st.host?.hostname || "\u672A\u77E5"} \xB7 ${st.host?.platform || "\u672A\u77E5"}`,
|
|
415
415
|
`CPU\uFF1A${st.host?.cpu?.model || "\u672A\u77E5"} \xB7 ${st.host?.cpu?.cores ?? "\u672A\u77E5"} \u6838`,
|
|
416
416
|
`\u5185\u5B58\uFF1A${st.host?.memory?.usedMb ?? "\u672A\u77E5"}/${st.host?.memory?.totalMb ?? "\u672A\u77E5"} MB`,
|
|
@@ -447,7 +447,7 @@ const packsHandler = async (ctx) => {
|
|
|
447
447
|
...pack.version ? { version: pack.version } : {}
|
|
448
448
|
}));
|
|
449
449
|
return {
|
|
450
|
-
text: ["\
|
|
450
|
+
text: ["\u8D44\u6E90\u5305", "", ...formatPackLines(packs, data.note)].join("\n"),
|
|
451
451
|
markdown: formatPackMarkdown(packs, data.note)
|
|
452
452
|
};
|
|
453
453
|
} catch (error) {
|
|
@@ -473,13 +473,7 @@ function registerBuiltinCommands(registry) {
|
|
|
473
473
|
"home"
|
|
474
474
|
);
|
|
475
475
|
add("account", ["\u6211\u7684\u8D26\u53F7"], "\u67E5\u770B\u4E0E\u7BA1\u7406\u6E38\u620F\u89D2\u8272\u7ED1\u5B9A", whoamiHandler, "home");
|
|
476
|
-
add(
|
|
477
|
-
"entry",
|
|
478
|
-
["\u5165\u670D"],
|
|
479
|
-
"\u76F4\u63A5\u8FDB\u670D\uFF0C\u6E38\u620F\u5185\u7ED1\u5B9A\u540E\u5373\u53EF\u6E38\u73A9",
|
|
480
|
-
entryGuideHandler,
|
|
481
|
-
"home"
|
|
482
|
-
);
|
|
476
|
+
add("entry", ["\u5165\u670D"], "\u76F4\u63A5\u8FDB\u670D\uFF0C\u6E38\u620F\u5185\u7ED1\u5B9A\u540E\u5373\u53EF\u6E38\u73A9", entryGuideHandler, "home");
|
|
483
477
|
add("help", ["\u5E2E\u52A9"], "\u67E5\u770B\u4F7F\u7528\u8BF4\u660E\u548C\u5E38\u7528\u547D\u4EE4", helpHandler(registry), "home");
|
|
484
478
|
add("admin", ["\u7BA1\u7406"], "\u7BA1\u7406\u83DC\u5355", createAdminMenuHandler(registry), "home", true);
|
|
485
479
|
add("status", ["\u67E5\u670D", "\u72B6\u6001"], "\u670D\u52A1\u5668\u8FD0\u884C\u72B6\u6001", statusHandler, "server");
|
|
@@ -487,7 +481,7 @@ function registerBuiltinCommands(registry) {
|
|
|
487
481
|
add("version", ["\u7248\u672C"], "\u57FA\u5CA9\u7248\u5165\u670D\u7248\u672C", serverVersionHandler, "server");
|
|
488
482
|
add("ip", ["\u5730\u5740"], "\u516C\u5F00\u670D\u52A1\u5668\u5730\u5740\u4E0E\u7AEF\u53E3", serverAddressHandler, "server");
|
|
489
483
|
add("modules", ["\u6A21\u5757"], "\u67E5\u770B\u5DF2\u5B89\u88C5\u6A21\u5757", modulesHandler, "server");
|
|
490
|
-
add("packs", ["\u8D44\u6E90\u5305", "\u884C\u4E3A\u5305", "\
|
|
484
|
+
add("packs", ["\u8D44\u6E90\u5305", "\u884C\u4E3A\u5305", "\u8D44\u6E90\u5305"], "\u67E5\u770B\u4E16\u754C\u884C\u4E3A\u5305\u548C\u8D44\u6E90\u5305", packsHandler, "server");
|
|
491
485
|
add("channel", ["\u9891\u9053"], "\u804A\u5929\u4E92\u901A\u72B6\u6001", channelHandler, "server");
|
|
492
486
|
add("ping", [], "\u673A\u5668\u4EBA\u8FDE\u901A\u6027", pingHandler, "server");
|
|
493
487
|
add("whoami", ["\u6211\u7684\u7ED1\u5B9A"], "\u67E5\u770B\u7ED1\u5B9A\u89D2\u8272", whoamiHandler, "account");
|
|
@@ -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 / 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": "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",
|
|
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 { formatAccountCard } from \"./account-format.js\";\nimport { formatModuleLines, formatPackLines, formatPackMarkdown } from \"./content-format.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 { 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\u5DF2\u5F00\u542F\u300CQQ\u300D\u6D88\u606F\u6765\u6E90\u7684\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\uFF1A\u5199\u5165\u6D88\u606F\u6765\u6E90\u4E3A QQ \u7684\u6E38\u620F\u9891\u9053\",\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: [\"\u8D44\u6E90\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(\"entry\", [\"\u5165\u670D\"], \"\u76F4\u63A5\u8FDB\u670D\uFF0C\u6E38\u620F\u5185\u7ED1\u5B9A\u540E\u5373\u53EF\u6E38\u73A9\", entryGuideHandler, \"home\");\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\", \"\u8D44\u6E90\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,SAAS,yBAAyB;AAClC,SAAS,mBAAmB,iBAAiB,0BAA0B;AACvE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,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;AAAA,MACA,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,MAAI,SAAS,CAAC,cAAI,GAAG,8FAAmB,mBAAmB,MAAM;AACjE,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
|
}
|
|
@@ -10,7 +10,7 @@ function pickDisplayLabel(cmd, maxChars = 8) {
|
|
|
10
10
|
channel: "\u804A\u5929\u4E92\u901A",
|
|
11
11
|
ping: "\u8FDE\u63A5\u68C0\u67E5",
|
|
12
12
|
modules: "\u6A21\u5757\u5217\u8868",
|
|
13
|
-
packs: "\
|
|
13
|
+
packs: "\u8D44\u6E90\u5305"
|
|
14
14
|
};
|
|
15
15
|
const label = labels[cmd.name];
|
|
16
16
|
if (label) return label.slice(0, maxChars);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/menu-format.ts"],
|
|
4
|
-
"sourcesContent": ["/** \u83DC\u5355\u4E0E\u4FE1\u606F\u5361\u7EDF\u4E00\u6392\u7248\uFF0C\u907F\u514D\u6B63\u6587\u548C\u64CD\u4F5C\u533A\u91CD\u590D\u5217\u51FA\u6307\u4EE4\u3002 */\nimport type { CommandButton, CommandResult, RegisteredCommand } from \"./types.js\";\n\nexport function pickDisplayLabel(cmd: RegisteredCommand, maxChars = 8): string {\n const labels: Record<string, string> = {\n server: \"\u670D\u52A1\u5668\u4FE1\u606F\",\n account: \"\u6211\u7684\u8D26\u53F7\",\n entry: \"\u8FDB\u670D\u8BF4\u660E\",\n help: \"\u4F7F\u7528\u5E2E\u52A9\",\n admin: \"\u670D\u52A1\u5668\u7BA1\u7406\",\n online: \"\u5728\u7EBF\u73A9\u5BB6\",\n ip: \"\u8FDE\u63A5\u5730\u5740\",\n channel: \"\u804A\u5929\u4E92\u901A\",\n ping: \"\u8FDE\u63A5\u68C0\u67E5\",\n modules: \"\u6A21\u5757\u5217\u8868\",\n packs: \"\
|
|
4
|
+
"sourcesContent": ["/** \u83DC\u5355\u4E0E\u4FE1\u606F\u5361\u7EDF\u4E00\u6392\u7248\uFF0C\u907F\u514D\u6B63\u6587\u548C\u64CD\u4F5C\u533A\u91CD\u590D\u5217\u51FA\u6307\u4EE4\u3002 */\nimport type { CommandButton, CommandResult, RegisteredCommand } from \"./types.js\";\n\nexport function pickDisplayLabel(cmd: RegisteredCommand, maxChars = 8): string {\n const labels: Record<string, string> = {\n server: \"\u670D\u52A1\u5668\u4FE1\u606F\",\n account: \"\u6211\u7684\u8D26\u53F7\",\n entry: \"\u8FDB\u670D\u8BF4\u660E\",\n help: \"\u4F7F\u7528\u5E2E\u52A9\",\n admin: \"\u670D\u52A1\u5668\u7BA1\u7406\",\n online: \"\u5728\u7EBF\u73A9\u5BB6\",\n ip: \"\u8FDE\u63A5\u5730\u5740\",\n channel: \"\u804A\u5929\u4E92\u901A\",\n ping: \"\u8FDE\u63A5\u68C0\u67E5\",\n modules: \"\u6A21\u5757\u5217\u8868\",\n packs: \"\u8D44\u6E90\u5305\",\n };\n const label = labels[cmd.name];\n if (label) return label.slice(0, maxChars);\n const candidates = [cmd.name, ...cmd.aliases].map((name) => name.replace(/^[/\uFF0F]+/, \"\").trim()).filter(Boolean);\n return (candidates.find((name) => /[\\u4e00-\\u9fff]/.test(name)) ?? candidates[0] ?? cmd.name).slice(0, maxChars);\n}\n\nexport function formatCard(title: string, lines: string[]): CommandResult {\n return {\n text: [title, \"\", ...lines].join(\"\\n\"),\n markdown: [`## ${title}`, \"\", ...lines].join(\"\\n\"),\n };\n}\n\nexport function formatCommandMenu(opts: {\n title: string;\n subtitle: string;\n cmds: RegisteredCommand[];\n idPrefix: string;\n footerMd: string;\n footerText: string;\n home?: boolean;\n}): CommandResult {\n const buttons: CommandButton[] = opts.cmds.map((cmd) => ({\n id: `${opts.idPrefix}_${cmd.name}`,\n label: pickDisplayLabel(cmd),\n description: cmd.description,\n command: `/${cmd.name}`,\n }));\n const card = formatCard(opts.title, [opts.subtitle]);\n return {\n ...card,\n menu: opts.home ? \"home\" : \"section\",\n markdown: [card.markdown, \"\", ...(opts.footerMd ? [\"\", opts.footerMd] : [])].join(\"\\n\"),\n text: card.text + (opts.footerText ? `\\n${opts.footerText}` : \"\"),\n buttons,\n };\n}\n"],
|
|
5
5
|
"mappings": "AAGO,SAAS,iBAAiB,KAAwB,WAAW,GAAW;AAC7E,QAAM,SAAiC;AAAA,IACrC,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AACA,QAAM,QAAQ,OAAO,IAAI,IAAI;AAC7B,MAAI,MAAO,QAAO,MAAM,MAAM,GAAG,QAAQ;AACzC,QAAM,aAAa,CAAC,IAAI,MAAM,GAAG,IAAI,OAAO,EAAE,IAAI,CAAC,SAAS,KAAK,QAAQ,UAAU,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAC7G,UAAQ,WAAW,KAAK,CAAC,SAAS,kBAAkB,KAAK,IAAI,CAAC,KAAK,WAAW,CAAC,KAAK,IAAI,MAAM,MAAM,GAAG,QAAQ;AACjH;AAEO,SAAS,WAAW,OAAe,OAAgC;AACxE,SAAO;AAAA,IACL,MAAM,CAAC,OAAO,IAAI,GAAG,KAAK,EAAE,KAAK,IAAI;AAAA,IACrC,UAAU,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,KAAK,IAAI;AAAA,EACnD;AACF;AAEO,SAAS,kBAAkB,MAQhB;AAChB,QAAM,UAA2B,KAAK,KAAK,IAAI,CAAC,SAAS;AAAA,IACvD,IAAI,GAAG,KAAK,QAAQ,IAAI,IAAI,IAAI;AAAA,IAChC,OAAO,iBAAiB,GAAG;AAAA,IAC3B,aAAa,IAAI;AAAA,IACjB,SAAS,IAAI,IAAI,IAAI;AAAA,EACvB,EAAE;AACF,QAAM,OAAO,WAAW,KAAK,OAAO,CAAC,KAAK,QAAQ,CAAC;AACnD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,KAAK,OAAO,SAAS;AAAA,IAC3B,UAAU,CAAC,KAAK,UAAU,IAAI,GAAI,KAAK,WAAW,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAE,EAAE,KAAK,IAAI;AAAA,IACtF,MAAM,KAAK,QAAQ,KAAK,aAAa;AAAA,EAAK,KAAK,UAAU,KAAK;AAAA,IAC9D;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/message-text.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandResult } from \"./types.js\";\n\n/** \u5B98\u65B9 Markdown \u53D1\u9001\u5931\u8D25\u65F6\uFF0C\u83DC\u5355\u4EE5\u7B80\u6D01\u6587\u672C\u5448\u73B0\uFF1B\u6309\u94AE\u547D\u4EE4\u4E0D\u91CD\u590D\u5199\u5165\u6B63\u6587\u3002 */\nexport function officialPlainFallback(result: CommandResult): string {\n if (!result.menu || !result.buttons?.length) return result.text;\n const items = result.buttons\n .filter((button) => button.command !== \"/menu\")\n .map((button) => `${button.label}${button.description ? ` \u00B7 ${button.description}` : \"\"}`);\n const home = result.buttons.some((button) => button.command === \"/menu\")
|
|
5
|
-
"mappings": "AAGO,SAAS,sBAAsB,QAA+B;AACnE,MAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,SAAS,OAAQ,QAAO,OAAO;AAC3D,QAAM,QAAQ,OAAO,QAClB,OAAO,CAAC,WAAW,OAAO,YAAY,OAAO,EAC7C,IAAI,CAAC,WAAW,GAAG,OAAO,KAAK,GAAG,OAAO,cAAc,SAAM,OAAO,WAAW,KAAK,EAAE,EAAE;AAC3F,QAAM,OAAO,OAAO,QAAQ,KAAK,CAAC,WAAW,OAAO,YAAY,OAAO,
|
|
4
|
+
"sourcesContent": ["import type { CommandResult } from \"./types.js\";\n\n/** \u5B98\u65B9 Markdown \u53D1\u9001\u5931\u8D25\u65F6\uFF0C\u83DC\u5355\u4EE5\u7B80\u6D01\u6587\u672C\u5448\u73B0\uFF1B\u6309\u94AE\u547D\u4EE4\u4E0D\u91CD\u590D\u5199\u5165\u6B63\u6587\u3002 */\nexport function officialPlainFallback(result: CommandResult): string {\n if (!result.menu || !result.buttons?.length) return result.text;\n const items = result.buttons\n .filter((button) => button.command !== \"/menu\")\n .map((button) => `${button.label}${button.description ? ` \u00B7 ${button.description}` : \"\"}`);\n const home = result.buttons.some((button) => button.command === \"/menu\") ? [\"\", \"\u53D1\u9001\u300C\u83DC\u5355\u300D\u8FD4\u56DE\u9996\u9875\u3002\"] : [];\n return [result.text, \"\", ...items, ...home].join(\"\\n\");\n}\n\nfunction isTableRow(line: string): boolean {\n return line.trim().startsWith(\"|\");\n}\n\n/** \u8868\u683C\u5206\u9694\u884C\uFF0C\u4F8B\u5982 `| --- | --- |`\u3002\u666E\u901A `---` \u5206\u5272\u7EBF\u4E0D\u7B97\u3002 */\nfunction isTableSeparator(line: string): boolean {\n const trimmed = line.trim();\n if (!trimmed.includes(\"|\")) return false;\n const cells = trimmed.replace(/^\\|/, \"\").replace(/\\|$/, \"\").split(\"|\");\n return cells.length > 0 && cells.every((cell) => /^\\s*:?-{3,}:?\\s*$/.test(cell));\n}\n\nfunction byteLength(lines: string[]): number {\n return Buffer.byteLength(lines.join(\"\\n\"), \"utf8\");\n}\n\n/**\n * \u6309\u884C\u62C6\u5206 Markdown\uFF0C\u5E76\u4FDD\u8BC1\u6BCF\u4E00\u6BB5\u91CC\u7684\u8868\u683C\u4ECD\u7136\u5B8C\u6574\u3002\n * \u4E00\u5F20\u8868\u8D85\u957F\u65F6\uFF0C\u4E0B\u4E00\u6BB5\u91CD\u590D\u8868\u5934\uFF0C\u5E76\u5728\u5C0F\u8282\u6807\u9898\u540E\u6807\u660E\u300C\u7EED\u300D\u3002\n * \u5F53\u524D\u7ED9 QQ \u8D44\u6E90\u5305\u8868\u683C\u4F7F\u7528\uFF1A\u5B98\u65B9\u6D88\u606F\u6309\u6BB5\u53D1\u9001\uFF0C\u534A\u5F20\u8868\u65E0\u6CD5\u6E32\u67D3\u3002\n */\nexport function splitMarkdownMessage(markdown: string, maxBytes = 3000): string[] {\n const lines = markdown.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n const parts: string[] = [];\n let bucket: string[] = [];\n let tableHeader: string[] = [];\n let sectionTitle = \"\";\n\n const flush = (): void => {\n const text = bucket.join(\"\\n\").trim();\n if (text) parts.push(text);\n bucket = [];\n };\n\n const seedContinuation = (): void => {\n const seed: string[] = [];\n if (sectionTitle) seed.push(`${sectionTitle}\uFF08\u7EED\uFF09`, \"\");\n if (tableHeader.length) seed.push(...tableHeader);\n bucket = seed;\n };\n\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? \"\";\n const next = lines[index + 1];\n const headerPair = isTableRow(line) && next !== undefined && isTableSeparator(next) ? [line, next] : null;\n const incoming = headerPair ?? [line];\n if (bucket.length > 0 && byteLength([...bucket, ...incoming]) > maxBytes) {\n flush();\n if (!headerPair && isTableRow(line) && !isTableSeparator(line) && tableHeader.length) seedContinuation();\n }\n if (headerPair) {\n tableHeader = headerPair;\n bucket.push(...headerPair);\n index += 1;\n continue;\n }\n if (/^###\\s+/.test(line)) {\n sectionTitle = line;\n tableHeader = [];\n } else if (/^##\\s+/.test(line)) {\n sectionTitle = \"\";\n tableHeader = [];\n }\n bucket.push(line);\n }\n flush();\n return parts.length ? parts : [\"\"];\n}\n\n/** \u4FDD\u5B88\u7684 UTF-8 \u5B57\u8282\u9884\u7B97\uFF1B\u4F18\u5148\u6309\u884C\u62C6\u5206\uFF0C\u8D85\u957F\u884C\u6309\u7801\u70B9\u62C6\u5206\u3002 */\nexport function splitMessage(text: string, maxBytes = 3000): string[] {\n const parts: string[] = [];\n let current = \"\";\n for (const line of text.split(/(?<=\\n)/u)) {\n if (Buffer.byteLength(current + line, \"utf8\") <= maxBytes) {\n current += line;\n continue;\n }\n if (current) {\n parts.push(current);\n current = \"\";\n }\n for (const char of line) {\n if (Buffer.byteLength(current + char, \"utf8\") > maxBytes) {\n parts.push(current);\n current = \"\";\n }\n current += char;\n }\n }\n if (current) parts.push(current);\n return parts.length ? parts : [\"\"];\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/reply-official.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * commands/reply-official.ts \u2014 \u5B98\u65B9 ReplyPort\uFF08\u7FA4 / C2C\uFF09\n */\n\nimport { sendC2cMessage, sendGroupMessage, type QqOfficialCredentials } from \"@sfmc-bds/sdk/node/qq-official\";\nimport { log } from \"../log.js\";\nimport { officialPlainFallback, splitMarkdownMessage, splitMessage } from \"./message-text.js\";\nimport { renderOfficial } from \"./render.js\";\nimport type { CommandResult, InboundMessage, ReplyPort, ReplyTarget } from \"./types.js\";\n\nfunction isC2c(inbound: InboundMessage): boolean {\n return inbound.scene === \"c2c\" || inbound.groupId.startsWith(\"c2c:\");\n}\n\nfunction c2cUserOpenid(inbound: InboundMessage): string {\n if (inbound.groupId.startsWith(\"c2c:\")) return inbound.groupId.slice(\"c2c:\".length);\n return inbound.userId;\n}\n\nexport function createOfficialReplyPort(creds: QqOfficialCredentials): ReplyPort {\n let msgSeq = 0;\n return {\n async send(target: ReplyTarget, result: CommandResult, inbound: InboundMessage): Promise<void> {\n const markdown = result.markdown?.trim() ?? \"\";\n // \u6709 Markdown \u65F6\u6309\u8868\u683C\u8FB9\u754C\u62C6\u6BB5\uFF0C\u907F\u514D\u8D85\u957F\
|
|
4
|
+
"sourcesContent": ["/**\n * commands/reply-official.ts \u2014 \u5B98\u65B9 ReplyPort\uFF08\u7FA4 / C2C\uFF09\n */\n\nimport { sendC2cMessage, sendGroupMessage, type QqOfficialCredentials } from \"@sfmc-bds/sdk/node/qq-official\";\nimport { log } from \"../log.js\";\nimport { officialPlainFallback, splitMarkdownMessage, splitMessage } from \"./message-text.js\";\nimport { renderOfficial } from \"./render.js\";\nimport type { CommandResult, InboundMessage, ReplyPort, ReplyTarget } from \"./types.js\";\n\nfunction isC2c(inbound: InboundMessage): boolean {\n return inbound.scene === \"c2c\" || inbound.groupId.startsWith(\"c2c:\");\n}\n\nfunction c2cUserOpenid(inbound: InboundMessage): string {\n if (inbound.groupId.startsWith(\"c2c:\")) return inbound.groupId.slice(\"c2c:\".length);\n return inbound.userId;\n}\n\nexport function createOfficialReplyPort(creds: QqOfficialCredentials): ReplyPort {\n let msgSeq = 0;\n return {\n async send(target: ReplyTarget, result: CommandResult, inbound: InboundMessage): Promise<void> {\n const markdown = result.markdown?.trim() ?? \"\";\n // \u6709 Markdown \u65F6\u6309\u8868\u683C\u8FB9\u754C\u62C6\u6BB5\uFF0C\u907F\u514D\u8D85\u957F\u8D44\u6E90\u5305\u5217\u8868\u88AB\u964D\u6210\u7EAF\u6587\u672C\u3002\n const parts = markdown ? splitMarkdownMessage(markdown) : splitMessage(result.text);\n for (let index = 0; index < parts.length; index++) {\n const content = parts[index]!;\n const isLast = index === parts.length - 1;\n const rendered = markdown\n ? renderOfficial({\n text: result.text,\n markdown: content,\n ...(isLast && result.buttons ? { buttons: result.buttons } : {}),\n })\n : parts.length === 1\n ? renderOfficial({ ...result, text: content })\n : renderOfficial({\n text: content,\n ...(isLast && result.buttons ? { buttons: result.buttons } : {}),\n });\n msgSeq += 1;\n const c2c = isC2c(inbound);\n const common = {\n msgType: rendered.msgType as 0 | 2,\n ...(rendered.msgType === 2\n ? { markdown: rendered.markdown ?? result.text }\n : { content: rendered.content ?? result.text }),\n ...(rendered.keyboardButtons\n ? {\n keyboardRows: Array.from({ length: Math.ceil(rendered.keyboardButtons.length / 2) }, (_, index) =>\n rendered.keyboardButtons!.slice(index * 2, index * 2 + 2)\n ),\n }\n : {}),\n ...(target.msgId ? { msgId: target.msgId, msgSeq } : {}),\n };\n\n const sendOnce = async (plainFallback: boolean) => {\n if (c2c) {\n const userOpenid = c2cUserOpenid(inbound);\n if (plainFallback) {\n return sendC2cMessage(creds, {\n userOpenid,\n msgType: 0,\n content: parts.length === 1 ? officialPlainFallback(result) : content,\n ...(target.msgId ? { msgId: target.msgId, msgSeq: ++msgSeq } : {}),\n });\n }\n return sendC2cMessage(creds, { userOpenid, ...common });\n }\n if (plainFallback) {\n return sendGroupMessage(creds, {\n groupOpenid: target.groupId,\n msgType: 0,\n content: parts.length === 1 ? officialPlainFallback(result) : content,\n ...(target.msgId ? { msgId: target.msgId, msgSeq: ++msgSeq } : {}),\n });\n }\n return sendGroupMessage(creds, { groupOpenid: target.groupId, ...common });\n };\n\n const res = await sendOnce(false);\n if (!res.ok) {\n if (rendered.msgType === 2) {\n log.warn(`\u5B98\u65B9 Markdown \u53D1\u9001\u5931\u8D25\uFF0C\u964D\u7EA7\u6587\u672C: ${res.error}`);\n const plain = await sendOnce(true);\n if (!plain.ok) throw new Error(plain.error);\n continue;\n }\n throw new Error(res.error);\n }\n }\n },\n };\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["index"]
|
|
7
7
|
}
|
package/dist/console.js
CHANGED
|
@@ -41,7 +41,7 @@ function handleCommand(line, opts, rl) {
|
|
|
41
41
|
case "reload": {
|
|
42
42
|
reloadInto(opts.config);
|
|
43
43
|
log.info(
|
|
44
|
-
`\u914D\u7F6E\u5DF2\u91CD\u8F7D (backend=${opts.config.qq_backend},
|
|
44
|
+
`\u914D\u7F6E\u5DF2\u91CD\u8F7D (backend=${opts.config.qq_backend}, db=${opts.config.db_host}:${opts.config.db_port})`
|
|
45
45
|
);
|
|
46
46
|
log.warn("reload \u53EA\u66F4\u65B0\u5185\u5B58\u914D\u7F6E\u5F15\u7528\uFF1B\u5207\u6362 backend / AppID \u9700\u91CD\u542F\u8FDB\u7A0B");
|
|
47
47
|
return false;
|
package/dist/console.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/console.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * console.ts \u2014 \u4EA4\u4E92\u5F0F\u63A7\u5236\u53F0 (readline)\n *\n * \u547D\u4EE4:\n * help \u663E\u793A\u5E2E\u52A9\n * reload \u91CD\u65B0\u8BFB\u53D6 configs/qq_config.json\n * status \u663E\u793A\u5F53\u524D\u72B6\u6001\n * sync-menu \u91CD\u63A8\u5B98\u65B9\u83DC\u5355/\u6307\u4EE4\u9762\u677F\uFF08\u4EC5 official\uFF09\n * stop \u9000\u51FA\u8FDB\u7A0B\n */\n\nimport { createInterface, type Interface as RLInterface } from \"node:readline\";\nimport { log } from \"./log.js\";\nimport { reloadInto } from \"./config.js\";\nimport type { QQBridgeConfig } from \"./types.js\";\n\nexport interface ConsoleOptions {\n config: QQBridgeConfig;\n initialEnabled: boolean;\n wsPort: number;\n botSelfIdRef: { value: string | null };\n backend: \"official\" | \"llbot\";\n onSyncMenu?: () => Promise<void>;\n}\n\nfunction showHelp(backend: \"official\" | \"llbot\"): void {\n console.log(\"\u53EF\u7528\u547D\u4EE4:\");\n console.log(\" help \u2014 \u663E\u793A\u672C\u5E2E\u52A9\");\n console.log(\" reload \u2014 \u91CD\u65B0\u8BFB\u53D6 qq_config.json\");\n console.log(\" status \u2014 \u663E\u793A\u5F53\u524D\u72B6\u6001\");\n if (backend === \"official\") {\n console.log(\" sync-menu \u2014 \u91CD\u63A8\u5B98\u65B9\u81EA\u5B9A\u4E49\u83DC\u5355 / \u7FA4\u6307\u4EE4\u9762\u677F\");\n }\n console.log(\" stop \u2014 \u505C\u6B62\u670D\u52A1\");\n}\n\nfunction showStatus(opts: ConsoleOptions): void {\n const { config: cfg, initialEnabled, wsPort, botSelfIdRef, backend } = opts;\n console.log(\"=== QQBridge \u72B6\u6001 ===\");\n console.log(` \u542F\u7528: ${initialEnabled}`);\n console.log(` \u540E\u7AEF: ${backend}`);\n if (backend === \"official\") {\n console.log(` \u63A5\u6536\u65B9\u5F0F: ${cfg.qq_official_transport}`);\n console.log(` \u6C99\u7BB1: ${cfg.qq_sandbox}`);\n console.log(` AppID: ${cfg.qq_app_id || \"\u672A\u914D\u7F6E\"}`);\n console.log(` \u7FA4 openid: ${cfg.qq_group_openid || \"\u672A\u914D\u7F6E\"}`);\n console.log(` \u9762\u677F id: ${cfg.qq_group_panel_id || \"\u672A\u914D\u7F6E\"}`);\n console.log(` sync \u83DC\u5355: ${cfg.qq_sync_menu_panel !== false}`);\n } else {\n console.log(` WS \u7AEF\u53E3: ${wsPort}`);\n console.log(` QQ \u7FA4\u53F7: ${cfg.qq_group_id || \"\u672A\u914D\u7F6E\"}`);\n console.log(` Bot self_id: ${botSelfIdRef.value || \"\u672A\u6355\u83B7\"}`);\n }\n console.log(\" Channel: qq\");\n console.log(` db-server: ${cfg.db_host}:${cfg.db_port}`);\n console.log(` MC\u2192QQ \u51FA\u7AD9: (\u7531 db-server \u6309 qq_backend \u76F4\u8FDE)`);\n}\n\nfunction handleCommand(line: string, opts: ConsoleOptions, rl: RLInterface): boolean {\n const cmd = line.trim().toLowerCase();\n switch (cmd) {\n case \"help\":\n showHelp(opts.backend);\n return false;\n case \"reload\": {\n reloadInto(opts.config);\n log.info(\n `\u914D\u7F6E\u5DF2\u91CD\u8F7D (backend=${opts.config.qq_backend},
|
|
5
|
-
"mappings": "AAWA,SAAS,uBAAsD;AAC/D,SAAS,WAAW;AACpB,SAAS,kBAAkB;AAY3B,SAAS,SAAS,SAAqC;AACrD,UAAQ,IAAI,2BAAO;AACnB,UAAQ,IAAI,oDAAsB;AAClC,UAAQ,IAAI,6DAAoC;AAChD,UAAQ,IAAI,0DAAuB;AACnC,MAAI,YAAY,YAAY;AAC1B,YAAQ,IAAI,6GAAkC;AAAA,EAChD;AACA,UAAQ,IAAI,8CAAqB;AACnC;AAEA,SAAS,WAAW,MAA4B;AAC9C,QAAM,EAAE,QAAQ,KAAK,gBAAgB,QAAQ,cAAc,QAAQ,IAAI;AACvE,UAAQ,IAAI,+BAAqB;AACjC,UAAQ,IAAI,0BAAgB,cAAc,EAAE;AAC5C,UAAQ,IAAI,0BAAgB,OAAO,EAAE;AACrC,MAAI,YAAY,YAAY;AAC1B,YAAQ,IAAI,kCAAc,IAAI,qBAAqB,EAAE;AACrD,YAAQ,IAAI,0BAAgB,IAAI,UAAU,EAAE;AAC5C,YAAQ,IAAI,kBAAkB,IAAI,aAAa,oBAAK,EAAE;AACtD,YAAQ,IAAI,sBAAiB,IAAI,mBAAmB,oBAAK,EAAE;AAC3D,YAAQ,IAAI,0BAAgB,IAAI,qBAAqB,oBAAK,EAAE;AAC5D,YAAQ,IAAI,0BAAgB,IAAI,uBAAuB,KAAK,EAAE;AAAA,EAChE,OAAO;AACL,YAAQ,IAAI,0BAAgB,MAAM,EAAE;AACpC,YAAQ,IAAI,0BAAgB,IAAI,eAAe,oBAAK,EAAE;AACtD,YAAQ,IAAI,kBAAkB,aAAa,SAAS,oBAAK,EAAE;AAAA,EAC7D;AACA,UAAQ,IAAI,mBAAmB;AAC/B,UAAQ,IAAI,kBAAkB,IAAI,OAAO,IAAI,IAAI,OAAO,EAAE;AAC1D,UAAQ,IAAI,+EAA4C;AAC1D;AAEA,SAAS,cAAc,MAAc,MAAsB,IAA0B;AACnF,QAAM,MAAM,KAAK,KAAK,EAAE,YAAY;AACpC,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,eAAS,KAAK,OAAO;AACrB,aAAO;AAAA,IACT,KAAK,UAAU;AACb,iBAAW,KAAK,MAAM;AACtB,UAAI;AAAA,QACF,2CAAkB,KAAK,OAAO,UAAU,
|
|
4
|
+
"sourcesContent": ["/**\n * console.ts \u2014 \u4EA4\u4E92\u5F0F\u63A7\u5236\u53F0 (readline)\n *\n * \u547D\u4EE4:\n * help \u663E\u793A\u5E2E\u52A9\n * reload \u91CD\u65B0\u8BFB\u53D6 configs/qq_config.json\n * status \u663E\u793A\u5F53\u524D\u72B6\u6001\n * sync-menu \u91CD\u63A8\u5B98\u65B9\u83DC\u5355/\u6307\u4EE4\u9762\u677F\uFF08\u4EC5 official\uFF09\n * stop \u9000\u51FA\u8FDB\u7A0B\n */\n\nimport { createInterface, type Interface as RLInterface } from \"node:readline\";\nimport { log } from \"./log.js\";\nimport { reloadInto } from \"./config.js\";\nimport type { QQBridgeConfig } from \"./types.js\";\n\nexport interface ConsoleOptions {\n config: QQBridgeConfig;\n initialEnabled: boolean;\n wsPort: number;\n botSelfIdRef: { value: string | null };\n backend: \"official\" | \"llbot\";\n onSyncMenu?: () => Promise<void>;\n}\n\nfunction showHelp(backend: \"official\" | \"llbot\"): void {\n console.log(\"\u53EF\u7528\u547D\u4EE4:\");\n console.log(\" help \u2014 \u663E\u793A\u672C\u5E2E\u52A9\");\n console.log(\" reload \u2014 \u91CD\u65B0\u8BFB\u53D6 qq_config.json\");\n console.log(\" status \u2014 \u663E\u793A\u5F53\u524D\u72B6\u6001\");\n if (backend === \"official\") {\n console.log(\" sync-menu \u2014 \u91CD\u63A8\u5B98\u65B9\u81EA\u5B9A\u4E49\u83DC\u5355 / \u7FA4\u6307\u4EE4\u9762\u677F\");\n }\n console.log(\" stop \u2014 \u505C\u6B62\u670D\u52A1\");\n}\n\nfunction showStatus(opts: ConsoleOptions): void {\n const { config: cfg, initialEnabled, wsPort, botSelfIdRef, backend } = opts;\n console.log(\"=== QQBridge \u72B6\u6001 ===\");\n console.log(` \u542F\u7528: ${initialEnabled}`);\n console.log(` \u540E\u7AEF: ${backend}`);\n if (backend === \"official\") {\n console.log(` \u63A5\u6536\u65B9\u5F0F: ${cfg.qq_official_transport}`);\n console.log(` \u6C99\u7BB1: ${cfg.qq_sandbox}`);\n console.log(` AppID: ${cfg.qq_app_id || \"\u672A\u914D\u7F6E\"}`);\n console.log(` \u7FA4 openid: ${cfg.qq_group_openid || \"\u672A\u914D\u7F6E\"}`);\n console.log(` \u9762\u677F id: ${cfg.qq_group_panel_id || \"\u672A\u914D\u7F6E\"}`);\n console.log(` sync \u83DC\u5355: ${cfg.qq_sync_menu_panel !== false}`);\n } else {\n console.log(` WS \u7AEF\u53E3: ${wsPort}`);\n console.log(` QQ \u7FA4\u53F7: ${cfg.qq_group_id || \"\u672A\u914D\u7F6E\"}`);\n console.log(` Bot self_id: ${botSelfIdRef.value || \"\u672A\u6355\u83B7\"}`);\n }\n console.log(\" Channel: qq\");\n console.log(` db-server: ${cfg.db_host}:${cfg.db_port}`);\n console.log(` MC\u2192QQ \u51FA\u7AD9: (\u7531 db-server \u6309 qq_backend \u76F4\u8FDE)`);\n}\n\nfunction handleCommand(line: string, opts: ConsoleOptions, rl: RLInterface): boolean {\n const cmd = line.trim().toLowerCase();\n switch (cmd) {\n case \"help\":\n showHelp(opts.backend);\n return false;\n case \"reload\": {\n reloadInto(opts.config);\n log.info(\n `\u914D\u7F6E\u5DF2\u91CD\u8F7D (backend=${opts.config.qq_backend}, db=${opts.config.db_host}:${opts.config.db_port})`\n );\n log.warn(\"reload \u53EA\u66F4\u65B0\u5185\u5B58\u914D\u7F6E\u5F15\u7528\uFF1B\u5207\u6362 backend / AppID \u9700\u91CD\u542F\u8FDB\u7A0B\");\n return false;\n }\n case \"status\":\n showStatus(opts);\n return false;\n case \"sync-menu\": {\n if (opts.backend !== \"official\") {\n log.info(\"sync-menu \u4EC5 official \u540E\u7AEF\u53EF\u7528\");\n return false;\n }\n if (!opts.onSyncMenu) {\n log.warn(\"sync-menu \u672A\u63A5\u7EBF\");\n return false;\n }\n void opts.onSyncMenu().then(\n () => log.info(\"sync-menu \u5B8C\u6210\"),\n (e) => log.warn(`sync-menu \u5931\u8D25: ${(e as Error).message}`)\n );\n return false;\n }\n case \"stop\":\n case \"exit\":\n case \"quit\":\n log.info(\"\u6B63\u5728\u505C\u6B62...\");\n rl.close();\n process.exit(0);\n return true;\n case \"\":\n return false;\n default:\n log.info(`\u672A\u77E5\u547D\u4EE4: ${cmd} (\u8F93\u5165 help \u67E5\u770B\u5E2E\u52A9)`);\n return false;\n }\n}\n\nexport function startConsole(opts: ConsoleOptions): void {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.on(\"line\", (line) => {\n handleCommand(line, opts, rl);\n });\n}\n"],
|
|
5
|
+
"mappings": "AAWA,SAAS,uBAAsD;AAC/D,SAAS,WAAW;AACpB,SAAS,kBAAkB;AAY3B,SAAS,SAAS,SAAqC;AACrD,UAAQ,IAAI,2BAAO;AACnB,UAAQ,IAAI,oDAAsB;AAClC,UAAQ,IAAI,6DAAoC;AAChD,UAAQ,IAAI,0DAAuB;AACnC,MAAI,YAAY,YAAY;AAC1B,YAAQ,IAAI,6GAAkC;AAAA,EAChD;AACA,UAAQ,IAAI,8CAAqB;AACnC;AAEA,SAAS,WAAW,MAA4B;AAC9C,QAAM,EAAE,QAAQ,KAAK,gBAAgB,QAAQ,cAAc,QAAQ,IAAI;AACvE,UAAQ,IAAI,+BAAqB;AACjC,UAAQ,IAAI,0BAAgB,cAAc,EAAE;AAC5C,UAAQ,IAAI,0BAAgB,OAAO,EAAE;AACrC,MAAI,YAAY,YAAY;AAC1B,YAAQ,IAAI,kCAAc,IAAI,qBAAqB,EAAE;AACrD,YAAQ,IAAI,0BAAgB,IAAI,UAAU,EAAE;AAC5C,YAAQ,IAAI,kBAAkB,IAAI,aAAa,oBAAK,EAAE;AACtD,YAAQ,IAAI,sBAAiB,IAAI,mBAAmB,oBAAK,EAAE;AAC3D,YAAQ,IAAI,0BAAgB,IAAI,qBAAqB,oBAAK,EAAE;AAC5D,YAAQ,IAAI,0BAAgB,IAAI,uBAAuB,KAAK,EAAE;AAAA,EAChE,OAAO;AACL,YAAQ,IAAI,0BAAgB,MAAM,EAAE;AACpC,YAAQ,IAAI,0BAAgB,IAAI,eAAe,oBAAK,EAAE;AACtD,YAAQ,IAAI,kBAAkB,aAAa,SAAS,oBAAK,EAAE;AAAA,EAC7D;AACA,UAAQ,IAAI,mBAAmB;AAC/B,UAAQ,IAAI,kBAAkB,IAAI,OAAO,IAAI,IAAI,OAAO,EAAE;AAC1D,UAAQ,IAAI,+EAA4C;AAC1D;AAEA,SAAS,cAAc,MAAc,MAAsB,IAA0B;AACnF,QAAM,MAAM,KAAK,KAAK,EAAE,YAAY;AACpC,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,eAAS,KAAK,OAAO;AACrB,aAAO;AAAA,IACT,KAAK,UAAU;AACb,iBAAW,KAAK,MAAM;AACtB,UAAI;AAAA,QACF,2CAAkB,KAAK,OAAO,UAAU,QAAQ,KAAK,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO;AAAA,MAC5F;AACA,UAAI,KAAK,gIAA2C;AACpD,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,iBAAW,IAAI;AACf,aAAO;AAAA,IACT,KAAK,aAAa;AAChB,UAAI,KAAK,YAAY,YAAY;AAC/B,YAAI,KAAK,oDAA2B;AACpC,eAAO;AAAA,MACT;AACA,UAAI,CAAC,KAAK,YAAY;AACpB,YAAI,KAAK,8BAAe;AACxB,eAAO;AAAA,MACT;AACA,WAAK,KAAK,WAAW,EAAE;AAAA,QACrB,MAAM,IAAI,KAAK,wBAAc;AAAA,QAC7B,CAAC,MAAM,IAAI,KAAK,2BAAkB,EAAY,OAAO,EAAE;AAAA,MACzD;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,UAAI,KAAK,6BAAS;AAClB,SAAG,MAAM;AACT,cAAQ,KAAK,CAAC;AACd,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,UAAI,KAAK,6BAAS,GAAG,+CAAiB;AACtC,aAAO;AAAA,EACX;AACF;AAEO,SAAS,aAAa,MAA4B;AACvD,QAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,KAAG,GAAG,QAAQ,CAAC,SAAS;AACtB,kBAAc,MAAM,MAAM,EAAE;AAAA,EAC9B,CAAC;AACH;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/dbserver.js
CHANGED
|
@@ -45,7 +45,6 @@ function postJSON(url, body, timeoutMs) {
|
|
|
45
45
|
async function forwardGroupMessage(cfg, fromId, fromName, content, now = Date.now()) {
|
|
46
46
|
const message = {
|
|
47
47
|
id: `${fromId}_${now}`,
|
|
48
|
-
channelId: cfg.channelId,
|
|
49
48
|
fromid: fromId,
|
|
50
49
|
fromName,
|
|
51
50
|
type: "text",
|
|
@@ -55,11 +54,15 @@ async function forwardGroupMessage(cfg, fromId, fromName, content, now = Date.no
|
|
|
55
54
|
};
|
|
56
55
|
const body = { messages: [message] };
|
|
57
56
|
const url = new URL(`http://${cfg.host}:${cfg.port}/api/sfmc/messages`);
|
|
58
|
-
|
|
57
|
+
return postJSON(url, body, REQUEST_TIMEOUT_MS);
|
|
59
58
|
}
|
|
60
59
|
async function tryForward(cfg, fromId, fromName, content) {
|
|
61
60
|
try {
|
|
62
|
-
await forwardGroupMessage(cfg, fromId, fromName, content);
|
|
61
|
+
const result = await forwardGroupMessage(cfg, fromId, fromName, content);
|
|
62
|
+
if (result && typeof result === "object" && result.qqChannels === 0) {
|
|
63
|
+
log.warn("\u6CA1\u6709\u6D88\u606F\u6765\u6E90\u4E3A QQ \u7684\u6E38\u620F\u9891\u9053\uFF0C\u672C\u6761\u672A\u6295\u9012");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
63
66
|
log.info(`QQ \u2192 MC: ${fromName}: ${content.slice(0, 60)}`);
|
|
64
67
|
} catch (e) {
|
|
65
68
|
log.error(`\u8F6C\u53D1\u5230 db-server \u5931\u8D25: ${e.message}`);
|
package/dist/dbserver.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/dbserver.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * dbserver.ts \u2014 \u8F6C\u53D1 QQ \u6D88\u606F\u81F3 db-server \u6D88\u606F\u805A\u5408\u7AEF\u70B9\uFF08/api/sfmc/messages\uFF09\n *\n * \u6838\u5FC3\u673A\u5236\uFF1A\n * - \u6D88\u606F\u6807\u51C6\u5316\uFF1A\u5C06\u5916\u90E8\u7FA4\u6D88\u606F\u6784\u9020\u4E3A\u6807\u51C6 `IncomingChatMessage` \u5BF9\u8C61\uFF08\u53D1\u9001\u8005\u6807\u8BC6\u7EDF\u4E00\u52A0\u4E0A `qq_` \u524D\u7F00\uFF09\n * - \u5FEB\u901F\u54CD\u5E94\u4E0E\u5BB9\u9519\uFF1A\u8BF7\u6C42\u8D85\u65F6\uFF085 \u79D2\uFF09\u540E\u81EA\u52A8\u7194\u65AD\uFF1B\u8F6C\u53D1\u5931\u8D25\u4EC5\u8BB0\u5F55\u544A\u8B66\u65E5\u5FD7\uFF0C\u4E0D\u963B\u585E\u4E3B\u4E8B\u4EF6\u5FAA\u73AF\n */\n\nimport { request as httpRequest, type RequestOptions } from \"node:http\";\nimport { log } from \"./log.js\";\nimport type { IncomingChatMessage, PostMessagesBody } from \"./types.js\";\n\nexport interface DBServerConfig {\n host: string;\n port: number;\n channelId
|
|
5
|
-
"mappings": "AAQA,SAAS,WAAW,mBAAwC;AAC5D,SAAS,WAAW;
|
|
4
|
+
"sourcesContent": ["/**\n * dbserver.ts \u2014 \u8F6C\u53D1 QQ \u6D88\u606F\u81F3 db-server \u6D88\u606F\u805A\u5408\u7AEF\u70B9\uFF08/api/sfmc/messages\uFF09\n *\n * \u6838\u5FC3\u673A\u5236\uFF1A\n * - \u6D88\u606F\u6807\u51C6\u5316\uFF1A\u5C06\u5916\u90E8\u7FA4\u6D88\u606F\u6784\u9020\u4E3A\u6807\u51C6 `IncomingChatMessage` \u5BF9\u8C61\uFF08\u53D1\u9001\u8005\u6807\u8BC6\u7EDF\u4E00\u52A0\u4E0A `qq_` \u524D\u7F00\uFF09\n * - \u5FEB\u901F\u54CD\u5E94\u4E0E\u5BB9\u9519\uFF1A\u8BF7\u6C42\u8D85\u65F6\uFF085 \u79D2\uFF09\u540E\u81EA\u52A8\u7194\u65AD\uFF1B\u8F6C\u53D1\u5931\u8D25\u4EC5\u8BB0\u5F55\u544A\u8B66\u65E5\u5FD7\uFF0C\u4E0D\u963B\u585E\u4E3B\u4E8B\u4EF6\u5FAA\u73AF\n */\n\nimport { request as httpRequest, type RequestOptions } from \"node:http\";\nimport { log } from \"./log.js\";\nimport type { IncomingChatMessage, PostMessagesBody } from \"./types.js\";\n\nexport interface DBServerConfig {\n host: string;\n port: number;\n /**\n * \u5DF2\u4E0D\u518D\u4F5C\u4E3A\u5165\u7AD9\u76EE\u6807\u3002QQ \u6D88\u606F\u7531 db-server \u5199\u5165\u6D88\u606F\u6765\u6E90\u4E3A QQ \u7684\u9891\u9053\u3002\n * \u4FDD\u7559\u5B57\u6BB5\u53EA\u4E3A\u517C\u5BB9\u65E7\u8C03\u7528\u65B9\uFF0C\u8F6C\u53D1\u65F6\u4E0D\u4F1A\u5E26\u4E0A\u3002\n */\n channelId?: string;\n}\n\nconst REQUEST_TIMEOUT_MS = 5_000;\n\nfunction postJSON<T>(url: URL, body: unknown, timeoutMs: number): Promise<T> {\n const payload = JSON.stringify(body);\n const options: RequestOptions = {\n hostname: url.hostname,\n port: url.port || \"3001\",\n path: url.pathname,\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": Buffer.byteLength(payload),\n },\n timeout: timeoutMs,\n };\n return new Promise<T>((resolve, reject) => {\n const req = httpRequest(options, (res) => {\n let buf = \"\";\n res.setEncoding(\"utf-8\");\n res.on(\"data\", (chunk: string) => {\n buf += chunk;\n });\n res.on(\"end\", () => {\n const code = res.statusCode ?? 0;\n if (code >= 200 && code < 300) {\n try {\n resolve(JSON.parse(buf) as T);\n } catch {\n // \u5141\u8BB8\u8FD4\u56DE\u975E JSON\uFF1A\u4ECD\u89C6\u4E3A\u6210\u529F\n resolve(buf as unknown as T);\n }\n } else {\n reject(new Error(`db-server ${code}: ${buf.slice(0, 200)}`));\n }\n });\n });\n req.on(\"timeout\", () => {\n req.destroy(new Error(`db-server \u8D85\u65F6 ${timeoutMs}ms`));\n });\n req.on(\"error\", reject);\n req.write(payload);\n req.end();\n });\n}\n\n/**\n * \u6784\u9020\u6807\u51C6\u804A\u5929\u6D88\u606F\u7ED3\u6784\u4F53\u5E76 POST \u53D1\u9001\u81F3 db-server \u6D88\u606F\u7AEF\u70B9\u3002\n *\n * @param cfg db-server \u76EE\u6807\u8FDE\u63A5\u4E0E\u9891\u9053\u914D\u7F6E\u3002\n * @param fromId \u53D1\u9001\u65B9\u552F\u4E00\u6807\u8BC6\u7B26\uFF08\u901A\u5E38\u5F62\u5982 `qq_<user_id>`\uFF09\u3002\n * @param fromName \u53D1\u9001\u65B9\u5C55\u793A\u6635\u79F0\u3002\n * @param content \u6D88\u606F\u7EAF\u6587\u672C\u5185\u5BB9\u3002\n * @param now \u6D88\u606F\u65F6\u95F4\u6233\uFF08\u6BEB\u79D2\uFF0C\u9ED8\u8BA4\u53D6\u5F53\u524D\u65F6\u95F4\uFF09\u3002\n */\nexport async function forwardGroupMessage(\n cfg: DBServerConfig,\n fromId: string,\n fromName: string,\n content: string,\n now: number = Date.now()\n): Promise<{ qqChannels?: number }> {\n const message: IncomingChatMessage = {\n id: `${fromId}_${now}`,\n fromid: fromId,\n fromName,\n type: \"text\",\n content,\n showTimestamp: true,\n timestamp: now,\n };\n const body: PostMessagesBody = { messages: [message] };\n const url = new URL(`http://${cfg.host}:${cfg.port}/api/sfmc/messages`);\n return postJSON<{ qqChannels?: number }>(url, body, REQUEST_TIMEOUT_MS);\n}\n\n/**\n * \u5B89\u5168\u8F6C\u53D1\u6D88\u606F\u81F3 db-server\uFF08\u5185\u90E8\u6355\u83B7\u5F02\u5E38\u5E76\u8BB0\u5F55\u65E5\u5FD7\uFF0C\u907F\u514D\u629B\u51FA\u7ED9\u4E3B\u4E8B\u4EF6\u5FAA\u73AF\uFF09\u3002\n *\n * @param cfg db-server \u8FDE\u63A5\u914D\u7F6E\u3002\n * @param fromId \u53D1\u9001\u65B9\u552F\u4E00\u6807\u8BC6\u7B26\u3002\n * @param fromName \u53D1\u9001\u65B9\u6635\u79F0\u3002\n * @param content \u6D88\u606F\u6587\u672C\u5185\u5BB9\u3002\n */\nexport async function tryForward(\n cfg: DBServerConfig,\n fromId: string,\n fromName: string,\n content: string\n): Promise<void> {\n try {\n const result = await forwardGroupMessage(cfg, fromId, fromName, content);\n if (result && typeof result === \"object\" && result.qqChannels === 0) {\n log.warn(\"\u6CA1\u6709\u6D88\u606F\u6765\u6E90\u4E3A QQ \u7684\u6E38\u620F\u9891\u9053\uFF0C\u672C\u6761\u672A\u6295\u9012\");\n return;\n }\n log.info(`QQ \u2192 MC: ${fromName}: ${content.slice(0, 60)}`);\n } catch (e) {\n log.error(`\u8F6C\u53D1\u5230 db-server \u5931\u8D25: ${(e as Error).message}`);\n }\n}\n\n"],
|
|
5
|
+
"mappings": "AAQA,SAAS,WAAW,mBAAwC;AAC5D,SAAS,WAAW;AAapB,MAAM,qBAAqB;AAE3B,SAAS,SAAY,KAAU,MAAe,WAA+B;AAC3E,QAAM,UAAU,KAAK,UAAU,IAAI;AACnC,QAAM,UAA0B;AAAA,IAC9B,UAAU,IAAI;AAAA,IACd,MAAM,IAAI,QAAQ;AAAA,IAClB,MAAM,IAAI;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,kBAAkB,OAAO,WAAW,OAAO;AAAA,IAC7C;AAAA,IACA,SAAS;AAAA,EACX;AACA,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,UAAM,MAAM,YAAY,SAAS,CAAC,QAAQ;AACxC,UAAI,MAAM;AACV,UAAI,YAAY,OAAO;AACvB,UAAI,GAAG,QAAQ,CAAC,UAAkB;AAChC,eAAO;AAAA,MACT,CAAC;AACD,UAAI,GAAG,OAAO,MAAM;AAClB,cAAM,OAAO,IAAI,cAAc;AAC/B,YAAI,QAAQ,OAAO,OAAO,KAAK;AAC7B,cAAI;AACF,oBAAQ,KAAK,MAAM,GAAG,CAAM;AAAA,UAC9B,QAAQ;AAEN,oBAAQ,GAAmB;AAAA,UAC7B;AAAA,QACF,OAAO;AACL,iBAAO,IAAI,MAAM,aAAa,IAAI,KAAK,IAAI,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;AAAA,QAC7D;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AACD,QAAI,GAAG,WAAW,MAAM;AACtB,UAAI,QAAQ,IAAI,MAAM,0BAAgB,SAAS,IAAI,CAAC;AAAA,IACtD,CAAC;AACD,QAAI,GAAG,SAAS,MAAM;AACtB,QAAI,MAAM,OAAO;AACjB,QAAI,IAAI;AAAA,EACV,CAAC;AACH;AAWA,eAAsB,oBACpB,KACA,QACA,UACA,SACA,MAAc,KAAK,IAAI,GACW;AAClC,QAAM,UAA+B;AAAA,IACnC,IAAI,GAAG,MAAM,IAAI,GAAG;AAAA,IACpB,QAAQ;AAAA,IACR;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AACA,QAAM,OAAyB,EAAE,UAAU,CAAC,OAAO,EAAE;AACrD,QAAM,MAAM,IAAI,IAAI,UAAU,IAAI,IAAI,IAAI,IAAI,IAAI,oBAAoB;AACtE,SAAO,SAAkC,KAAK,MAAM,kBAAkB;AACxE;AAUA,eAAsB,WACpB,KACA,QACA,UACA,SACe;AACf,MAAI;AACF,UAAM,SAAS,MAAM,oBAAoB,KAAK,QAAQ,UAAU,OAAO;AACvE,QAAI,UAAU,OAAO,WAAW,YAAY,OAAO,eAAe,GAAG;AACnE,UAAI,KAAK,kHAAwB;AACjC;AAAA,IACF;AACA,QAAI,KAAK,iBAAY,QAAQ,KAAK,QAAQ,MAAM,GAAG,EAAE,CAAC,EAAE;AAAA,EAC1D,SAAS,GAAG;AACV,QAAI,MAAM,8CAAsB,EAAY,OAAO,EAAE;AAAA,EACvD;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.js
CHANGED
|
@@ -21,8 +21,7 @@ async function main() {
|
|
|
21
21
|
const botSelfIdRef = { value: null };
|
|
22
22
|
const db = {
|
|
23
23
|
host: cfg.db_host,
|
|
24
|
-
port: cfg.db_port
|
|
25
|
-
channelId: "qq"
|
|
24
|
+
port: cfg.db_port
|
|
26
25
|
};
|
|
27
26
|
if (cfg.qq_backend === "official") {
|
|
28
27
|
if (!cfg.qq_app_id || !cfg.qq_app_secret) {
|
|
@@ -45,7 +44,6 @@ async function main() {
|
|
|
45
44
|
dbPort: cfg.db_port,
|
|
46
45
|
groupOpenid: cfg.qq_group_openid,
|
|
47
46
|
adminOpenids: Array.isArray(cfg.qq_admin_openids) ? cfg.qq_admin_openids : [],
|
|
48
|
-
bridgeChannelId: "qq",
|
|
49
47
|
officialCreds: creds
|
|
50
48
|
},
|
|
51
49
|
startedAt
|
|
@@ -95,7 +93,7 @@ async function main() {
|
|
|
95
93
|
void runSyncMenu().catch((e) => log.warn(`menu/panel sync \u5F02\u5E38: ${e.message}`));
|
|
96
94
|
installQqRuntimeStatusHooks("official");
|
|
97
95
|
log.info(
|
|
98
|
-
`\u5B98\u65B9\u540E\u7AEF\u5DF2\u542F\u52A8 (transport=${cfg.qq_official_transport}, sandbox=${cfg.qq_sandbox}, group_openid=${cfg.qq_group_openid || "\u672A\u914D\u7F6E"},
|
|
96
|
+
`\u5B98\u65B9\u540E\u7AEF\u5DF2\u542F\u52A8 (transport=${cfg.qq_official_transport}, sandbox=${cfg.qq_sandbox}, group_openid=${cfg.qq_group_openid || "\u672A\u914D\u7F6E"}, db=${cfg.db_host}:${cfg.db_port})`
|
|
99
97
|
);
|
|
100
98
|
startConsole({
|
|
101
99
|
config: cfg,
|
|
@@ -117,8 +115,7 @@ async function main() {
|
|
|
117
115
|
publicServer: cfg.public_server,
|
|
118
116
|
dbHost: cfg.db_host,
|
|
119
117
|
dbPort: cfg.db_port,
|
|
120
|
-
adminOpenids: Array.isArray(cfg.qq_admin_openids) ? cfg.qq_admin_openids : []
|
|
121
|
-
bridgeChannelId: "qq"
|
|
118
|
+
adminOpenids: Array.isArray(cfg.qq_admin_openids) ? cfg.qq_admin_openids : []
|
|
122
119
|
},
|
|
123
120
|
startedAt
|
|
124
121
|
);
|
|
@@ -133,7 +130,7 @@ async function main() {
|
|
|
133
130
|
await startWsServer({ port: cfg.qq_ws_port, dispatcher });
|
|
134
131
|
installQqRuntimeStatusHooks("llbot");
|
|
135
132
|
log.info(
|
|
136
|
-
`LLBot \u540E\u7AEF\u7B49\u5F85\u8FDE\u63A5 (\u4E3B\u7FA4: ${cfg.qq_group_id || "\u672A\u914D\u7F6E"},
|
|
133
|
+
`LLBot \u540E\u7AEF\u7B49\u5F85\u8FDE\u63A5 (\u4E3B\u7FA4: ${cfg.qq_group_id || "\u672A\u914D\u7F6E"}, db: ${cfg.db_host}:${cfg.db_port})`
|
|
137
134
|
);
|
|
138
135
|
startConsole({
|
|
139
136
|
config: cfg,
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n/**\n * index.ts \u2014 QQ \u2194 MC \u6865\u63A5\u8FDB\u7A0B\u5165\u53E3\n *\n * \u53CC\u540E\u7AEF:\n * official \u2014 \u7FA4\u5168\u91CF\u6D88\u606F\u53EA\u5904\u7406\u6307\u4EE4\uFF1B\u7FA4 @ \u6D88\u606F\u53EF\u8F6C\u53D1\u6E38\u620F\uFF1BC2C \u8D70\u6307\u4EE4\n * llbot \u2014 \u76D1\u542C WS:3002 \u63A5 LLBot reverse-ws\uFF08OneBot 11\uFF09\n *\n * \u5171\u540C\u51FA\u7AD9\u4FE1\u5C01: POST db-server:3001/api/sfmc/messages\n * MC\u2192QQ \u7531 db-server \u6309\u540C\u4E00 qq_backend \u76F4\u8FDE\u5B98\u65B9 OpenAPI \u6216 LLBot HTTP\n *\n * QQ \u4FA7\u6307\u4EE4\u5728\u6865\u5185\u62E6\u622A\uFF1Bofficial \u53EF sync \u81EA\u5B9A\u4E49\u83DC\u5355 / \u7FA4\u6307\u4EE4\u9762\u677F\u3002\n */\n\nimport { createLlbotCommandRouter, createOfficialCommandRouter } from \"./commands/index.js\";\nimport { createInteractionRouter } from \"./commands/interaction-router.js\";\nimport { persistPanelIdToConfig, syncMenuAndPanel } from \"./commands/menu-panel-sync.js\";\nimport { loadInitialConfig } from \"./config.js\";\nimport { startConsole } from \"./console.js\";\nimport { log } from \"./log.js\";\nimport { OfficialAtMessageDispatcher } from \"./official/events.js\";\nimport { startOfficialGateway } from \"./official/gateway.js\";\nimport { startOfficialWebhook } from \"./official/webhook.js\";\nimport { OneBotDispatcher } from \"./onebot.js\";\nimport { installQqRuntimeStatusHooks } from \"./runtime-status.js\";\nimport type { QQBridgeConfig } from \"./types.js\";\nimport { startWsServer } from \"./ws-server.js\";\n\nasync function main(): Promise<void> {\n const cfg: QQBridgeConfig = loadInitialConfig();\n const startedAt = Date.now();\n\n if (!cfg.qq_enabled) {\n log.info(\"\u5DF2\u7981\u7528 (qq_enabled = false)\");\n process.exit(0);\n }\n\n const botSelfIdRef: { value: string | null } = { value: null };\n const db = {\n host: cfg.db_host,\n port: cfg.db_port,\n
|
|
5
|
-
"mappings": ";AAcA,SAAS,0BAA0B,mCAAmC;AACtE,SAAS,+BAA+B;AACxC,SAAS,wBAAwB,wBAAwB;AACzD,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,WAAW;AACpB,SAAS,mCAAmC;AAC5C,SAAS,4BAA4B;AACrC,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AACjC,SAAS,mCAAmC;AAE5C,SAAS,qBAAqB;AAE9B,eAAe,OAAsB;AACnC,QAAM,MAAsB,kBAAkB;AAC9C,QAAM,YAAY,KAAK,IAAI;AAE3B,MAAI,CAAC,IAAI,YAAY;AACnB,QAAI,KAAK,yCAA0B;AACnC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,eAAyC,EAAE,OAAO,KAAK;AAC7D,QAAM,KAAK;AAAA,IACT,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n/**\n * index.ts \u2014 QQ \u2194 MC \u6865\u63A5\u8FDB\u7A0B\u5165\u53E3\n *\n * \u53CC\u540E\u7AEF:\n * official \u2014 \u7FA4\u5168\u91CF\u6D88\u606F\u53EA\u5904\u7406\u6307\u4EE4\uFF1B\u7FA4 @ \u6D88\u606F\u53EF\u8F6C\u53D1\u6E38\u620F\uFF1BC2C \u8D70\u6307\u4EE4\n * llbot \u2014 \u76D1\u542C WS:3002 \u63A5 LLBot reverse-ws\uFF08OneBot 11\uFF09\n *\n * \u5171\u540C\u51FA\u7AD9\u4FE1\u5C01: POST db-server:3001/api/sfmc/messages\n * MC\u2192QQ \u7531 db-server \u6309\u540C\u4E00 qq_backend \u76F4\u8FDE\u5B98\u65B9 OpenAPI \u6216 LLBot HTTP\n *\n * QQ \u4FA7\u6307\u4EE4\u5728\u6865\u5185\u62E6\u622A\uFF1Bofficial \u53EF sync \u81EA\u5B9A\u4E49\u83DC\u5355 / \u7FA4\u6307\u4EE4\u9762\u677F\u3002\n */\n\nimport { createLlbotCommandRouter, createOfficialCommandRouter } from \"./commands/index.js\";\nimport { createInteractionRouter } from \"./commands/interaction-router.js\";\nimport { persistPanelIdToConfig, syncMenuAndPanel } from \"./commands/menu-panel-sync.js\";\nimport { loadInitialConfig } from \"./config.js\";\nimport { startConsole } from \"./console.js\";\nimport { log } from \"./log.js\";\nimport { OfficialAtMessageDispatcher } from \"./official/events.js\";\nimport { startOfficialGateway } from \"./official/gateway.js\";\nimport { startOfficialWebhook } from \"./official/webhook.js\";\nimport { OneBotDispatcher } from \"./onebot.js\";\nimport { installQqRuntimeStatusHooks } from \"./runtime-status.js\";\nimport type { QQBridgeConfig } from \"./types.js\";\nimport { startWsServer } from \"./ws-server.js\";\n\nasync function main(): Promise<void> {\n const cfg: QQBridgeConfig = loadInitialConfig();\n const startedAt = Date.now();\n\n if (!cfg.qq_enabled) {\n log.info(\"\u5DF2\u7981\u7528 (qq_enabled = false)\");\n process.exit(0);\n }\n\n const botSelfIdRef: { value: string | null } = { value: null };\n const db = {\n host: cfg.db_host,\n port: cfg.db_port,\n };\n\n if (cfg.qq_backend === \"official\") {\n if (!cfg.qq_app_id || !cfg.qq_app_secret) {\n log.error(\"\u5B98\u65B9\u540E\u7AEF\u9700\u8981\u914D\u7F6E official.app_id \u4E0E official.app_secret\");\n process.exit(1);\n }\n\n const creds = {\n appId: cfg.qq_app_id,\n appSecret: cfg.qq_app_secret,\n sandbox: cfg.qq_sandbox,\n };\n const appId = cfg.qq_app_id;\n const commandRouter = createOfficialCommandRouter(\n creds,\n {\n sandbox: cfg.qq_sandbox,\n appIdHint: appId.length > 8 ? `${appId.slice(0, 4)}\u2026${appId.slice(-4)}` : appId,\n publicServer: cfg.public_server,\n dbHost: cfg.db_host,\n dbPort: cfg.db_port,\n groupOpenid: cfg.qq_group_openid,\n adminOpenids: Array.isArray(cfg.qq_admin_openids) ? cfg.qq_admin_openids : [],\n officialCreds: creds,\n },\n startedAt\n );\n\n const runSyncMenu = async (): Promise<void> => {\n if (cfg.qq_sync_menu_panel === false) {\n log.info(\"\u5DF2\u8DF3\u8FC7 menu/panel sync\uFF08qq_sync_menu_panel=false\uFF09\");\n return;\n }\n await syncMenuAndPanel({\n creds,\n registry: commandRouter.registry,\n groupOpenid: cfg.qq_group_openid,\n panelId: String(cfg.qq_group_panel_id ?? \"\"),\n persistPanelId: (id) => {\n cfg.qq_group_panel_id = id;\n persistPanelIdToConfig(id);\n },\n });\n };\n\n const dispatcher = new OfficialAtMessageDispatcher({\n groupOpenid: cfg.qq_group_openid,\n db,\n commandRouter,\n });\n\n const interactionRouter = createInteractionRouter({\n creds,\n commandRouter,\n groupOpenid: cfg.qq_group_openid,\n });\n\n if (cfg.qq_official_transport === \"webhook\") {\n await startOfficialWebhook({\n appId: creds.appId,\n appSecret: creds.appSecret,\n port: cfg.qq_webhook_port,\n path: cfg.qq_webhook_path,\n dispatcher,\n interactionRouter,\n });\n } else {\n await startOfficialGateway({\n creds,\n dispatcher,\n interactionRouter,\n });\n }\n\n // \u4E0D\u963B\u65AD Gateway\uFF1A\u5931\u8D25\u53EA warn\n void runSyncMenu().catch((e) => log.warn(`menu/panel sync \u5F02\u5E38: ${(e as Error).message}`));\n\n installQqRuntimeStatusHooks(\"official\");\n\n log.info(\n `\u5B98\u65B9\u540E\u7AEF\u5DF2\u542F\u52A8 (transport=${cfg.qq_official_transport}, sandbox=${cfg.qq_sandbox}, group_openid=${cfg.qq_group_openid || \"\u672A\u914D\u7F6E\"}, db=${cfg.db_host}:${cfg.db_port})`\n );\n\n startConsole({\n config: cfg,\n initialEnabled: cfg.qq_enabled,\n wsPort: 0,\n botSelfIdRef,\n backend: \"official\",\n onSyncMenu: runSyncMenu,\n });\n } else {\n const commandRouter = createLlbotCommandRouter(\n {\n host: cfg.llbot_host || \"127.0.0.1\",\n port: cfg.llbot_port || 3004,\n token: cfg.llbot_token || \"\",\n groupId: cfg.qq_group_id || \"0\",\n },\n {\n publicServer: cfg.public_server,\n dbHost: cfg.db_host,\n dbPort: cfg.db_port,\n adminOpenids: Array.isArray(cfg.qq_admin_openids) ? cfg.qq_admin_openids : [],\n },\n startedAt\n );\n\n const dispatcher = new OneBotDispatcher({\n qqGroupId: cfg.qq_group_id,\n db,\n commandRouter,\n });\n\n Object.defineProperty(botSelfIdRef, \"value\", {\n get: () => dispatcher.selfId,\n });\n\n await startWsServer({ port: cfg.qq_ws_port, dispatcher });\n\n installQqRuntimeStatusHooks(\"llbot\");\n\n log.info(\n `LLBot \u540E\u7AEF\u7B49\u5F85\u8FDE\u63A5 (\u4E3B\u7FA4: ${cfg.qq_group_id || \"\u672A\u914D\u7F6E\"}, db: ${cfg.db_host}:${cfg.db_port})`\n );\n\n startConsole({\n config: cfg,\n initialEnabled: cfg.qq_enabled,\n wsPort: cfg.qq_ws_port,\n botSelfIdRef,\n backend: \"llbot\",\n });\n }\n\n log.info(\"\u542F\u52A8\u5B8C\u6210\");\n}\n\nmain().catch((e) => {\n log.error(`\u672A\u6355\u83B7\u5F02\u5E38: ${(e as Error).message}`);\n process.exit(1);\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/official/events.js
CHANGED
|
@@ -55,23 +55,21 @@ class OfficialAtMessageDispatcher {
|
|
|
55
55
|
this.opts = opts;
|
|
56
56
|
this.forward = opts.forward ?? tryForward;
|
|
57
57
|
}
|
|
58
|
-
/**
|
|
58
|
+
/** 全量群消息处理指令和普通聊天;与 @ 事件共用消息 ID 去重。 */
|
|
59
59
|
async handleGroupMessage(msg) {
|
|
60
60
|
if (!msg || typeof msg !== "object" || msg.author?.bot) return;
|
|
61
61
|
const groupOpenid = String(msg.group_openid ?? "");
|
|
62
62
|
if (!groupOpenid || !this.opts.groupOpenid || groupOpenid !== this.opts.groupOpenid) return;
|
|
63
63
|
if (/^<@!?/.test(String(msg.content ?? "").trim()) && msg.mentions?.length && !msg.mentions.some((mention) => mention.is_you)) return;
|
|
64
|
-
const router = this.opts.commandRouter;
|
|
65
|
-
if (!router) return;
|
|
66
64
|
const text = extractOfficialText(msg);
|
|
67
65
|
if (!text) return;
|
|
66
|
+
if (this.dedup.seen(msg.id)) return;
|
|
67
|
+
const router = this.opts.commandRouter;
|
|
68
68
|
const normalized = text.replace(/^[//]+/, "").trim();
|
|
69
69
|
const isConfirmation = /^(confirm|确认|cancel|取消)(?:\s+\S+)?$/i.test(normalized);
|
|
70
|
-
if (!router.registry.resolve(normalized) && !isConfirmation && !/^[//]/.test(text)) return;
|
|
71
|
-
if (this.dedup.seen(msg.id)) return;
|
|
72
70
|
const memberId = String(msg.author?.member_openid || msg.author?.id || "unknown");
|
|
73
71
|
const fromName = String(msg.author?.username || `QQ_${memberId.slice(0, 8)}`);
|
|
74
|
-
await router.handle({
|
|
72
|
+
if (router && (router.registry.resolve(normalized) || isConfirmation || /^[//]/.test(text)) && await router.handle({
|
|
75
73
|
backend: "official",
|
|
76
74
|
scene: "group",
|
|
77
75
|
groupId: groupOpenid,
|
|
@@ -80,7 +78,8 @@ class OfficialAtMessageDispatcher {
|
|
|
80
78
|
text,
|
|
81
79
|
isGroupAdmin: detectOfficialGroupAdmin(msg),
|
|
82
80
|
...msg.id ? { msgId: String(msg.id) } : {}
|
|
83
|
-
});
|
|
81
|
+
})) return;
|
|
82
|
+
await this.forward(this.opts.db, `qq_${memberId}`, fromName, text);
|
|
84
83
|
}
|
|
85
84
|
async handleGroupAtMessage(msg) {
|
|
86
85
|
if (!msg || typeof msg !== "object") return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/official/events.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * official/events.ts \u2014 \u5B98\u65B9\u7FA4\u6D88\u606F / C2C \u89E3\u6790\u4E0E\u8F6C\u53D1\n */\n\nimport { stripOfficialAtMention } from \"@sfmc-bds/sdk/node/qq-official\";\nimport type { CommandRouter } from \"../commands/index.js\";\nimport { RecentMessageDedup } from \"../onebot.js\";\nimport { tryForward, type DBServerConfig } from \"../dbserver.js\";\nimport { log } from \"../log.js\";\n\nexport type OfficialAttachment = {\n url?: string;\n content_type?: string;\n filename?: string;\n};\n\nexport type OfficialGroupAtMessage = {\n id?: string;\n content?: string;\n group_openid?: string;\n timestamp?: string;\n author?: {\n id?: string;\n member_openid?: string;\n username?: string;\n bot?: boolean;\n /** \u82E5\u5E73\u53F0\u4E0B\u53D1\u5219\u89E3\u6790\uFF1B\u65E0\u5219\u65E0\u6CD5\u5224\u5B9A\u7FA4\u7BA1 */\n roles?: unknown;\n member_role?: unknown;\n };\n member?: {\n roles?: unknown;\n role?: unknown;\n };\n attachments?: OfficialAttachment[];\n mentions?: Array<{ is_you?: boolean; username?: string }>;\n};\n\n/** \u4ECE\u5B98\u65B9\u4E8B\u4EF6\u53EF\u9009\u5B57\u6BB5\u63A8\u65AD\u7FA4\u4E3B/\u7FA4\u7BA1\uFF08\u65E0\u53EF\u9760\u5B57\u6BB5\u5219 false\uFF09 */\nfunction detectOfficialGroupAdmin(msg: OfficialGroupAtMessage): boolean {\n const candidates: unknown[] = [\n msg.author?.member_role,\n msg.author?.roles,\n msg.member?.role,\n msg.member?.roles,\n ];\n for (const c of candidates) {\n if (c == null) continue;\n if (Array.isArray(c)) {\n const joined = c.map((x) => String(x).toLowerCase()).join(\",\");\n if (/\\b(owner|admin|2|3)\\b/.test(joined)) return true;\n continue;\n }\n const s = String(c).toLowerCase();\n if (s === \"owner\" || s === \"admin\" || s === \"2\" || s === \"3\") return true;\n }\n return false;\n}\n\n/** C2C \u5355\u804A\u4E8B\u4EF6\u4F53 */\nexport type OfficialC2cMessage = {\n id?: string;\n content?: string;\n timestamp?: string;\n author?: {\n id?: string;\n user_openid?: string;\n username?: string;\n bot?: boolean;\n };\n attachments?: OfficialAttachment[];\n};\n\nexport type OfficialForwardFn = (\n db: DBServerConfig,\n fromId: string,\n fromName: string,\n content: string\n) => Promise<void>;\n\nexport type OfficialDispatcherOptions = {\n /** \u5DF2\u914D\u7F6E\u7684\u7FA4 openid\uFF1B\u7A7A = \u53EA\u6253\u65E5\u5FD7\u4E0D\u8F6C\u53D1 */\n groupOpenid: string;\n db: DBServerConfig;\n /** \u53EF\u6CE8\u5165\uFF0C\u9ED8\u8BA4 tryForward\uFF08\u4FBF\u4E8E\u5355\u6D4B\uFF09 */\n forward?: OfficialForwardFn;\n /** QQ \u4FA7\u6307\u4EE4\u8DEF\u7531\uFF1B\u547D\u4E2D\u5219\u4E0D\u8F6C\u53D1 MC */\n commandRouter?: CommandRouter;\n};\n\n/**\n * \u628A attachments \u8F6C\u6210\u4E0E OneBot \u4E00\u81F4\u7684\u5360\u4F4D\u7B26\u540E\u7F00\u3002\n */\nexport function attachmentsPlaceholder(attachments: OfficialAttachment[] | undefined): string {\n if (!Array.isArray(attachments) || attachments.length === 0) return \"\";\n const parts: string[] = [];\n for (const att of attachments) {\n const ct = String(att.content_type ?? \"\").toLowerCase();\n const name = String(att.filename ?? \"\").toLowerCase();\n if (ct.startsWith(\"image/\") || /\\.(png|jpe?g|gif|webp|bmp)$/i.test(name)) {\n parts.push(\"[\u56FE\u7247]\");\n } else if (ct.startsWith(\"video/\") || /\\.(mp4|mov|avi|mkv)$/i.test(name)) {\n parts.push(\"[\u89C6\u9891]\");\n } else if (ct.startsWith(\"audio/\") || /\\.(mp3|wav|amr|silk)$/i.test(name)) {\n parts.push(\"[\u8BED\u97F3]\");\n } else {\n parts.push(\"[\u6587\u4EF6]\");\n }\n }\n return parts.join(\"\");\n}\n\n/** \u4ECE\u5B98\u65B9\u4E8B\u4EF6\u62BD\u51FA\u7EAF\u6587\u672C\uFF08\u53BB @bot + \u9644\u4EF6\u5360\u4F4D\uFF09 */\nexport function extractOfficialText(msg: {\n content?: string;\n attachments?: OfficialAttachment[];\n mentions?: Array<{ is_you?: boolean; username?: string }>;\n}): string {\n let base = stripOfficialAtMention(String(msg.content ?? \"\"));\n const botName = msg.mentions?.find((mention) => mention.is_you)?.username;\n if (botName && base.startsWith(`@${botName}`)) base = base.slice(botName.length + 1).trim();\n const suffix = attachmentsPlaceholder(msg.attachments);\n return `${base}${suffix ? (base ? \" \" : \"\") + suffix : \"\"}`.trim();\n}\n\nexport class OfficialAtMessageDispatcher {\n private readonly opts: OfficialDispatcherOptions;\n private readonly dedup = new RecentMessageDedup();\n private readonly forward: OfficialForwardFn;\n private loggedMissingOpenid = false;\n\n constructor(opts: OfficialDispatcherOptions) {\n this.opts = opts;\n this.forward = opts.forward ?? tryForward;\n }\n\n /** \u5168\u91CF\u7FA4\u6D88\u606F\
|
|
5
|
-
"mappings": "AAIA,SAAS,8BAA8B;AAEvC,SAAS,0BAA0B;AACnC,SAAS,kBAAuC;AAChD,SAAS,WAAW;AA+BpB,SAAS,yBAAyB,KAAsC;AACtE,QAAM,aAAwB;AAAA,IAC5B,IAAI,QAAQ;AAAA,IACZ,IAAI,QAAQ;AAAA,IACZ,IAAI,QAAQ;AAAA,IACZ,IAAI,QAAQ;AAAA,EACd;AACA,aAAW,KAAK,YAAY;AAC1B,QAAI,KAAK,KAAM;AACf,QAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,YAAM,SAAS,EAAE,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,YAAY,CAAC,EAAE,KAAK,GAAG;AAC7D,UAAI,wBAAwB,KAAK,MAAM,EAAG,QAAO;AACjD;AAAA,IACF;AACA,UAAM,IAAI,OAAO,CAAC,EAAE,YAAY;AAChC,QAAI,MAAM,WAAW,MAAM,WAAW,MAAM,OAAO,MAAM,IAAK,QAAO;AAAA,EACvE;AACA,SAAO;AACT;AAoCO,SAAS,uBAAuB,aAAuD;AAC5F,MAAI,CAAC,MAAM,QAAQ,WAAW,KAAK,YAAY,WAAW,EAAG,QAAO;AACpE,QAAM,QAAkB,CAAC;AACzB,aAAW,OAAO,aAAa;AAC7B,UAAM,KAAK,OAAO,IAAI,gBAAgB,EAAE,EAAE,YAAY;AACtD,UAAM,OAAO,OAAO,IAAI,YAAY,EAAE,EAAE,YAAY;AACpD,QAAI,GAAG,WAAW,QAAQ,KAAK,+BAA+B,KAAK,IAAI,GAAG;AACxE,YAAM,KAAK,gBAAM;AAAA,IACnB,WAAW,GAAG,WAAW,QAAQ,KAAK,wBAAwB,KAAK,IAAI,GAAG;AACxE,YAAM,KAAK,gBAAM;AAAA,IACnB,WAAW,GAAG,WAAW,QAAQ,KAAK,yBAAyB,KAAK,IAAI,GAAG;AACzE,YAAM,KAAK,gBAAM;AAAA,IACnB,OAAO;AACL,YAAM,KAAK,gBAAM;AAAA,IACnB;AAAA,EACF;AACA,SAAO,MAAM,KAAK,EAAE;AACtB;AAGO,SAAS,oBAAoB,KAIzB;AACT,MAAI,OAAO,uBAAuB,OAAO,IAAI,WAAW,EAAE,CAAC;AAC3D,QAAM,UAAU,IAAI,UAAU,KAAK,CAAC,YAAY,QAAQ,MAAM,GAAG;AACjE,MAAI,WAAW,KAAK,WAAW,IAAI,OAAO,EAAE,EAAG,QAAO,KAAK,MAAM,QAAQ,SAAS,CAAC,EAAE,KAAK;AAC1F,QAAM,SAAS,uBAAuB,IAAI,WAAW;AACrD,SAAO,GAAG,IAAI,GAAG,UAAU,OAAO,MAAM,MAAM,SAAS,EAAE,GAAG,KAAK;AACnE;AAEO,MAAM,4BAA4B;AAAA,EACtB;AAAA,EACA,QAAQ,IAAI,mBAAmB;AAAA,EAC/B;AAAA,EACT,sBAAsB;AAAA,EAE9B,YAAY,MAAiC;AAC3C,SAAK,OAAO;AACZ,SAAK,UAAU,KAAK,WAAW;AAAA,EACjC;AAAA;AAAA,EAGA,MAAM,mBAAmB,KAA4C;AACnE,QAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,IAAI,QAAQ,IAAK;AACxD,UAAM,cAAc,OAAO,IAAI,gBAAgB,EAAE;AACjD,QAAI,CAAC,eAAe,CAAC,KAAK,KAAK,eAAe,gBAAgB,KAAK,KAAK,YAAa;AACrF,QACE,QAAQ,KAAK,OAAO,IAAI,WAAW,EAAE,EAAE,KAAK,CAAC,KAC7C,IAAI,UAAU,UACd,CAAC,IAAI,SAAS,KAAK,CAAC,YAAY,QAAQ,MAAM,EAC9C;AACF,UAAM,
|
|
4
|
+
"sourcesContent": ["/**\n * official/events.ts \u2014 \u5B98\u65B9\u7FA4\u6D88\u606F / C2C \u89E3\u6790\u4E0E\u8F6C\u53D1\n */\n\nimport { stripOfficialAtMention } from \"@sfmc-bds/sdk/node/qq-official\";\nimport type { CommandRouter } from \"../commands/index.js\";\nimport { RecentMessageDedup } from \"../onebot.js\";\nimport { tryForward, type DBServerConfig } from \"../dbserver.js\";\nimport { log } from \"../log.js\";\n\nexport type OfficialAttachment = {\n url?: string;\n content_type?: string;\n filename?: string;\n};\n\nexport type OfficialGroupAtMessage = {\n id?: string;\n content?: string;\n group_openid?: string;\n timestamp?: string;\n author?: {\n id?: string;\n member_openid?: string;\n username?: string;\n bot?: boolean;\n /** \u82E5\u5E73\u53F0\u4E0B\u53D1\u5219\u89E3\u6790\uFF1B\u65E0\u5219\u65E0\u6CD5\u5224\u5B9A\u7FA4\u7BA1 */\n roles?: unknown;\n member_role?: unknown;\n };\n member?: {\n roles?: unknown;\n role?: unknown;\n };\n attachments?: OfficialAttachment[];\n mentions?: Array<{ is_you?: boolean; username?: string }>;\n};\n\n/** \u4ECE\u5B98\u65B9\u4E8B\u4EF6\u53EF\u9009\u5B57\u6BB5\u63A8\u65AD\u7FA4\u4E3B/\u7FA4\u7BA1\uFF08\u65E0\u53EF\u9760\u5B57\u6BB5\u5219 false\uFF09 */\nfunction detectOfficialGroupAdmin(msg: OfficialGroupAtMessage): boolean {\n const candidates: unknown[] = [\n msg.author?.member_role,\n msg.author?.roles,\n msg.member?.role,\n msg.member?.roles,\n ];\n for (const c of candidates) {\n if (c == null) continue;\n if (Array.isArray(c)) {\n const joined = c.map((x) => String(x).toLowerCase()).join(\",\");\n if (/\\b(owner|admin|2|3)\\b/.test(joined)) return true;\n continue;\n }\n const s = String(c).toLowerCase();\n if (s === \"owner\" || s === \"admin\" || s === \"2\" || s === \"3\") return true;\n }\n return false;\n}\n\n/** C2C \u5355\u804A\u4E8B\u4EF6\u4F53 */\nexport type OfficialC2cMessage = {\n id?: string;\n content?: string;\n timestamp?: string;\n author?: {\n id?: string;\n user_openid?: string;\n username?: string;\n bot?: boolean;\n };\n attachments?: OfficialAttachment[];\n};\n\nexport type OfficialForwardFn = (\n db: DBServerConfig,\n fromId: string,\n fromName: string,\n content: string\n) => Promise<void>;\n\nexport type OfficialDispatcherOptions = {\n /** \u5DF2\u914D\u7F6E\u7684\u7FA4 openid\uFF1B\u7A7A = \u53EA\u6253\u65E5\u5FD7\u4E0D\u8F6C\u53D1 */\n groupOpenid: string;\n db: DBServerConfig;\n /** \u53EF\u6CE8\u5165\uFF0C\u9ED8\u8BA4 tryForward\uFF08\u4FBF\u4E8E\u5355\u6D4B\uFF09 */\n forward?: OfficialForwardFn;\n /** QQ \u4FA7\u6307\u4EE4\u8DEF\u7531\uFF1B\u547D\u4E2D\u5219\u4E0D\u8F6C\u53D1 MC */\n commandRouter?: CommandRouter;\n};\n\n/**\n * \u628A attachments \u8F6C\u6210\u4E0E OneBot \u4E00\u81F4\u7684\u5360\u4F4D\u7B26\u540E\u7F00\u3002\n */\nexport function attachmentsPlaceholder(attachments: OfficialAttachment[] | undefined): string {\n if (!Array.isArray(attachments) || attachments.length === 0) return \"\";\n const parts: string[] = [];\n for (const att of attachments) {\n const ct = String(att.content_type ?? \"\").toLowerCase();\n const name = String(att.filename ?? \"\").toLowerCase();\n if (ct.startsWith(\"image/\") || /\\.(png|jpe?g|gif|webp|bmp)$/i.test(name)) {\n parts.push(\"[\u56FE\u7247]\");\n } else if (ct.startsWith(\"video/\") || /\\.(mp4|mov|avi|mkv)$/i.test(name)) {\n parts.push(\"[\u89C6\u9891]\");\n } else if (ct.startsWith(\"audio/\") || /\\.(mp3|wav|amr|silk)$/i.test(name)) {\n parts.push(\"[\u8BED\u97F3]\");\n } else {\n parts.push(\"[\u6587\u4EF6]\");\n }\n }\n return parts.join(\"\");\n}\n\n/** \u4ECE\u5B98\u65B9\u4E8B\u4EF6\u62BD\u51FA\u7EAF\u6587\u672C\uFF08\u53BB @bot + \u9644\u4EF6\u5360\u4F4D\uFF09 */\nexport function extractOfficialText(msg: {\n content?: string;\n attachments?: OfficialAttachment[];\n mentions?: Array<{ is_you?: boolean; username?: string }>;\n}): string {\n let base = stripOfficialAtMention(String(msg.content ?? \"\"));\n const botName = msg.mentions?.find((mention) => mention.is_you)?.username;\n if (botName && base.startsWith(`@${botName}`)) base = base.slice(botName.length + 1).trim();\n const suffix = attachmentsPlaceholder(msg.attachments);\n return `${base}${suffix ? (base ? \" \" : \"\") + suffix : \"\"}`.trim();\n}\n\nexport class OfficialAtMessageDispatcher {\n private readonly opts: OfficialDispatcherOptions;\n private readonly dedup = new RecentMessageDedup();\n private readonly forward: OfficialForwardFn;\n private loggedMissingOpenid = false;\n\n constructor(opts: OfficialDispatcherOptions) {\n this.opts = opts;\n this.forward = opts.forward ?? tryForward;\n }\n\n /** \u5168\u91CF\u7FA4\u6D88\u606F\u5904\u7406\u6307\u4EE4\u548C\u666E\u901A\u804A\u5929\uFF1B\u4E0E @ \u4E8B\u4EF6\u5171\u7528\u6D88\u606F ID \u53BB\u91CD\u3002 */\n async handleGroupMessage(msg: OfficialGroupAtMessage): Promise<void> {\n if (!msg || typeof msg !== \"object\" || msg.author?.bot) return;\n const groupOpenid = String(msg.group_openid ?? \"\");\n if (!groupOpenid || !this.opts.groupOpenid || groupOpenid !== this.opts.groupOpenid) return;\n if (\n /^<@!?/.test(String(msg.content ?? \"\").trim()) &&\n msg.mentions?.length &&\n !msg.mentions.some((mention) => mention.is_you)\n ) return;\n const text = extractOfficialText(msg);\n if (!text) return;\n if (this.dedup.seen(msg.id)) return;\n const router = this.opts.commandRouter;\n const normalized = text.replace(/^[/\uFF0F]+/, \"\").trim();\n const isConfirmation = /^(confirm|\u786E\u8BA4|cancel|\u53D6\u6D88)(?:\\s+\\S+)?$/i.test(normalized);\n const memberId = String(msg.author?.member_openid || msg.author?.id || \"unknown\");\n const fromName = String(msg.author?.username || `QQ_${memberId.slice(0, 8)}`);\n if (\n router &&\n (router.registry.resolve(normalized) || isConfirmation || /^[/\uFF0F]/.test(text)) &&\n await router.handle({\n backend: \"official\",\n scene: \"group\",\n groupId: groupOpenid,\n userId: memberId,\n userName: fromName,\n text,\n isGroupAdmin: detectOfficialGroupAdmin(msg),\n ...(msg.id ? { msgId: String(msg.id) } : {}),\n })\n ) return;\n await this.forward(this.opts.db, `qq_${memberId}`, fromName, text);\n }\n\n async handleGroupAtMessage(msg: OfficialGroupAtMessage): Promise<void> {\n if (!msg || typeof msg !== \"object\") return;\n if (msg.author?.bot) return;\n\n const groupOpenid = String(msg.group_openid ?? \"\");\n if (!groupOpenid) {\n log.warn(\"\u5B98\u65B9\u4E8B\u4EF6\u7F3A group_openid\uFF0C\u8DF3\u8FC7\");\n return;\n }\n\n if (!this.opts.groupOpenid) {\n if (!this.loggedMissingOpenid) {\n log.warn(\n `official.group_openid \u672A\u914D\u7F6E\u3002\u6536\u5230\u7FA4 openid=${groupOpenid}\uFF0C\u8BF7\u5199\u5165 configs/qq_config.json \u540E\u91CD\u542F\uFF08\u672C\u6761\u4E0D\u8F6C\u53D1\uFF09`\n );\n this.loggedMissingOpenid = true;\n } else {\n log.info(`official.group_openid \u672A\u914D\u7F6E\uFF0C\u4E22\u5F03\u7FA4\u6D88\u606F openid=${groupOpenid}`);\n }\n return;\n }\n\n if (groupOpenid !== this.opts.groupOpenid) {\n log.info(`\u975E\u76EE\u6807\u7FA4 openid=${groupOpenid}\uFF0C\u8DF3\u8FC7`);\n return;\n }\n\n if (this.dedup.seen(msg.id)) return;\n\n const text = extractOfficialText(msg);\n if (!text) return;\n\n const memberId = String(msg.author?.member_openid || msg.author?.id || \"unknown\");\n const fromName = String(msg.author?.username || `QQ_${memberId.slice(0, 8)}`);\n const fromId = `qq_${memberId}`;\n\n if (this.opts.commandRouter) {\n const inbound = {\n backend: \"official\" as const,\n scene: \"group\" as const,\n groupId: groupOpenid,\n userId: memberId,\n userName: fromName,\n text,\n isGroupAdmin: detectOfficialGroupAdmin(msg),\n ...(msg.id ? { msgId: String(msg.id) } : {}),\n };\n if (await this.opts.commandRouter.handle(inbound)) return;\n }\n\n await this.forward(this.opts.db, fromId, fromName, text);\n }\n\n /**\n * \u5355\u804A\uFF1A\u4EC5\u8D70\u6307\u4EE4\u8DEF\u7531\uFF08\u83DC\u5355\u70B9\u51FB\u843D\u70B9\uFF09\uFF0C\u4E0D\u8F6C\u53D1 MC\u3002\n */\n async handleC2cMessage(msg: OfficialC2cMessage): Promise<void> {\n if (!msg || typeof msg !== \"object\") return;\n if (msg.author?.bot) return;\n if (this.dedup.seen(msg.id)) return;\n\n const text = extractOfficialText(msg);\n if (!text) return;\n\n const userId = String(msg.author?.user_openid || msg.author?.id || \"unknown\");\n const fromName = String(msg.author?.username || `QQ_${userId.slice(0, 8)}`);\n\n if (!this.opts.commandRouter) {\n log.info(`C2C \u65E0\u6307\u4EE4\u8DEF\u7531\uFF0C\u5FFD\u7565 text=${text.slice(0, 40)}`);\n return;\n }\n\n const inbound = {\n backend: \"official\" as const,\n scene: \"c2c\" as const,\n groupId: `c2c:${userId}`,\n userId,\n userName: fromName,\n text,\n ...(msg.id ? { msgId: String(msg.id) } : {}),\n };\n await this.opts.commandRouter.handle(inbound);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/onebot.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/onebot.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * onebot.ts \u2014 OneBot 11 \u534F\u8BAE\u4E8B\u4EF6\u5206\u53D1\u4E0E\u6D88\u606F\u89E3\u6790\u4E2D\u5FC3\n *\n * \u6838\u5FC3\u673A\u5236\uFF1A\n * - \u673A\u5668\u4EBA\u81EA\u8EAB\u8EAB\u4EFD\u6355\u83B7\uFF1A\u4ECE OneBot lifecycle \u5143\u4E8B\u4EF6\u4E2D\u63D0\u53D6 `botSelfId`\uFF0C\u9632\u6B62\u81EA\u8EAB\u6D88\u606F\u56DE\u73AF\n * - \u6D88\u606F\u77ED\u671F\u53BB\u91CD\uFF1A\u7EF4\u62A4 5 \u79D2\u7A97\u53E3\u7684\u9AD8\u901F Map \u5E42\u7B49\u7F13\u5B58\uFF0C\u9632\u8303\u5916\u90E8\u5BA2\u6237\u7AEF\u5076\u53D1\u91CD\u590D\u63A8\u9001\n * - \u590D\u5408\u5BCC\u6587\u672C\u89C4\u6574\u5316\uFF1A\u5C06\u5305\u542B text / at / image / face / reply \u7B49\u591A\u6BB5\u590D\u5408\u5185\u5BB9\u683C\u5F0F\u5316\u4E3A\u6574\u6D01\u6587\u672C\n * - \u76EE\u6807\u7FA4\u4E0E\u547D\u4EE4\u5206\u6D41\uFF1A\u5BF9\u9F50\u914D\u7F6E\u7684\u76EE\u6807\u7FA4 ID\uFF0C\u6307\u4EE4\u4F18\u5148\u4EA4\u7531\u6307\u4EE4\u8DEF\u7531\u5668\u6D88\u8D39\uFF0C\u5176\u4F59\u6D88\u606F\u8F6C\u53D1\u81F3 MC\n */\n\nimport { log } from \"./log.js\";\nimport type { CommandRouter } from \"./commands/index.js\";\nimport { tryForward, type DBServerConfig } from \"./dbserver.js\";\nimport type {\n OneBotAtSegment,\n OneBotEvent,\n OneBotFaceSegment,\n OneBotFileSegment,\n OneBotForwardSegment,\n OneBotGroupMessageEvent,\n OneBotImageSegment,\n OneBotLifecycleEvent,\n OneBotRecordSegment,\n OneBotReplySegment,\n OneBotSegment,\n OneBotTextSegment,\n OneBotVideoSegment,\n} from \"./types.js\";\n\n\n// \u2500\u2500 \u7C7B\u578B\u5B88\u536B \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction isGroupMessageEvent(e: OneBotEvent): e is OneBotGroupMessageEvent {\n return e.post_type === \"message\" && e.message_type === \"group\";\n}\n\nfunction isLifecycleEvent(e: OneBotEvent): e is OneBotLifecycleEvent {\n return e.post_type === \"meta_event\" && e.meta_event_type === \"lifecycle\";\n}\n\nfunction isTextSegment(s: OneBotSegment | undefined): s is OneBotTextSegment {\n return s?.type === \"text\";\n}\nfunction isAtSegment(s: OneBotSegment | undefined): s is OneBotAtSegment {\n return s?.type === \"at\";\n}\nfunction isImageSegment(s: OneBotSegment | undefined): s is OneBotImageSegment {\n return s?.type === \"image\";\n}\nfunction isFaceSegment(s: OneBotSegment | undefined): s is OneBotFaceSegment {\n return s?.type === \"face\";\n}\nfunction isReplySegment(s: OneBotSegment | undefined): s is OneBotReplySegment {\n return s?.type === \"reply\";\n}\nfunction isForwardSegment(s: OneBotSegment | undefined): s is OneBotForwardSegment {\n return s?.type === \"forward\";\n}\nfunction isRecordSegment(s: OneBotSegment | undefined): s is OneBotRecordSegment {\n return s?.type === \"record\";\n}\nfunction isVideoSegment(s: OneBotSegment | undefined): s is OneBotVideoSegment {\n return s?.type === \"video\";\n}\nfunction isFileSegment(s: OneBotSegment | undefined): s is OneBotFileSegment {\n return s?.type === \"file\";\n}\n\n// \u2500\u2500 \u6D88\u606F\u6BB5 \u2192 \u7EAF\u6587\u672C \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * OneBot 11 \u6D88\u606F\u6BB5\u6570\u7EC4 (\u6216\u7EAF\u5B57\u7B26\u4E32) \u2192 \u7EAF\u6587\u672C\u3002\n * \u884C\u4E3A\u4E0E\u65E7\u5B9E\u73B0\u5B8C\u5168\u4E00\u81F4:\n * - text: \u539F\u6837\u62FC\u63A5\n * - at: \"@\u6635\u79F0 \" \u6216 \"@qq \" (\u6709 name \u4F18\u5148 name)\n * - \u5176\u5B83: [\u56FE\u7247]/[\u8868\u60C5]/[\u56DE\u590D]/[\u8F6C\u53D1]/[\u8BED\u97F3]/[\u89C6\u9891]/[\u6587\u4EF6]\n * - \u672A\u77E5\u6BB5: \u8DF3\u8FC7\n */\nexport function extractText(message: OneBotGroupMessageEvent[\"message\"]): string {\n if (typeof message === \"string\") return message;\n if (!Array.isArray(message)) return \"\";\n const parts: string[] = [];\n for (const seg of message) {\n if (!seg || typeof seg !== \"object\") continue;\n if (isTextSegment(seg)) {\n const text = seg.data.text;\n if (typeof text === \"string\") parts.push(text);\n } else if (isAtSegment(seg)) {\n const name = seg.data.name ? `@${seg.data.name} ` : `@${seg.data.qq ?? \"?\"} `;\n parts.push(name);\n } else if (isImageSegment(seg)) {\n parts.push(\"[\u56FE\u7247]\");\n } else if (isFaceSegment(seg)) {\n parts.push(\"[\u8868\u60C5]\");\n } else if (isReplySegment(seg)) {\n parts.push(\"[\u56DE\u590D]\");\n } else if (isForwardSegment(seg)) {\n parts.push(\"[\u8F6C\u53D1]\");\n } else if (isRecordSegment(seg)) {\n parts.push(\"[\u8BED\u97F3]\");\n } else if (isVideoSegment(seg)) {\n parts.push(\"[\u89C6\u9891]\");\n } else if (isFileSegment(seg)) {\n parts.push(\"[\u6587\u4EF6]\");\n }\n // \u672A\u77E5\u6BB5:\u8DF3\u8FC7\n }\n return parts.join(\"\").trim();\n}\n\n// \u2500\u2500 \u77ED\u671F message_id \u53BB\u91CD (\u61D2\u6E05\u7406) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst DEDUP_WINDOW_MS = 5_000;\nconst CLEANUP_INTERVAL_MS = 1_000;\n\nexport class RecentMessageDedup {\n private readonly map = new Map<string, number>();\n private lastCleanup = 0;\n\n seen(messageId: string | number | undefined): boolean {\n if (messageId === undefined || messageId === null) return false;\n const key = String(messageId);\n const now = Date.now();\n if (now - this.lastCleanup > CLEANUP_INTERVAL_MS) {\n this.lastCleanup = now;\n for (const [k, ts] of this.map) {\n if (now - ts > DEDUP_WINDOW_MS) this.map.delete(k);\n }\n }\n const prev = this.map.get(key);\n if (prev !== undefined && now - prev < DEDUP_WINDOW_MS) return true;\n this.map.set(key, now);\n return false;\n }\n}\n\n// \u2500\u2500 OneBot \u4E8B\u4EF6\u5206\u53D1\u5668 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface DispatcherOptions {\n /** \u7FA4 ID \u5B57\u7B26\u4E32,\u7A7A = \u63A5\u6536\u6240\u6709\u7FA4(\u65E7\u884C\u4E3A:\u7A7A\u65F6\u4E0D\u5339\u914D\u4EFB\u4F55\u7FA4,\u4E0D\u4F1A\u89E6\u53D1) */\n qqGroupId: string;\n /** db-server \
|
|
4
|
+
"sourcesContent": ["/**\n * onebot.ts \u2014 OneBot 11 \u534F\u8BAE\u4E8B\u4EF6\u5206\u53D1\u4E0E\u6D88\u606F\u89E3\u6790\u4E2D\u5FC3\n *\n * \u6838\u5FC3\u673A\u5236\uFF1A\n * - \u673A\u5668\u4EBA\u81EA\u8EAB\u8EAB\u4EFD\u6355\u83B7\uFF1A\u4ECE OneBot lifecycle \u5143\u4E8B\u4EF6\u4E2D\u63D0\u53D6 `botSelfId`\uFF0C\u9632\u6B62\u81EA\u8EAB\u6D88\u606F\u56DE\u73AF\n * - \u6D88\u606F\u77ED\u671F\u53BB\u91CD\uFF1A\u7EF4\u62A4 5 \u79D2\u7A97\u53E3\u7684\u9AD8\u901F Map \u5E42\u7B49\u7F13\u5B58\uFF0C\u9632\u8303\u5916\u90E8\u5BA2\u6237\u7AEF\u5076\u53D1\u91CD\u590D\u63A8\u9001\n * - \u590D\u5408\u5BCC\u6587\u672C\u89C4\u6574\u5316\uFF1A\u5C06\u5305\u542B text / at / image / face / reply \u7B49\u591A\u6BB5\u590D\u5408\u5185\u5BB9\u683C\u5F0F\u5316\u4E3A\u6574\u6D01\u6587\u672C\n * - \u76EE\u6807\u7FA4\u4E0E\u547D\u4EE4\u5206\u6D41\uFF1A\u5BF9\u9F50\u914D\u7F6E\u7684\u76EE\u6807\u7FA4 ID\uFF0C\u6307\u4EE4\u4F18\u5148\u4EA4\u7531\u6307\u4EE4\u8DEF\u7531\u5668\u6D88\u8D39\uFF0C\u5176\u4F59\u6D88\u606F\u8F6C\u53D1\u81F3 MC\n */\n\nimport { log } from \"./log.js\";\nimport type { CommandRouter } from \"./commands/index.js\";\nimport { tryForward, type DBServerConfig } from \"./dbserver.js\";\nimport type {\n OneBotAtSegment,\n OneBotEvent,\n OneBotFaceSegment,\n OneBotFileSegment,\n OneBotForwardSegment,\n OneBotGroupMessageEvent,\n OneBotImageSegment,\n OneBotLifecycleEvent,\n OneBotRecordSegment,\n OneBotReplySegment,\n OneBotSegment,\n OneBotTextSegment,\n OneBotVideoSegment,\n} from \"./types.js\";\n\n\n// \u2500\u2500 \u7C7B\u578B\u5B88\u536B \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction isGroupMessageEvent(e: OneBotEvent): e is OneBotGroupMessageEvent {\n return e.post_type === \"message\" && e.message_type === \"group\";\n}\n\nfunction isLifecycleEvent(e: OneBotEvent): e is OneBotLifecycleEvent {\n return e.post_type === \"meta_event\" && e.meta_event_type === \"lifecycle\";\n}\n\nfunction isTextSegment(s: OneBotSegment | undefined): s is OneBotTextSegment {\n return s?.type === \"text\";\n}\nfunction isAtSegment(s: OneBotSegment | undefined): s is OneBotAtSegment {\n return s?.type === \"at\";\n}\nfunction isImageSegment(s: OneBotSegment | undefined): s is OneBotImageSegment {\n return s?.type === \"image\";\n}\nfunction isFaceSegment(s: OneBotSegment | undefined): s is OneBotFaceSegment {\n return s?.type === \"face\";\n}\nfunction isReplySegment(s: OneBotSegment | undefined): s is OneBotReplySegment {\n return s?.type === \"reply\";\n}\nfunction isForwardSegment(s: OneBotSegment | undefined): s is OneBotForwardSegment {\n return s?.type === \"forward\";\n}\nfunction isRecordSegment(s: OneBotSegment | undefined): s is OneBotRecordSegment {\n return s?.type === \"record\";\n}\nfunction isVideoSegment(s: OneBotSegment | undefined): s is OneBotVideoSegment {\n return s?.type === \"video\";\n}\nfunction isFileSegment(s: OneBotSegment | undefined): s is OneBotFileSegment {\n return s?.type === \"file\";\n}\n\n// \u2500\u2500 \u6D88\u606F\u6BB5 \u2192 \u7EAF\u6587\u672C \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * OneBot 11 \u6D88\u606F\u6BB5\u6570\u7EC4 (\u6216\u7EAF\u5B57\u7B26\u4E32) \u2192 \u7EAF\u6587\u672C\u3002\n * \u884C\u4E3A\u4E0E\u65E7\u5B9E\u73B0\u5B8C\u5168\u4E00\u81F4:\n * - text: \u539F\u6837\u62FC\u63A5\n * - at: \"@\u6635\u79F0 \" \u6216 \"@qq \" (\u6709 name \u4F18\u5148 name)\n * - \u5176\u5B83: [\u56FE\u7247]/[\u8868\u60C5]/[\u56DE\u590D]/[\u8F6C\u53D1]/[\u8BED\u97F3]/[\u89C6\u9891]/[\u6587\u4EF6]\n * - \u672A\u77E5\u6BB5: \u8DF3\u8FC7\n */\nexport function extractText(message: OneBotGroupMessageEvent[\"message\"]): string {\n if (typeof message === \"string\") return message;\n if (!Array.isArray(message)) return \"\";\n const parts: string[] = [];\n for (const seg of message) {\n if (!seg || typeof seg !== \"object\") continue;\n if (isTextSegment(seg)) {\n const text = seg.data.text;\n if (typeof text === \"string\") parts.push(text);\n } else if (isAtSegment(seg)) {\n const name = seg.data.name ? `@${seg.data.name} ` : `@${seg.data.qq ?? \"?\"} `;\n parts.push(name);\n } else if (isImageSegment(seg)) {\n parts.push(\"[\u56FE\u7247]\");\n } else if (isFaceSegment(seg)) {\n parts.push(\"[\u8868\u60C5]\");\n } else if (isReplySegment(seg)) {\n parts.push(\"[\u56DE\u590D]\");\n } else if (isForwardSegment(seg)) {\n parts.push(\"[\u8F6C\u53D1]\");\n } else if (isRecordSegment(seg)) {\n parts.push(\"[\u8BED\u97F3]\");\n } else if (isVideoSegment(seg)) {\n parts.push(\"[\u89C6\u9891]\");\n } else if (isFileSegment(seg)) {\n parts.push(\"[\u6587\u4EF6]\");\n }\n // \u672A\u77E5\u6BB5:\u8DF3\u8FC7\n }\n return parts.join(\"\").trim();\n}\n\n// \u2500\u2500 \u77ED\u671F message_id \u53BB\u91CD (\u61D2\u6E05\u7406) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst DEDUP_WINDOW_MS = 5_000;\nconst CLEANUP_INTERVAL_MS = 1_000;\n\nexport class RecentMessageDedup {\n private readonly map = new Map<string, number>();\n private lastCleanup = 0;\n\n seen(messageId: string | number | undefined): boolean {\n if (messageId === undefined || messageId === null) return false;\n const key = String(messageId);\n const now = Date.now();\n if (now - this.lastCleanup > CLEANUP_INTERVAL_MS) {\n this.lastCleanup = now;\n for (const [k, ts] of this.map) {\n if (now - ts > DEDUP_WINDOW_MS) this.map.delete(k);\n }\n }\n const prev = this.map.get(key);\n if (prev !== undefined && now - prev < DEDUP_WINDOW_MS) return true;\n this.map.set(key, now);\n return false;\n }\n}\n\n// \u2500\u2500 OneBot \u4E8B\u4EF6\u5206\u53D1\u5668 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface DispatcherOptions {\n /** \u7FA4 ID \u5B57\u7B26\u4E32,\u7A7A = \u63A5\u6536\u6240\u6709\u7FA4(\u65E7\u884C\u4E3A:\u7A7A\u65F6\u4E0D\u5339\u914D\u4EFB\u4F55\u7FA4,\u4E0D\u4F1A\u89E6\u53D1) */\n qqGroupId: string;\n /** db-server \u8FDE\u63A5\u3002\u5165\u7AD9\u9891\u9053\u7531\u6D88\u606F\u6765\u6E90\u4E3A QQ \u7684\u6E38\u620F\u9891\u9053\u51B3\u5B9A\u3002 */\n db: DBServerConfig;\n /** QQ \u4FA7\u6307\u4EE4\u8DEF\u7531\uFF1B\u547D\u4E2D\u5219\u4E0D\u8F6C\u53D1 MC */\n commandRouter?: CommandRouter;\n /** \u53EF\u6CE8\u5165\u8F6C\u53D1\uFF08\u5355\u6D4B\uFF09 */\n forward?: typeof tryForward;\n}\n\nexport class OneBotDispatcher {\n private botSelfId: string | null = null;\n private readonly opts: DispatcherOptions;\n private readonly dedup = new RecentMessageDedup();\n private readonly forward: typeof tryForward;\n\n constructor(opts: DispatcherOptions) {\n this.opts = opts;\n this.forward = opts.forward ?? tryForward;\n }\n\n /** \u6D4B\u8BD5/\u8C03\u8BD5\u7528 */\n get selfId(): string | null {\n return this.botSelfId;\n }\n\n /** \u6536\u5230\u4E00\u6761\u539F\u59CB JSON \u5B57\u7B26\u4E32(\u5DF2 parse) */\n async handle(rawEvent: unknown): Promise<void> {\n const event = rawEvent as OneBotEvent;\n if (!event || typeof event !== \"object\") return;\n\n if (isLifecycleEvent(event)) {\n if (event.self_id !== undefined && this.botSelfId === null) {\n this.botSelfId = String(event.self_id);\n log.info(`LLBot self_id = ${this.botSelfId}`);\n }\n return;\n }\n\n if (!isGroupMessageEvent(event)) return;\n if (!this.opts.qqGroupId || String(event.group_id) !== this.opts.qqGroupId) return;\n\n // \u5FAA\u73AF\u9632\u62A4 1: \u8DF3\u8FC7 bot \u81EA\u5DF1\u53D1\u7684\u6D88\u606F\u56DE\u58F0\n if (this.botSelfId && String(event.sender?.user_id) === this.botSelfId) return;\n\n // \u5FAA\u73AF\u9632\u62A4 2: \u77ED\u671F\u53BB\u91CD (LLBot \u5076\u53D1\u91CD\u53D1)\n if (this.dedup.seen(event.message_id)) return;\n\n const text = extractText(event.message);\n if (!text) return;\n\n const senderCard = event.sender?.card;\n const senderNick = event.sender?.nickname;\n const fromName = senderCard || senderNick || `QQ_${event.user_id}`;\n const userId = String(event.user_id);\n const fromId = `qq_${userId}`;\n const groupId = String(event.group_id);\n\n if (this.opts.commandRouter) {\n const role = String(event.sender?.role ?? \"\").toLowerCase();\n const isGroupAdmin = role === \"owner\" || role === \"admin\";\n const inbound = {\n backend: \"llbot\" as const,\n groupId,\n userId,\n userName: fromName,\n text,\n isGroupAdmin,\n ...(event.message_id !== undefined ? { msgId: String(event.message_id) } : {}),\n };\n if (await this.opts.commandRouter.handle(inbound)) return;\n }\n\n await this.forward(this.opts.db, fromId, fromName, text);\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sfmc-bds/qq-bridge",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "SFMC QQ ↔ MC bridge — official QQ Open Platform Bot and/or LLBot OneBot 11",
|
|
5
5
|
"author": "Shiroha7z",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"ws": "^8.21.1",
|
|
36
|
-
"@sfmc-bds/sdk": "0.2.
|
|
36
|
+
"@sfmc-bds/sdk": "0.2.2"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@sfmc-bds/tools": "0.2.
|
|
39
|
+
"@sfmc-bds/tools": "0.2.2"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public",
|