@sfmc-bds/qq-bridge 0.1.0 → 0.1.1-beta.3
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/README.md +1 -1
- package/dist/config.js +49 -53
- package/dist/config.js.map +7 -1
- package/dist/console.js +59 -65
- package/dist/console.js.map +7 -1
- package/dist/dbserver.js +65 -76
- package/dist/dbserver.js.map +7 -1
- package/dist/index.js +30 -47
- package/dist/index.js.map +7 -1
- package/dist/log.js +10 -14
- package/dist/log.js.map +7 -1
- package/dist/onebot.js +100 -141
- package/dist/onebot.js.map +7 -1
- package/dist/project-root.js +9 -0
- package/dist/project-root.js.map +7 -0
- package/dist/types.js +1 -8
- package/dist/types.js.map +7 -1
- package/dist/ws-server.js +35 -48
- package/dist/ws-server.js.map +7 -1
- package/package.json +15 -15
- package/dist/config.d.ts +0 -20
- package/dist/config.d.ts.map +0 -1
- package/dist/console.d.ts +0 -22
- package/dist/console.d.ts.map +0 -1
- package/dist/dbserver.d.ts +0 -19
- package/dist/dbserver.d.ts.map +0 -1
- package/dist/index.d.ts +0 -20
- package/dist/index.d.ts.map +0 -1
- package/dist/log.d.ts +0 -11
- package/dist/log.d.ts.map +0 -1
- package/dist/onebot.d.ts +0 -44
- package/dist/onebot.d.ts.map +0 -1
- package/dist/types.d.ts +0 -124
- package/dist/types.d.ts.map +0 -1
- package/dist/ws-server.d.ts +0 -20
- package/dist/ws-server.d.ts.map +0 -1
package/README.md
CHANGED
package/dist/config.js
CHANGED
|
@@ -1,60 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* - reload 时仅覆盖原对象 (mutate), 保留运行时引用的同一份对象
|
|
8
|
-
*/
|
|
9
|
-
import { configPath, readJson, resolveRuntimeRoot } from "@sfmc-bds/sdk/node/config";
|
|
10
|
-
import { dirname, resolve } from "node:path";
|
|
11
|
-
import { fileURLToPath } from "node:url";
|
|
1
|
+
import {
|
|
2
|
+
configPath,
|
|
3
|
+
DEFAULT_QQ_CONFIG,
|
|
4
|
+
loadEnsuredConfig,
|
|
5
|
+
stripConfigMeta
|
|
6
|
+
} from "@sfmc-bds/sdk/node/config";
|
|
12
7
|
import { log } from "./log.js";
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
export const ROOT_DIR = resolveRuntimeRoot(resolve(__dirname, "..", ".."));
|
|
17
|
-
export const CFG_PATH = configPath(ROOT_DIR, "qq_config.json");
|
|
8
|
+
import { PROJECT_ROOT } from "./project-root.js";
|
|
9
|
+
const ROOT_DIR = PROJECT_ROOT;
|
|
10
|
+
const CFG_PATH = configPath(ROOT_DIR, "qq_config.json");
|
|
18
11
|
function applyDefaults(raw) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
12
|
+
const merged = { ...DEFAULT_QQ_CONFIG, ...raw };
|
|
13
|
+
const stripped = stripConfigMeta(merged);
|
|
14
|
+
return {
|
|
15
|
+
qq_enabled: stripped.qq_enabled !== false,
|
|
16
|
+
qq_ws_port: parseInt(String(stripped.qq_ws_port ?? DEFAULT_QQ_CONFIG.qq_ws_port ?? 3002), 10),
|
|
17
|
+
qq_group_id: String(stripped.qq_group_id ?? DEFAULT_QQ_CONFIG.qq_group_id ?? "0"),
|
|
18
|
+
bridge_channel_id: String(stripped.bridge_channel_id ?? DEFAULT_QQ_CONFIG.bridge_channel_id ?? ""),
|
|
19
|
+
db_host: String(stripped.db_host ?? "127.0.0.1"),
|
|
20
|
+
db_port: parseInt(String(stripped.db_port ?? "3001"), 10),
|
|
21
|
+
mctoqq_prefix: String(stripped.mctoqq_prefix ?? DEFAULT_QQ_CONFIG.mctoqq_prefix ?? "[MC]"),
|
|
22
|
+
...stripped
|
|
23
|
+
};
|
|
29
24
|
}
|
|
30
25
|
function readFromDisk() {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
const raw = loadEnsuredConfig(
|
|
27
|
+
ROOT_DIR,
|
|
28
|
+
"qq_config.json",
|
|
29
|
+
"qq_config",
|
|
30
|
+
{ ...DEFAULT_QQ_CONFIG }
|
|
31
|
+
);
|
|
32
|
+
return applyDefaults(raw);
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
34
|
+
function loadInitialConfig() {
|
|
35
|
+
try {
|
|
36
|
+
return readFromDisk();
|
|
37
|
+
} catch (e) {
|
|
38
|
+
log.error(`\u65E0\u6CD5\u8BFB\u53D6\u914D\u7F6E: ${CFG_PATH}: ${e.message}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
45
41
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Object.assign(cfg, fresh);
|
|
54
|
-
}
|
|
55
|
-
catch (e) {
|
|
56
|
-
// reload 失败不抛,旧实现也是只 log
|
|
57
|
-
log.error(`重载配置失败: ${e.message}`);
|
|
58
|
-
}
|
|
42
|
+
function reloadInto(cfg) {
|
|
43
|
+
try {
|
|
44
|
+
const fresh = readFromDisk();
|
|
45
|
+
Object.assign(cfg, fresh);
|
|
46
|
+
} catch (e) {
|
|
47
|
+
log.error(`\u91CD\u8F7D\u914D\u7F6E\u5931\u8D25: ${e.message}`);
|
|
48
|
+
}
|
|
59
49
|
}
|
|
60
|
-
|
|
50
|
+
export {
|
|
51
|
+
CFG_PATH,
|
|
52
|
+
ROOT_DIR,
|
|
53
|
+
loadInitialConfig,
|
|
54
|
+
reloadInto
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/config.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * config.ts \u2014 \u52A0\u8F7D configs/qq_config.json\n *\n * \u884C\u4E3A\u4E0E\u65E7 index.js \u4FDD\u6301\u5B8C\u5168\u4E00\u81F4:\n * - \u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u89E3\u6790\u5931\u8D25: \u8FDB\u7A0B\u9000\u51FA (\u65E7\u7248 process.exit(1))\n * - \u5B57\u6BB5\u7F3A\u5931: \u8D70\u9ED8\u8BA4\u503C\n * - reload \u65F6\u4EC5\u8986\u76D6\u539F\u5BF9\u8C61 (mutate), \u4FDD\u7559\u8FD0\u884C\u65F6\u5F15\u7528\u7684\u540C\u4E00\u4EFD\u5BF9\u8C61\n */\n\nimport {\n configPath,\n DEFAULT_QQ_CONFIG,\n loadEnsuredConfig,\n stripConfigMeta,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { log } from \"./log.js\";\nimport { PROJECT_ROOT } from \"./project-root.js\";\nimport type { QQBridgeConfig } from \"./types.js\";\n\n/** \u7EDF\u4E00\u901A\u8FC7 SDK \u89E3\u6790\u9879\u76EE\u6839:env SFMC_ROOT > project-root \u4E0A\u6EAF\u3002 */\nexport const ROOT_DIR: string = PROJECT_ROOT;\nexport const CFG_PATH: string = configPath(ROOT_DIR, \"qq_config.json\");\n\nfunction applyDefaults(raw: Partial<QQBridgeConfig>): QQBridgeConfig {\n /* \u4EE5 SDK DEFAULT_QQ_CONFIG \u4E3A\u552F\u4E00\u7F3A\u7701\u6743\u5A01\uFF08DRY/LSP\uFF09\uFF0C\u518D\u53E0\u8FD0\u884C\u65F6\u6D3E\u751F\u5B57\u6BB5 */\n const merged = { ...DEFAULT_QQ_CONFIG, ...raw } as Partial<QQBridgeConfig> & Record<string, unknown>;\n const stripped = stripConfigMeta(merged);\n return {\n qq_enabled: stripped.qq_enabled !== false,\n qq_ws_port: parseInt(String(stripped.qq_ws_port ?? DEFAULT_QQ_CONFIG.qq_ws_port ?? 3002), 10),\n qq_group_id: String(stripped.qq_group_id ?? DEFAULT_QQ_CONFIG.qq_group_id ?? \"0\"),\n bridge_channel_id: String(stripped.bridge_channel_id ?? DEFAULT_QQ_CONFIG.bridge_channel_id ?? \"\"),\n db_host: String(stripped.db_host ?? \"127.0.0.1\"),\n db_port: parseInt(String(stripped.db_port ?? \"3001\"), 10),\n mctoqq_prefix: String(stripped.mctoqq_prefix ?? DEFAULT_QQ_CONFIG.mctoqq_prefix ?? \"[MC]\"),\n ...stripped,\n };\n}\n\nfunction readFromDisk(): QQBridgeConfig {\n const raw = loadEnsuredConfig(\n ROOT_DIR,\n \"qq_config.json\",\n \"qq_config\",\n { ...DEFAULT_QQ_CONFIG } as Record<string, unknown>\n );\n return applyDefaults(raw as Partial<QQBridgeConfig>);\n}\n\n/** \u8FDB\u7A0B\u542F\u52A8\u65F6\u52A0\u8F7D\u4E00\u6B21\u3002\u5931\u8D25\u76F4\u63A5\u9000\u51FA,\u4E0E\u65E7\u5B9E\u73B0\u4E00\u81F4\u3002 */\nexport function loadInitialConfig(): QQBridgeConfig {\n try {\n return readFromDisk();\n } catch (e) {\n log.error(`\u65E0\u6CD5\u8BFB\u53D6\u914D\u7F6E: ${CFG_PATH}: ${(e as Error).message}`);\n process.exit(1);\n }\n}\n\n/**\n * \u91CD\u65B0\u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6,\u5408\u5E76\u5230\u4F20\u5165\u5BF9\u8C61\u4E0A (mutate)\u3002\n * \u65E7\u5B9E\u73B0\u662F Object.assign(cfg, newCfg),\u4FDD\u7559\u8FD0\u884C\u65F6\u5BF9\u539F cfg \u5BF9\u8C61\u7684\u5F15\u7528 \u2014 \u540C\u6837\u884C\u4E3A\u3002\n */\nexport function reloadInto(cfg: QQBridgeConfig): void {\n try {\n const fresh = readFromDisk();\n Object.assign(cfg, fresh);\n } catch (e) {\n // reload \u5931\u8D25\u4E0D\u629B,\u65E7\u5B9E\u73B0\u4E5F\u662F\u53EA log\n log.error(`\u91CD\u8F7D\u914D\u7F6E\u5931\u8D25: ${(e as Error).message}`);\n }\n}\n"],
|
|
5
|
+
"mappings": "AASA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW;AACpB,SAAS,oBAAoB;AAItB,MAAM,WAAmB;AACzB,MAAM,WAAmB,WAAW,UAAU,gBAAgB;AAErE,SAAS,cAAc,KAA8C;AAEnE,QAAM,SAAS,EAAE,GAAG,mBAAmB,GAAG,IAAI;AAC9C,QAAM,WAAW,gBAAgB,MAAM;AACvC,SAAO;AAAA,IACL,YAAY,SAAS,eAAe;AAAA,IACpC,YAAY,SAAS,OAAO,SAAS,cAAc,kBAAkB,cAAc,IAAI,GAAG,EAAE;AAAA,IAC5F,aAAa,OAAO,SAAS,eAAe,kBAAkB,eAAe,GAAG;AAAA,IAChF,mBAAmB,OAAO,SAAS,qBAAqB,kBAAkB,qBAAqB,EAAE;AAAA,IACjG,SAAS,OAAO,SAAS,WAAW,WAAW;AAAA,IAC/C,SAAS,SAAS,OAAO,SAAS,WAAW,MAAM,GAAG,EAAE;AAAA,IACxD,eAAe,OAAO,SAAS,iBAAiB,kBAAkB,iBAAiB,MAAM;AAAA,IACzF,GAAG;AAAA,EACL;AACF;AAEA,SAAS,eAA+B;AACtC,QAAM,MAAM;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,GAAG,kBAAkB;AAAA,EACzB;AACA,SAAO,cAAc,GAA8B;AACrD;AAGO,SAAS,oBAAoC;AAClD,MAAI;AACF,WAAO,aAAa;AAAA,EACtB,SAAS,GAAG;AACV,QAAI,MAAM,yCAAW,QAAQ,KAAM,EAAY,OAAO,EAAE;AACxD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAMO,SAAS,WAAW,KAA2B;AACpD,MAAI;AACF,UAAM,QAAQ,aAAa;AAC3B,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B,SAAS,GAAG;AAEV,QAAI,MAAM,yCAAY,EAAY,OAAO,EAAE;AAAA,EAC7C;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/console.js
CHANGED
|
@@ -1,76 +1,70 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* console.ts — 交互式控制台 (readline)
|
|
3
|
-
*
|
|
4
|
-
* 命令:
|
|
5
|
-
* help 显示帮助
|
|
6
|
-
* reload 重新读取 configs/qq_config.json
|
|
7
|
-
* status 显示当前状态
|
|
8
|
-
* stop 退出进程
|
|
9
|
-
*
|
|
10
|
-
* 行为与旧实现完全一致。
|
|
11
|
-
*/
|
|
12
1
|
import { createInterface } from "node:readline";
|
|
13
2
|
import { log } from "./log.js";
|
|
14
3
|
import { reloadInto } from "./config.js";
|
|
15
4
|
function showHelp() {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
console.log("\u53EF\u7528\u547D\u4EE4:");
|
|
6
|
+
console.log(" help \u2014 \u663E\u793A\u672C\u5E2E\u52A9");
|
|
7
|
+
console.log(" reload \u2014 \u91CD\u65B0\u8BFB\u53D6 qq_config.json");
|
|
8
|
+
console.log(" status \u2014 \u663E\u793A\u5F53\u524D\u72B6\u6001");
|
|
9
|
+
console.log(" stop \u2014 \u505C\u6B62\u670D\u52A1");
|
|
21
10
|
}
|
|
22
11
|
function showStatus(opts) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
12
|
+
const { config: cfg, initialEnabled, wsPort, botSelfIdRef } = opts;
|
|
13
|
+
console.log("=== QQBridge \u72B6\u6001 ===");
|
|
14
|
+
console.log(` \u542F\u7528: ${initialEnabled}`);
|
|
15
|
+
console.log(` WS \u7AEF\u53E3: ${wsPort}`);
|
|
16
|
+
console.log(` LLBot HTTP: (db-server \u76F4\u8FDE,\u4E0D\u7ECF\u8FC7\u672C\u8FDB\u7A0B)`);
|
|
17
|
+
console.log(` QQ \u7FA4: ${cfg.qq_group_id || "\u672A\u914D\u7F6E"}`);
|
|
18
|
+
console.log(` Channel: ${cfg.bridge_channel_id || "\u672A\u914D\u7F6E"}`);
|
|
19
|
+
console.log(` db-server: ${cfg.db_host}:${cfg.db_port}`);
|
|
20
|
+
console.log(` Bot self_id: ${botSelfIdRef.value || "\u672A\u6355\u83B7"}`);
|
|
21
|
+
console.log(` MC\u2192QQ \u524D\u7F00: ${cfg.mctoqq_prefix}`);
|
|
33
22
|
}
|
|
34
23
|
function handleCommand(line, opts, rl) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
case "status":
|
|
54
|
-
showStatus(opts);
|
|
55
|
-
return false;
|
|
56
|
-
case "stop":
|
|
57
|
-
case "exit":
|
|
58
|
-
case "quit":
|
|
59
|
-
log.info("正在停止...");
|
|
60
|
-
rl.close();
|
|
61
|
-
process.exit(0);
|
|
62
|
-
return true; // 不可达,但满足 noImplicitReturns
|
|
63
|
-
case "":
|
|
64
|
-
return false;
|
|
65
|
-
default:
|
|
66
|
-
log.info(`未知命令: ${cmd} (输入 help 查看帮助)`);
|
|
67
|
-
return false;
|
|
24
|
+
const cmd = line.trim().toLowerCase();
|
|
25
|
+
switch (cmd) {
|
|
26
|
+
case "help":
|
|
27
|
+
showHelp();
|
|
28
|
+
return false;
|
|
29
|
+
case "reload": {
|
|
30
|
+
const before = {
|
|
31
|
+
qq_group_id: opts.config.qq_group_id,
|
|
32
|
+
bridge_channel_id: opts.config.bridge_channel_id,
|
|
33
|
+
db_host: opts.config.db_host,
|
|
34
|
+
db_port: opts.config.db_port
|
|
35
|
+
};
|
|
36
|
+
reloadInto(opts.config);
|
|
37
|
+
log.info(
|
|
38
|
+
`\u914D\u7F6E\u5DF2\u91CD\u8F7D (qq_group_id=${opts.config.qq_group_id}, channel=${opts.config.bridge_channel_id}, db=${opts.config.db_host}:${opts.config.db_port})`
|
|
39
|
+
);
|
|
40
|
+
void before;
|
|
41
|
+
return false;
|
|
68
42
|
}
|
|
43
|
+
case "status":
|
|
44
|
+
showStatus(opts);
|
|
45
|
+
return false;
|
|
46
|
+
case "stop":
|
|
47
|
+
case "exit":
|
|
48
|
+
case "quit":
|
|
49
|
+
log.info("\u6B63\u5728\u505C\u6B62...");
|
|
50
|
+
rl.close();
|
|
51
|
+
process.exit(0);
|
|
52
|
+
return true;
|
|
53
|
+
// 不可达,但满足 noImplicitReturns
|
|
54
|
+
case "":
|
|
55
|
+
return false;
|
|
56
|
+
default:
|
|
57
|
+
log.info(`\u672A\u77E5\u547D\u4EE4: ${cmd} (\u8F93\u5165 help \u67E5\u770B\u5E2E\u52A9)`);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
69
60
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
function startConsole(opts) {
|
|
62
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
63
|
+
rl.on("line", (line) => {
|
|
64
|
+
handleCommand(line, opts, rl);
|
|
65
|
+
});
|
|
75
66
|
}
|
|
76
|
-
|
|
67
|
+
export {
|
|
68
|
+
startConsole
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=console.js.map
|
package/dist/console.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 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 * stop \u9000\u51FA\u8FDB\u7A0B\n *\n * \u884C\u4E3A\u4E0E\u65E7\u5B9E\u73B0\u5B8C\u5168\u4E00\u81F4\u3002\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}\n\nfunction showHelp(): 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 console.log(\" stop \u2014 \u505C\u6B62\u670D\u52A1\");\n}\n\nfunction showStatus(opts: ConsoleOptions): void {\n const { config: cfg, initialEnabled, wsPort, botSelfIdRef } = opts;\n console.log(\"=== QQBridge \u72B6\u6001 ===\");\n console.log(` \u542F\u7528: ${initialEnabled}`);\n console.log(` WS \u7AEF\u53E3: ${wsPort}`);\n console.log(` LLBot HTTP: (db-server \u76F4\u8FDE,\u4E0D\u7ECF\u8FC7\u672C\u8FDB\u7A0B)`);\n console.log(` QQ \u7FA4: ${cfg.qq_group_id || \"\u672A\u914D\u7F6E\"}`);\n console.log(` Channel: ${cfg.bridge_channel_id || \"\u672A\u914D\u7F6E\"}`);\n console.log(` db-server: ${cfg.db_host}:${cfg.db_port}`);\n console.log(` Bot self_id: ${botSelfIdRef.value || \"\u672A\u6355\u83B7\"}`);\n console.log(` MC\u2192QQ \u524D\u7F00: ${cfg.mctoqq_prefix}`);\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();\n return false;\n case \"reload\": {\n const before = {\n qq_group_id: opts.config.qq_group_id,\n bridge_channel_id: opts.config.bridge_channel_id,\n db_host: opts.config.db_host,\n db_port: opts.config.db_port,\n };\n reloadInto(opts.config);\n log.info(\n `\u914D\u7F6E\u5DF2\u91CD\u8F7D (qq_group_id=${opts.config.qq_group_id}, channel=${opts.config.bridge_channel_id}, db=${opts.config.db_host}:${opts.config.db_port})`\n );\n // \u9759\u9ED8\u6D88\u8D39\u672A\u4F7F\u7528\u53D8\u91CF\u8B66\u544A\n void before;\n return false;\n }\n case \"status\":\n showStatus(opts);\n return false;\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; // \u4E0D\u53EF\u8FBE,\u4F46\u6EE1\u8DB3 noImplicitReturns\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": "AAYA,SAAS,uBAAsD;AAC/D,SAAS,WAAW;AACpB,SAAS,kBAAkB;AAU3B,SAAS,WAAiB;AACxB,UAAQ,IAAI,2BAAO;AACnB,UAAQ,IAAI,iDAAmB;AAC/B,UAAQ,IAAI,0DAAiC;AAC7C,UAAQ,IAAI,uDAAoB;AAChC,UAAQ,IAAI,2CAAkB;AAChC;AAEA,SAAS,WAAW,MAA4B;AAC9C,QAAM,EAAE,QAAQ,KAAK,gBAAgB,QAAQ,aAAa,IAAI;AAC9D,UAAQ,IAAI,+BAAqB;AACjC,UAAQ,IAAI,0BAAgB,cAAc,EAAE;AAC5C,UAAQ,IAAI,0BAAgB,MAAM,EAAE;AACpC,UAAQ,IAAI,8EAAsC;AAClD,UAAQ,IAAI,sBAAiB,IAAI,eAAe,oBAAK,EAAE;AACvD,UAAQ,IAAI,kBAAkB,IAAI,qBAAqB,oBAAK,EAAE;AAC9D,UAAQ,IAAI,kBAAkB,IAAI,OAAO,IAAI,IAAI,OAAO,EAAE;AAC1D,UAAQ,IAAI,kBAAkB,aAAa,SAAS,oBAAK,EAAE;AAC3D,UAAQ,IAAI,+BAAgB,IAAI,aAAa,EAAE;AACjD;AAEA,SAAS,cAAc,MAAc,MAAsB,IAA0B;AACnF,QAAM,MAAM,KAAK,KAAK,EAAE,YAAY;AACpC,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,eAAS;AACT,aAAO;AAAA,IACT,KAAK,UAAU;AACb,YAAM,SAAS;AAAA,QACb,aAAa,KAAK,OAAO;AAAA,QACzB,mBAAmB,KAAK,OAAO;AAAA,QAC/B,SAAS,KAAK,OAAO;AAAA,QACrB,SAAS,KAAK,OAAO;AAAA,MACvB;AACA,iBAAW,KAAK,MAAM;AACtB,UAAI;AAAA,QACF,+CAAsB,KAAK,OAAO,WAAW,aAAa,KAAK,OAAO,iBAAiB,QAAQ,KAAK,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO;AAAA,MAC3I;AAEA,WAAK;AACL,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,iBAAW,IAAI;AACf,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,UAAI,KAAK,6BAAS;AAClB,SAAG,MAAM;AACT,cAAQ,KAAK,CAAC;AACd,aAAO;AAAA;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
|
+
"names": []
|
|
7
|
+
}
|
package/dist/dbserver.js
CHANGED
|
@@ -1,83 +1,72 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* dbserver.ts — 转发 OneBot 群消息到 db-server /api/sfmc/messages
|
|
3
|
-
*
|
|
4
|
-
* 与旧实现保持行为一致: 仅 POST 200 视为成功,否则抛错; 失败不重试 (主流程不阻塞)。
|
|
5
|
-
* 超时: 与 db-server 内部 HTTP 风格一致,使用 req.on("timeout") + req.destroy。
|
|
6
|
-
*/
|
|
7
1
|
import { request as httpRequest } from "node:http";
|
|
8
2
|
import { log } from "./log.js";
|
|
9
|
-
const REQUEST_TIMEOUT_MS =
|
|
3
|
+
const REQUEST_TIMEOUT_MS = 5e3;
|
|
10
4
|
function postJSON(url, body, timeoutMs) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
reject(new Error(`db-server ${code}: ${buf.slice(0, 200)}`));
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
req.on("timeout", () => {
|
|
47
|
-
req.destroy(new Error(`db-server 超时 ${timeoutMs}ms`));
|
|
48
|
-
});
|
|
49
|
-
req.on("error", reject);
|
|
50
|
-
req.write(payload);
|
|
51
|
-
req.end();
|
|
5
|
+
const payload = JSON.stringify(body);
|
|
6
|
+
const options = {
|
|
7
|
+
hostname: url.hostname,
|
|
8
|
+
port: url.port || "3001",
|
|
9
|
+
path: url.pathname,
|
|
10
|
+
method: "POST",
|
|
11
|
+
headers: {
|
|
12
|
+
"Content-Type": "application/json",
|
|
13
|
+
"Content-Length": Buffer.byteLength(payload)
|
|
14
|
+
},
|
|
15
|
+
timeout: timeoutMs
|
|
16
|
+
};
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const req = httpRequest(options, (res) => {
|
|
19
|
+
let buf = "";
|
|
20
|
+
res.setEncoding("utf-8");
|
|
21
|
+
res.on("data", (chunk) => {
|
|
22
|
+
buf += chunk;
|
|
23
|
+
});
|
|
24
|
+
res.on("end", () => {
|
|
25
|
+
const code = res.statusCode ?? 0;
|
|
26
|
+
if (code >= 200 && code < 300) {
|
|
27
|
+
try {
|
|
28
|
+
resolve(JSON.parse(buf));
|
|
29
|
+
} catch {
|
|
30
|
+
resolve(buf);
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
reject(new Error(`db-server ${code}: ${buf.slice(0, 200)}`));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
52
36
|
});
|
|
37
|
+
req.on("timeout", () => {
|
|
38
|
+
req.destroy(new Error(`db-server \u8D85\u65F6 ${timeoutMs}ms`));
|
|
39
|
+
});
|
|
40
|
+
req.on("error", reject);
|
|
41
|
+
req.write(payload);
|
|
42
|
+
req.end();
|
|
43
|
+
});
|
|
53
44
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
};
|
|
69
|
-
const body = { messages: [message] };
|
|
70
|
-
const url = new URL(`http://${cfg.host}:${cfg.port}/api/sfmc/messages`);
|
|
71
|
-
await postJSON(url, body, REQUEST_TIMEOUT_MS);
|
|
45
|
+
async function forwardGroupMessage(cfg, fromId, fromName, content, now = Date.now()) {
|
|
46
|
+
const message = {
|
|
47
|
+
id: `${fromId}_${now}`,
|
|
48
|
+
channelId: cfg.channelId,
|
|
49
|
+
fromid: fromId,
|
|
50
|
+
fromName,
|
|
51
|
+
type: "text",
|
|
52
|
+
content,
|
|
53
|
+
showTimestamp: true,
|
|
54
|
+
timestamp: now
|
|
55
|
+
};
|
|
56
|
+
const body = { messages: [message] };
|
|
57
|
+
const url = new URL(`http://${cfg.host}:${cfg.port}/api/sfmc/messages`);
|
|
58
|
+
await postJSON(url, body, REQUEST_TIMEOUT_MS);
|
|
72
59
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
log.error(`转发到 db-server 失败: ${e.message}`);
|
|
81
|
-
}
|
|
60
|
+
async function tryForward(cfg, fromId, fromName, content) {
|
|
61
|
+
try {
|
|
62
|
+
await forwardGroupMessage(cfg, fromId, fromName, content);
|
|
63
|
+
log.info(`QQ \u2192 MC: ${fromName}: ${content.slice(0, 60)}`);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
log.error(`\u8F6C\u53D1\u5230 db-server \u5931\u8D25: ${e.message}`);
|
|
66
|
+
}
|
|
82
67
|
}
|
|
83
|
-
|
|
68
|
+
export {
|
|
69
|
+
forwardGroupMessage,
|
|
70
|
+
tryForward
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=dbserver.js.map
|
package/dist/dbserver.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/dbserver.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * dbserver.ts \u2014 \u8F6C\u53D1 OneBot \u7FA4\u6D88\u606F\u5230 db-server /api/sfmc/messages\n *\n * \u4E0E\u65E7\u5B9E\u73B0\u4FDD\u6301\u884C\u4E3A\u4E00\u81F4: \u4EC5 POST 200 \u89C6\u4E3A\u6210\u529F,\u5426\u5219\u629B\u9519; \u5931\u8D25\u4E0D\u91CD\u8BD5 (\u4E3B\u6D41\u7A0B\u4E0D\u963B\u585E)\u3002\n * \u8D85\u65F6: \u4E0E db-server \u5185\u90E8 HTTP \u98CE\u683C\u4E00\u81F4,\u4F7F\u7528 req.on(\"timeout\") + req.destroy\u3002\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: 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: \u4ECD\u89C6\u4E3A\u6210\u529F,\u4F5C\u4E3A void \u629B\u51FA\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\u4E00\u6761 IncomingChatMessage \u5E76 POST \u5230 db-server\u3002\n * fromid \u5F62\u5982 `qq_<user_id>`,\u4E0E\u65E7\u5B9E\u73B0\u4FDD\u6301\u5B8C\u5168\u4E00\u81F4\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<void> {\n const message: IncomingChatMessage = {\n id: `${fromId}_${now}`,\n channelId: cfg.channelId,\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 await postJSON<unknown>(url, body, REQUEST_TIMEOUT_MS);\n}\n\n/** \u5305\u88C5 try/catch,\u5931\u8D25\u4EC5 log (\u4E0E\u65E7\u5B9E\u73B0\u4E00\u81F4,\u4E0D\u629B\u7ED9\u4E3B\u5FAA\u73AF)\u3002 */\nexport async function tryForward(\n cfg: DBServerConfig,\n fromId: string,\n fromName: string,\n content: string\n): Promise<void> {\n try {\n await forwardGroupMessage(cfg, fromId, fromName, content);\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"],
|
|
5
|
+
"mappings": "AAOA,SAAS,WAAW,mBAAwC;AAC5D,SAAS,WAAW;AASpB,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;AAMA,eAAsB,oBACpB,KACA,QACA,UACA,SACA,MAAc,KAAK,IAAI,GACR;AACf,QAAM,UAA+B;AAAA,IACnC,IAAI,GAAG,MAAM,IAAI,GAAG;AAAA,IACpB,WAAW,IAAI;AAAA,IACf,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,QAAM,SAAkB,KAAK,MAAM,kBAAkB;AACvD;AAGA,eAAsB,WACpB,KACA,QACA,UACA,SACe;AACf,MAAI;AACF,UAAM,oBAAoB,KAAK,QAAQ,UAAU,OAAO;AACxD,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
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,58 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* index.ts — QQ ↔ MC 桥接进程入口
|
|
4
|
-
*
|
|
5
|
-
* 端口: 3002 (默认) — WebSocket (LLBot reverse-ws)
|
|
6
|
-
*
|
|
7
|
-
* 数据流:
|
|
8
|
-
* QQ → MC: LLBot ──WS:3002──→ qq-bridge ──POST──→ db-server:3001/api/sfmc/messages
|
|
9
|
-
* MC → QQ: SAPI ──POST──→ db-server:3001 ──(内部)──→ LLBot:3004/send_group_msg
|
|
10
|
-
*
|
|
11
|
-
* 注意: 本进程只做 WS 入口,不再起 HTTP server。MC→QQ 由 db-server 直连 LLBot
|
|
12
|
-
* (见 db-server/src/domain/bridge.ts:forwardToQQBridge)
|
|
13
|
-
*
|
|
14
|
-
* 循环防护:
|
|
15
|
-
* 1. 跳过 sender.user_id === botSelfId 的回声
|
|
16
|
-
* (botSelfId 通过 LLBot 的 lifecycle 元事件捕获)
|
|
17
|
-
* 2. 5 秒内同 message_id 短期去重 (防 race)
|
|
18
|
-
*/
|
|
19
2
|
import { loadInitialConfig } from "./config.js";
|
|
20
3
|
import { OneBotDispatcher } from "./onebot.js";
|
|
21
4
|
import { startWsServer } from "./ws-server.js";
|
|
22
5
|
import { startConsole } from "./console.js";
|
|
23
6
|
import { log } from "./log.js";
|
|
24
7
|
async function main() {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
8
|
+
const cfg = loadInitialConfig();
|
|
9
|
+
if (!cfg.qq_enabled) {
|
|
10
|
+
log.info("\u5DF2\u7981\u7528 (qq_enabled = false)");
|
|
11
|
+
process.exit(0);
|
|
12
|
+
}
|
|
13
|
+
const botSelfIdRef = { value: null };
|
|
14
|
+
const dispatcher = new OneBotDispatcher({
|
|
15
|
+
qqGroupId: cfg.qq_group_id,
|
|
16
|
+
db: {
|
|
17
|
+
host: cfg.db_host,
|
|
18
|
+
port: cfg.db_port,
|
|
19
|
+
channelId: cfg.bridge_channel_id
|
|
29
20
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
log.info(`等待 LLBot 连接 (主群: ${cfg.qq_group_id || "未配置"}, channel: ${cfg.bridge_channel_id || "未配置"}, db: ${cfg.db_host}:${cfg.db_port})`);
|
|
46
|
-
startConsole({
|
|
47
|
-
config: cfg,
|
|
48
|
-
initialEnabled: cfg.qq_enabled,
|
|
49
|
-
wsPort: cfg.qq_ws_port,
|
|
50
|
-
botSelfIdRef,
|
|
51
|
-
});
|
|
52
|
-
log.info("启动完成");
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(botSelfIdRef, "value", {
|
|
23
|
+
get: () => dispatcher.selfId
|
|
24
|
+
});
|
|
25
|
+
await startWsServer({ port: cfg.qq_ws_port, dispatcher });
|
|
26
|
+
log.info(
|
|
27
|
+
`\u7B49\u5F85 LLBot \u8FDE\u63A5 (\u4E3B\u7FA4: ${cfg.qq_group_id || "\u672A\u914D\u7F6E"}, channel: ${cfg.bridge_channel_id || "\u672A\u914D\u7F6E"}, db: ${cfg.db_host}:${cfg.db_port})`
|
|
28
|
+
);
|
|
29
|
+
startConsole({
|
|
30
|
+
config: cfg,
|
|
31
|
+
initialEnabled: cfg.qq_enabled,
|
|
32
|
+
wsPort: cfg.qq_ws_port,
|
|
33
|
+
botSelfIdRef
|
|
34
|
+
});
|
|
35
|
+
log.info("\u542F\u52A8\u5B8C\u6210");
|
|
53
36
|
}
|
|
54
37
|
main().catch((e) => {
|
|
55
|
-
|
|
56
|
-
|
|
38
|
+
log.error(`\u672A\u6355\u83B7\u5F02\u5E38: ${e.message}`);
|
|
39
|
+
process.exit(1);
|
|
57
40
|
});
|
|
58
|
-
//# sourceMappingURL=index.js.map
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 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 * \u7AEF\u53E3: 3002 (\u9ED8\u8BA4) \u2014 WebSocket (LLBot reverse-ws)\n *\n * \u6570\u636E\u6D41:\n * QQ \u2192 MC: LLBot \u2500\u2500WS:3002\u2500\u2500\u2192 qq-bridge \u2500\u2500POST\u2500\u2500\u2192 db-server:3001/api/sfmc/messages\n * MC \u2192 QQ: SAPI \u2500\u2500POST\u2500\u2500\u2192 db-server:3001 \u2500\u2500(\u5185\u90E8)\u2500\u2500\u2192 LLBot:3004/send_group_msg\n *\n * \u6CE8\u610F: \u672C\u8FDB\u7A0B\u53EA\u505A WS \u5165\u53E3,\u4E0D\u518D\u8D77 HTTP server\u3002MC\u2192QQ \u7531 db-server \u76F4\u8FDE LLBot\n * (\u89C1 db-server/src/domain/bridge.ts:forwardToQQBridge)\n *\n * \u5FAA\u73AF\u9632\u62A4:\n * 1. \u8DF3\u8FC7 sender.user_id === botSelfId \u7684\u56DE\u58F0\n * (botSelfId \u901A\u8FC7 LLBot \u7684 lifecycle \u5143\u4E8B\u4EF6\u6355\u83B7)\n * 2. 5 \u79D2\u5185\u540C message_id \u77ED\u671F\u53BB\u91CD (\u9632 race)\n */\n\nimport { loadInitialConfig } from \"./config.js\";\nimport { OneBotDispatcher } from \"./onebot.js\";\nimport { startWsServer } from \"./ws-server.js\";\nimport { startConsole } from \"./console.js\";\nimport { log } from \"./log.js\";\nimport type { QQBridgeConfig } from \"./types.js\";\n\nasync function main(): Promise<void> {\n const cfg: QQBridgeConfig = loadInitialConfig();\n\n if (!cfg.qq_enabled) {\n log.info(\"\u5DF2\u7981\u7528 (qq_enabled = false)\");\n process.exit(0);\n }\n\n // \u8BA9\u63A7\u5236\u53F0 status \u547D\u4EE4\u8BFB\u5230 bot \u5F53\u524D\u7684 self_id\n const botSelfIdRef: { value: string | null } = { value: null };\n\n const dispatcher = new OneBotDispatcher({\n qqGroupId: cfg.qq_group_id,\n db: {\n host: cfg.db_host,\n port: cfg.db_port,\n channelId: cfg.bridge_channel_id,\n },\n });\n\n // botSelfId \u901A\u8FC7 dispatcher \u5185\u90E8\u7EF4\u62A4; \u63A7\u5236\u53F0\u8BFB self_id \u65F6\u53D6\u6700\u65B0\u503C\n Object.defineProperty(botSelfIdRef, \"value\", {\n get: () => dispatcher.selfId,\n });\n\n await startWsServer({ port: cfg.qq_ws_port, dispatcher });\n\n log.info(\n `\u7B49\u5F85 LLBot \u8FDE\u63A5 (\u4E3B\u7FA4: ${cfg.qq_group_id || \"\u672A\u914D\u7F6E\"}, channel: ${cfg.bridge_channel_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 });\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": ";AAmBA,SAAS,yBAAyB;AAClC,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,WAAW;AAGpB,eAAe,OAAsB;AACnC,QAAM,MAAsB,kBAAkB;AAE9C,MAAI,CAAC,IAAI,YAAY;AACnB,QAAI,KAAK,yCAA0B;AACnC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,eAAyC,EAAE,OAAO,KAAK;AAE7D,QAAM,aAAa,IAAI,iBAAiB;AAAA,IACtC,WAAW,IAAI;AAAA,IACf,IAAI;AAAA,MACF,MAAM,IAAI;AAAA,MACV,MAAM,IAAI;AAAA,MACV,WAAW,IAAI;AAAA,IACjB;AAAA,EACF,CAAC;AAGD,SAAO,eAAe,cAAc,SAAS;AAAA,IAC3C,KAAK,MAAM,WAAW;AAAA,EACxB,CAAC;AAED,QAAM,cAAc,EAAE,MAAM,IAAI,YAAY,WAAW,CAAC;AAExD,MAAI;AAAA,IACF,kDAAoB,IAAI,eAAe,oBAAK,cAAc,IAAI,qBAAqB,oBAAK,SAAS,IAAI,OAAO,IAAI,IAAI,OAAO;AAAA,EAC7H;AAEA,eAAa;AAAA,IACX,QAAQ;AAAA,IACR,gBAAgB,IAAI;AAAA,IACpB,QAAQ,IAAI;AAAA,IACZ;AAAA,EACF,CAAC;AAED,MAAI,KAAK,0BAAM;AACjB;AAEA,KAAK,EAAE,MAAM,CAAC,MAAM;AAClB,MAAI,MAAM,mCAAW,EAAY,OAAO,EAAE;AAC1C,UAAQ,KAAK,CAAC;AAChB,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/log.js
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* bare 模式: stdout 只输出纯 text,不加时间戳/source/level 前缀
|
|
8
|
-
* (由 sfmc 的 formatLog 统一添加,避免重复)。error 走 stderr。
|
|
9
|
-
*/
|
|
10
|
-
import { createLogger, createStdoutSink } from "@sfmc-bds/sdk/logs";
|
|
11
|
-
export const log = createLogger({
|
|
12
|
-
source: "qq",
|
|
13
|
-
sinks: [createStdoutSink({ bare: true })],
|
|
1
|
+
import { createNodeServiceLogger } from "@sfmc-bds/sdk/logs";
|
|
2
|
+
import { logFile } from "@sfmc-bds/sdk/node/config";
|
|
3
|
+
import { PROJECT_ROOT } from "./project-root.js";
|
|
4
|
+
const log = createNodeServiceLogger({
|
|
5
|
+
source: "qq",
|
|
6
|
+
logPath: logFile(PROJECT_ROOT, "qq")
|
|
14
7
|
});
|
|
15
|
-
|
|
8
|
+
export {
|
|
9
|
+
log
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=log.js.map
|
package/dist/log.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/log.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * log.ts \u2014 qq-bridge \u7EDF\u4E00\u65E5\u5FD7\u5B9E\u4F8B\n *\n * stdout bare + \u843D\u76D8 `<SFMC_ROOT>/.sfmc/logs/qq.log`\u3002\n * bare: \u53EA\u8F93\u51FA\u7EAF text,\u7531 sfmc \u6355\u83B7\u540E\u7EDF\u4E00\u52A0\u524D\u7F00;error \u8D70 stderr\u3002\n */\n\nimport { createNodeServiceLogger } from \"@sfmc-bds/sdk/logs\";\nimport { logFile } from \"@sfmc-bds/sdk/node/config\";\nimport { PROJECT_ROOT } from \"./project-root.js\";\n\nexport const log = createNodeServiceLogger({\n source: \"qq\",\n logPath: logFile(PROJECT_ROOT, \"qq\"),\n});\n"],
|
|
5
|
+
"mappings": "AAOA,SAAS,+BAA+B;AACxC,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAEtB,MAAM,MAAM,wBAAwB;AAAA,EACzC,QAAQ;AAAA,EACR,SAAS,QAAQ,cAAc,IAAI;AACrC,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|