@sfmc-bds/db-server 0.2.0-beta.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +1 -1
  2. package/dist/domain/bridge.d.ts +1 -5
  3. package/dist/domain/bridge.d.ts.map +1 -1
  4. package/dist/domain/bridge.js +15 -14
  5. package/dist/domain/bridge.js.map +2 -2
  6. package/dist/domain/installed-content.d.ts +84 -0
  7. package/dist/domain/installed-content.d.ts.map +1 -0
  8. package/dist/domain/installed-content.js +149 -0
  9. package/dist/domain/installed-content.js.map +7 -0
  10. package/dist/domain/player-session.d.ts +8 -0
  11. package/dist/domain/player-session.d.ts.map +1 -0
  12. package/dist/domain/player-session.js +16 -0
  13. package/dist/domain/player-session.js.map +7 -0
  14. package/dist/domain/qq-account-profile.d.ts +51 -0
  15. package/dist/domain/qq-account-profile.d.ts.map +1 -0
  16. package/dist/domain/qq-account-profile.js +129 -0
  17. package/dist/domain/qq-account-profile.js.map +7 -0
  18. package/dist/domain/qq-events.d.ts +2 -2
  19. package/dist/domain/qq-events.d.ts.map +1 -1
  20. package/dist/domain/qq-events.js +6 -3
  21. package/dist/domain/qq-events.js.map +2 -2
  22. package/dist/domain/schema.d.ts.map +1 -1
  23. package/dist/domain/schema.js +48 -0
  24. package/dist/domain/schema.js.map +2 -2
  25. package/dist/domain/system-status.d.ts +3 -0
  26. package/dist/domain/system-status.d.ts.map +1 -1
  27. package/dist/domain/system-status.js +27 -12
  28. package/dist/domain/system-status.js.map +2 -2
  29. package/dist/env.d.ts +0 -2
  30. package/dist/env.d.ts.map +1 -1
  31. package/dist/env.js +12 -24
  32. package/dist/env.js.map +2 -2
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +108 -52
  36. package/dist/index.js.map +3 -3
  37. package/dist/routes/config.d.ts +1 -1
  38. package/dist/routes/config.d.ts.map +1 -1
  39. package/dist/routes/config.js +0 -4
  40. package/dist/routes/config.js.map +2 -2
  41. package/dist/routes/content.d.ts +23 -0
  42. package/dist/routes/content.d.ts.map +1 -0
  43. package/dist/routes/content.js +19 -0
  44. package/dist/routes/content.js.map +7 -0
  45. package/dist/routes/messages.d.ts +14 -6
  46. package/dist/routes/messages.d.ts.map +1 -1
  47. package/dist/routes/messages.js +22 -8
  48. package/dist/routes/messages.js.map +2 -2
  49. package/dist/routes/qq-bind.d.ts.map +1 -1
  50. package/dist/routes/qq-bind.js +29 -1
  51. package/dist/routes/qq-bind.js.map +2 -2
  52. package/dist/routes/qq-events.d.ts +6 -2
  53. package/dist/routes/qq-events.d.ts.map +1 -1
  54. package/dist/routes/qq-events.js +35 -1
  55. package/dist/routes/qq-events.js.map +3 -3
  56. package/dist/routes/qq-join.js +1 -1
  57. package/dist/routes/qq-join.js.map +2 -2
  58. package/dist/routes/status.d.ts +3 -11
  59. package/dist/routes/status.d.ts.map +1 -1
  60. package/dist/routes/status.js +39 -49
  61. package/dist/routes/status.js.map +2 -2
  62. package/dist/tx-runner.d.ts +11 -2
  63. package/dist/tx-runner.d.ts.map +1 -1
  64. package/dist/tx-runner.js +42 -7
  65. package/dist/tx-runner.js.map +2 -2
  66. package/package.json +4 -5
  67. package/dist/domain/bridge.test.d.ts +0 -2
  68. package/dist/domain/bridge.test.d.ts.map +0 -1
  69. package/dist/domain/bridge.test.js +0 -87
  70. package/dist/domain/bridge.test.js.map +0 -7
  71. package/dist/domain/messages-bridge-filter.test.d.ts +0 -5
  72. package/dist/domain/messages-bridge-filter.test.d.ts.map +0 -1
  73. package/dist/domain/messages-bridge-filter.test.js +0 -20
  74. package/dist/domain/messages-bridge-filter.test.js.map +0 -7
  75. package/dist/domain/qq-bind-status.test.d.ts +0 -2
  76. package/dist/domain/qq-bind-status.test.d.ts.map +0 -1
  77. package/dist/domain/qq-bind-status.test.js +0 -211
  78. package/dist/domain/qq-bind-status.test.js.map +0 -7
  79. package/dist/domain/qq-events.test.d.ts +0 -5
  80. package/dist/domain/qq-events.test.d.ts.map +0 -1
  81. package/dist/domain/qq-events.test.js +0 -170
  82. package/dist/domain/qq-events.test.js.map +0 -7
  83. package/dist/domain/qq-join.test.d.ts +0 -2
  84. package/dist/domain/qq-join.test.d.ts.map +0 -1
  85. package/dist/domain/qq-join.test.js +0 -353
  86. package/dist/domain/qq-join.test.js.map +0 -7
  87. package/dist/domain/system-status.test.d.ts +0 -5
  88. package/dist/domain/system-status.test.d.ts.map +0 -1
  89. package/dist/domain/system-status.test.js +0 -19
  90. package/dist/domain/system-status.test.js.map +0 -7
  91. package/dist/runtime.test.d.ts +0 -2
  92. package/dist/runtime.test.d.ts.map +0 -1
  93. package/dist/runtime.test.js +0 -402
  94. package/dist/runtime.test.js.map +0 -7
package/dist/env.d.ts CHANGED
@@ -12,13 +12,11 @@ export interface EnvConfig {
12
12
  LLBOT_PORT: number;
13
13
  LLBOT_TOKEN: string;
14
14
  QQ_GROUP_ID: string;
15
- QQ_BRIDGE_CHANNEL_ID: string;
16
15
  QQ_BACKEND: QQBackend;
17
16
  QQ_APP_ID: string;
18
17
  QQ_APP_SECRET: string;
19
18
  QQ_SANDBOX: boolean;
20
19
  QQ_GROUP_OPENID: string;
21
- MCTOQQ_PREFIX: string;
22
20
  MODULES_DIR: string;
23
21
  MODULE_CATALOG_PATH: string;
24
22
  MODULE_LOCK_PATH: string;
package/dist/env.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,2BAA2B,CAAC;AAsBnC,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAE7B,UAAU,EAAE,SAAS,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,wBAAgB,OAAO,IAAI,SAAS,CAiInC"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAML,KAAK,SAAS,EAEf,MAAM,2BAA2B,CAAC;AAsBnC,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,WAAW,EAAE,MAAM,CAAC;IAEpB,UAAU,EAAE,SAAS,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,wBAAgB,OAAO,IAAI,SAAS,CAqHnC"}
package/dist/env.js CHANGED
@@ -43,6 +43,7 @@ function loadEnv() {
43
43
  log.info(`db_config::${k} -> process.env.${envKey} = ${redactConfigValue(k, v)}`);
44
44
  }
45
45
  for (const [k, v] of Object.entries(qqconfig)) {
46
+ if (v !== null && typeof v === "object") continue;
46
47
  const envKey = k.replace(/([A-Z])/g, "_$1").toUpperCase();
47
48
  if (process.env[envKey] === void 0) {
48
49
  process.env[envKey] = String(v);
@@ -64,18 +65,17 @@ function loadEnv() {
64
65
  const HOST = "127.0.0.1";
65
66
  const DB_PATH_RAW = String(pick(dbconfig["dbDir"], "DB_DIR", "data/sfmc_data.db", "dbDir"));
66
67
  const DB_PATH = isAbsolute(DB_PATH_RAW) ? DB_PATH_RAW : resolve(PROJECT_ROOT, DB_PATH_RAW);
68
+ const official = qqconfig["official"] ?? {};
69
+ const llbot = qqconfig["llbot"] ?? {};
67
70
  const LLBOT_HOST = String(
68
- pick(qqconfig["llbot_host"], "LLBOT_HOST", "127.0.0.1", "llbot_host")
71
+ pick(llbot.host, "LLBOT_HOST", "127.0.0.1", "llbot.host")
69
72
  );
70
73
  const LLBOT_PORT = parseInt(
71
- String(pick(qqconfig["llbot_port"], "LLBOT_PORT", 3004, "llbot_port")),
74
+ String(pick(llbot.port, "LLBOT_PORT", 3004, "llbot.port")),
72
75
  10
73
76
  );
74
- const LLBOT_TOKEN = String(pick(qqconfig["llbot_token"], "LLBOT_TOKEN", "", "llbot_token"));
75
- const QQ_GROUP_ID = String(pick(qqconfig["qq_group_id"], "QQ_GROUP_ID", "", "qq_group_id"));
76
- const QQ_BRIDGE_CHANNEL_ID = String(
77
- pick(qqconfig["bridge_channel_id"], "BRIDGE_CHANNEL_ID", "", "bridge_channel_id")
78
- );
77
+ const LLBOT_TOKEN = String(pick(llbot.token, "LLBOT_TOKEN", "", "llbot.token"));
78
+ const QQ_GROUP_ID = String(pick(llbot.group_id, "QQ_GROUP_ID", "", "llbot.group_id"));
79
79
  const rawBackend = String(
80
80
  pick(
81
81
  qqconfig["qq_backend"],
@@ -85,29 +85,19 @@ function loadEnv() {
85
85
  )
86
86
  );
87
87
  const QQ_BACKEND = rawBackend === "llbot" ? "llbot" : "official";
88
- const QQ_APP_ID = String(
89
- pick(qqconfig["qq_app_id"], "QQ_APP_ID", "", "qq_app_id")
90
- );
88
+ const QQ_APP_ID = String(pick(official.app_id, "QQ_APP_ID", "", "official.app_id"));
91
89
  const QQ_APP_SECRET = String(
92
- pick(qqconfig["qq_app_secret"], "QQ_APP_SECRET", "", "qq_app_secret")
90
+ pick(official.app_secret, "QQ_APP_SECRET", "", "official.app_secret")
93
91
  );
94
92
  const sandboxRaw = pick(
95
- qqconfig["qq_sandbox"],
93
+ official.sandbox,
96
94
  "QQ_SANDBOX",
97
95
  false,
98
- "qq_sandbox"
96
+ "official.sandbox"
99
97
  );
100
98
  const QQ_SANDBOX = sandboxRaw === true || sandboxRaw === "true" || sandboxRaw === "1";
101
99
  const QQ_GROUP_OPENID = String(
102
- pick(qqconfig["qq_group_openid"], "QQ_GROUP_OPENID", "", "qq_group_openid")
103
- );
104
- const MCTOQQ_PREFIX = String(
105
- pick(
106
- qqconfig["mctoqq_prefix"],
107
- "MCTOQQ_PREFIX",
108
- DEFAULT_QQ_CONFIG.mctoqq_prefix ?? "[MC]",
109
- "mctoqq_prefix"
110
- )
100
+ pick(official.group_openid, "QQ_GROUP_OPENID", "", "official.group_openid")
111
101
  );
112
102
  const AUTH_TOKEN = String(pick(dbconfig["http_auth"], "HTTP_AUTH", "", "http_auth"));
113
103
  const MODULES_DIR = dbconfig["modulesDir"] ? resolve(PROJECT_ROOT, String(dbconfig["modulesDir"])) : join(PROJECT_ROOT, "modules");
@@ -123,13 +113,11 @@ function loadEnv() {
123
113
  LLBOT_PORT,
124
114
  LLBOT_TOKEN,
125
115
  QQ_GROUP_ID,
126
- QQ_BRIDGE_CHANNEL_ID,
127
116
  QQ_BACKEND,
128
117
  QQ_APP_ID,
129
118
  QQ_APP_SECRET,
130
119
  QQ_SANDBOX,
131
120
  QQ_GROUP_OPENID,
132
- MCTOQQ_PREFIX,
133
121
  MODULES_DIR,
134
122
  MODULE_CATALOG_PATH,
135
123
  MODULE_LOCK_PATH,
package/dist/env.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/env.ts"],
4
- "sourcesContent": ["/**\n * env.ts \u2014 \u73AF\u5883\u914D\u7F6E\u52A0\u8F7D\n */\n\nimport {\n ensureCoreConfigs,\n loadEnsuredConfig,\n modulePath,\n DEFAULT_DB_CONFIG,\n DEFAULT_QQ_CONFIG,\n type QQBackend,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nimport { log } from \"./lib/log.js\";\nimport { PROJECT_ROOT as RESOLVED_ROOT } from \"./project-root.js\";\n\n/** \u65E5\u5FD7\u8131\u654F\uFF1A\u5BC6\u94A5\u7C7B\u5B57\u6BB5\u4E0D\u6253\u5370\u660E\u6587 */\nconst SECRET_CONFIG_KEYS = new Set([\n \"qq_app_secret\",\n \"llbot_token\",\n \"http_auth\",\n \"agent_secret\",\n]);\n\nfunction redactConfigValue(key: string, value: unknown): string {\n if (SECRET_CONFIG_KEYS.has(key)) {\n const s = String(value ?? \"\");\n return s.length > 0 ? \"***\" : \"\";\n }\n return String(value);\n}\n\nexport interface EnvConfig {\n PROJECT_ROOT: string;\n PORT: number;\n HOST: string;\n DB_PATH: string;\n AUTH_TOKEN: string;\n // LLBot HTTP\n LLBOT_HOST: string;\n LLBOT_PORT: number;\n LLBOT_TOKEN: string;\n // QQ \u7FA4 / channel(\u4ECE qq_config.json \u900F\u51FA,\u7ED9 bridge / messages \u8DEF\u7531\u7528)\n QQ_GROUP_ID: string;\n QQ_BRIDGE_CHANNEL_ID: string;\n // \u5B98\u65B9 Bot\n QQ_BACKEND: QQBackend;\n QQ_APP_ID: string;\n QQ_APP_SECRET: string;\n QQ_SANDBOX: boolean;\n QQ_GROUP_OPENID: string;\n MCTOQQ_PREFIX: string;\n MODULES_DIR: string;\n MODULE_CATALOG_PATH: string;\n MODULE_LOCK_PATH: string;\n dbconfig: Record<string, unknown>;\n qqconfig: Record<string, unknown>;\n}\n\nexport function loadEnv(): EnvConfig {\n const PROJECT_ROOT = RESOLVED_ROOT;\n /* \u542F\u52A8\u65F6\u786E\u8BA4 db/qq/permissions \u5B58\u5728;\u4E0D\u5B58\u5728\u5C31\u5199\u5E26\u9ED8\u8BA4\u503C\u7684\u9AA8\u67B6\u3002\n * \u4E0D\u4F9D\u8D56 wizard:wizard \u53EA\u586B\u5B57\u6BB5,\u9AA8\u67B6\u7531\u670D\u52A1\u81EA\u5DF1 ensure\u3002 */\n ensureCoreConfigs(PROJECT_ROOT, [\"db_config\", \"qq_config\", \"permissions\"]);\n const dbconfig = loadEnsuredConfig(\n PROJECT_ROOT,\n \"db_config.json\",\n \"db_config\",\n { ...DEFAULT_DB_CONFIG } as Record<string, unknown>\n );\n const qqconfig = loadEnsuredConfig(\n PROJECT_ROOT,\n \"qq_config.json\",\n \"qq_config\",\n { ...DEFAULT_QQ_CONFIG } as Record<string, unknown>\n );\n\n // \u2500\u2500 \u4F18\u5148\u7EA7:JSON > \u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF > \u9ED8\u8BA4\u503C \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const envBaseline = { ...process.env };\n\n for (const [k, v] of Object.entries(dbconfig)) {\n const envKey = k.replace(/([A-Z])/g, \"_$1\").toUpperCase();\n process.env[envKey] = String(v);\n log.info(`db_config::${k} -> process.env.${envKey} = ${redactConfigValue(k, v)}`);\n }\n for (const [k, v] of Object.entries(qqconfig)) {\n const envKey = k.replace(/([A-Z])/g, \"_$1\").toUpperCase();\n if (process.env[envKey] === undefined) {\n process.env[envKey] = String(v);\n log.info(`qq_config::${k} -> process.env.${envKey} = ${redactConfigValue(k, v)}`);\n }\n }\n\n // \u5DE5\u5177:JSON > envBaseline(\u539F process.env) > default\n // \u8BED\u4E49:JSON \u91CC\u6709\u8FD9\u4E2A\u952E(\u975E undefined / null)\u5C31\u7528 JSON;\u7A7A\u4E32\u30010\u3001false \u90FD\u7B97\"\u663E\u5F0F\u914D\u7F6E\"\n // \u53EA\u6709 JSON \u5B8C\u5168\u6CA1\u8FD9\u4E2A\u952E(\u6216\u8005\u663E\u5F0F null)\u624D fall through \u5230 env\n function pick<T>(jsonVal: T | undefined | null, envKey: string, fallback: T, source: string): T {\n if (jsonVal !== undefined && jsonVal !== null) {\n return jsonVal;\n }\n const fromEnv = envBaseline[envKey];\n if (fromEnv !== undefined && fromEnv !== \"\") {\n log.info(`${source} \u672A\u5728 JSON \u4E2D\u914D\u7F6E,\u4F7F\u7528\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF ${envKey} = ${redactConfigValue(source, fromEnv)}`);\n return fromEnv as unknown as T;\n }\n return fallback;\n }\n\n const PORT = parseInt(String(pick(dbconfig[\"db_port\"] as number | undefined, \"DB_PORT\", 3001, \"db_port\")), 10);\n const HOST = \"127.0.0.1\";\n const DB_PATH_RAW = String(pick(dbconfig[\"dbDir\"] as string | undefined, \"DB_DIR\", \"data/sfmc_data.db\", \"dbDir\"));\n const DB_PATH = isAbsolute(DB_PATH_RAW) ? DB_PATH_RAW : resolve(PROJECT_ROOT, DB_PATH_RAW);\n const LLBOT_HOST = String(\n pick(qqconfig[\"llbot_host\"] as string | undefined, \"LLBOT_HOST\", \"127.0.0.1\", \"llbot_host\")\n );\n const LLBOT_PORT = parseInt(\n String(pick(qqconfig[\"llbot_port\"] as number | undefined, \"LLBOT_PORT\", 3004, \"llbot_port\")),\n 10\n );\n const LLBOT_TOKEN = String(pick(qqconfig[\"llbot_token\"] as string | undefined, \"LLBOT_TOKEN\", \"\", \"llbot_token\"));\n const QQ_GROUP_ID = String(pick(qqconfig[\"qq_group_id\"] as string | undefined, \"QQ_GROUP_ID\", \"\", \"qq_group_id\"));\n const QQ_BRIDGE_CHANNEL_ID = String(\n pick(qqconfig[\"bridge_channel_id\"] as string | undefined, \"BRIDGE_CHANNEL_ID\", \"\", \"bridge_channel_id\")\n );\n const rawBackend = String(\n pick(\n qqconfig[\"qq_backend\"] as string | undefined,\n \"QQ_BACKEND\",\n DEFAULT_QQ_CONFIG.qq_backend ?? \"official\",\n \"qq_backend\"\n )\n );\n const QQ_BACKEND: QQBackend = rawBackend === \"llbot\" ? \"llbot\" : \"official\";\n const QQ_APP_ID = String(\n pick(qqconfig[\"qq_app_id\"] as string | undefined, \"QQ_APP_ID\", \"\", \"qq_app_id\")\n );\n const QQ_APP_SECRET = String(\n pick(qqconfig[\"qq_app_secret\"] as string | undefined, \"QQ_APP_SECRET\", \"\", \"qq_app_secret\")\n );\n const sandboxRaw = pick(\n qqconfig[\"qq_sandbox\"] as boolean | string | undefined,\n \"QQ_SANDBOX\",\n false as boolean | string,\n \"qq_sandbox\"\n );\n const QQ_SANDBOX =\n sandboxRaw === true || sandboxRaw === \"true\" || sandboxRaw === \"1\";\n const QQ_GROUP_OPENID = String(\n pick(qqconfig[\"qq_group_openid\"] as string | undefined, \"QQ_GROUP_OPENID\", \"\", \"qq_group_openid\")\n );\n const MCTOQQ_PREFIX = String(\n pick(\n qqconfig[\"mctoqq_prefix\"] as string | undefined,\n \"MCTOQQ_PREFIX\",\n DEFAULT_QQ_CONFIG.mctoqq_prefix ?? \"[MC]\",\n \"mctoqq_prefix\"\n )\n );\n const AUTH_TOKEN = String(pick(dbconfig[\"http_auth\"] as string | undefined, \"HTTP_AUTH\", \"\", \"http_auth\"));\n const MODULES_DIR = dbconfig[\"modulesDir\"]\n ? resolve(PROJECT_ROOT, String(dbconfig[\"modulesDir\"]))\n : join(PROJECT_ROOT, \"modules\");\n const MODULE_CATALOG_PATH = modulePath(MODULES_DIR, \"catalog.json\");\n const MODULE_LOCK_PATH = modulePath(MODULES_DIR, \"module-lock.json\");\n\n return {\n PROJECT_ROOT,\n PORT,\n HOST,\n DB_PATH,\n AUTH_TOKEN,\n LLBOT_HOST,\n LLBOT_PORT,\n LLBOT_TOKEN,\n QQ_GROUP_ID,\n QQ_BRIDGE_CHANNEL_ID,\n QQ_BACKEND,\n QQ_APP_ID,\n QQ_APP_SECRET,\n QQ_SANDBOX,\n QQ_GROUP_OPENID,\n MCTOQQ_PREFIX,\n MODULES_DIR,\n MODULE_CATALOG_PATH,\n MODULE_LOCK_PATH,\n dbconfig,\n qqconfig,\n };\n}\n\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * env.ts \u2014 \u73AF\u5883\u914D\u7F6E\u52A0\u8F7D\n */\n\nimport {\n ensureCoreConfigs,\n loadEnsuredConfig,\n modulePath,\n DEFAULT_DB_CONFIG,\n DEFAULT_QQ_CONFIG,\n type QQBackend,\n type QQBridgeConfig,\n} from \"@sfmc-bds/sdk/node/config\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nimport { log } from \"./lib/log.js\";\nimport { PROJECT_ROOT as RESOLVED_ROOT } from \"./project-root.js\";\n\n/** \u65E5\u5FD7\u8131\u654F\uFF1A\u5BC6\u94A5\u7C7B\u5B57\u6BB5\u4E0D\u6253\u5370\u660E\u6587 */\nconst SECRET_CONFIG_KEYS = new Set([\n \"qq_app_secret\",\n \"llbot_token\",\n \"http_auth\",\n \"agent_secret\",\n]);\n\nfunction redactConfigValue(key: string, value: unknown): string {\n if (SECRET_CONFIG_KEYS.has(key)) {\n const s = String(value ?? \"\");\n return s.length > 0 ? \"***\" : \"\";\n }\n return String(value);\n}\n\nexport interface EnvConfig {\n PROJECT_ROOT: string;\n PORT: number;\n HOST: string;\n DB_PATH: string;\n AUTH_TOKEN: string;\n // LLBot HTTP\n LLBOT_HOST: string;\n LLBOT_PORT: number;\n LLBOT_TOKEN: string;\n // QQ \u7FA4 / channel(\u4ECE qq_config.json \u900F\u51FA,\u7ED9 bridge / messages \u8DEF\u7531\u7528)\n QQ_GROUP_ID: string;\n // \u5B98\u65B9 Bot\n QQ_BACKEND: QQBackend;\n QQ_APP_ID: string;\n QQ_APP_SECRET: string;\n QQ_SANDBOX: boolean;\n QQ_GROUP_OPENID: string;\n MODULES_DIR: string;\n MODULE_CATALOG_PATH: string;\n MODULE_LOCK_PATH: string;\n dbconfig: Record<string, unknown>;\n qqconfig: Record<string, unknown>;\n}\n\nexport function loadEnv(): EnvConfig {\n const PROJECT_ROOT = RESOLVED_ROOT;\n /* \u542F\u52A8\u65F6\u786E\u8BA4 db/qq/permissions \u5B58\u5728;\u4E0D\u5B58\u5728\u5C31\u5199\u5E26\u9ED8\u8BA4\u503C\u7684\u9AA8\u67B6\u3002\n * \u4E0D\u4F9D\u8D56 wizard:wizard \u53EA\u586B\u5B57\u6BB5,\u9AA8\u67B6\u7531\u670D\u52A1\u81EA\u5DF1 ensure\u3002 */\n ensureCoreConfigs(PROJECT_ROOT, [\"db_config\", \"qq_config\", \"permissions\"]);\n const dbconfig = loadEnsuredConfig(\n PROJECT_ROOT,\n \"db_config.json\",\n \"db_config\",\n { ...DEFAULT_DB_CONFIG } as Record<string, unknown>\n );\n const qqconfig = loadEnsuredConfig(\n PROJECT_ROOT,\n \"qq_config.json\",\n \"qq_config\",\n { ...DEFAULT_QQ_CONFIG } as Record<string, unknown>\n );\n\n // \u2500\u2500 \u4F18\u5148\u7EA7:JSON > \u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF > \u9ED8\u8BA4\u503C \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const envBaseline = { ...process.env };\n\n for (const [k, v] of Object.entries(dbconfig)) {\n const envKey = k.replace(/([A-Z])/g, \"_$1\").toUpperCase();\n process.env[envKey] = String(v);\n log.info(`db_config::${k} -> process.env.${envKey} = ${redactConfigValue(k, v)}`);\n }\n for (const [k, v] of Object.entries(qqconfig)) {\n if (v !== null && typeof v === \"object\") continue;\n const envKey = k.replace(/([A-Z])/g, \"_$1\").toUpperCase();\n if (process.env[envKey] === undefined) {\n process.env[envKey] = String(v);\n log.info(`qq_config::${k} -> process.env.${envKey} = ${redactConfigValue(k, v)}`);\n }\n }\n\n // \u5DE5\u5177:JSON > envBaseline(\u539F process.env) > default\n // \u8BED\u4E49:JSON \u91CC\u6709\u8FD9\u4E2A\u952E(\u975E undefined / null)\u5C31\u7528 JSON;\u7A7A\u4E32\u30010\u3001false \u90FD\u7B97\"\u663E\u5F0F\u914D\u7F6E\"\n // \u53EA\u6709 JSON \u5B8C\u5168\u6CA1\u8FD9\u4E2A\u952E(\u6216\u8005\u663E\u5F0F null)\u624D fall through \u5230 env\n function pick<T>(jsonVal: T | undefined | null, envKey: string, fallback: T, source: string): T {\n if (jsonVal !== undefined && jsonVal !== null) {\n return jsonVal;\n }\n const fromEnv = envBaseline[envKey];\n if (fromEnv !== undefined && fromEnv !== \"\") {\n log.info(`${source} \u672A\u5728 JSON \u4E2D\u914D\u7F6E,\u4F7F\u7528\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF ${envKey} = ${redactConfigValue(source, fromEnv)}`);\n return fromEnv as unknown as T;\n }\n return fallback;\n }\n\n const PORT = parseInt(String(pick(dbconfig[\"db_port\"] as number | undefined, \"DB_PORT\", 3001, \"db_port\")), 10);\n const HOST = \"127.0.0.1\";\n const DB_PATH_RAW = String(pick(dbconfig[\"dbDir\"] as string | undefined, \"DB_DIR\", \"data/sfmc_data.db\", \"dbDir\"));\n const DB_PATH = isAbsolute(DB_PATH_RAW) ? DB_PATH_RAW : resolve(PROJECT_ROOT, DB_PATH_RAW);\n const official = (qqconfig[\"official\"] ?? {}) as NonNullable<QQBridgeConfig[\"official\"]>;\n const llbot = (qqconfig[\"llbot\"] ?? {}) as NonNullable<QQBridgeConfig[\"llbot\"]>;\n const LLBOT_HOST = String(\n pick(llbot.host, \"LLBOT_HOST\", \"127.0.0.1\", \"llbot.host\")\n );\n const LLBOT_PORT = parseInt(\n String(pick(llbot.port, \"LLBOT_PORT\", 3004, \"llbot.port\")),\n 10\n );\n const LLBOT_TOKEN = String(pick(llbot.token, \"LLBOT_TOKEN\", \"\", \"llbot.token\"));\n const QQ_GROUP_ID = String(pick(llbot.group_id, \"QQ_GROUP_ID\", \"\", \"llbot.group_id\"));\n const rawBackend = String(\n pick(\n qqconfig[\"qq_backend\"] as string | undefined,\n \"QQ_BACKEND\",\n DEFAULT_QQ_CONFIG.qq_backend ?? \"official\",\n \"qq_backend\"\n )\n );\n const QQ_BACKEND: QQBackend = rawBackend === \"llbot\" ? \"llbot\" : \"official\";\n const QQ_APP_ID = String(pick(official.app_id, \"QQ_APP_ID\", \"\", \"official.app_id\"));\n const QQ_APP_SECRET = String(\n pick(official.app_secret, \"QQ_APP_SECRET\", \"\", \"official.app_secret\")\n );\n const sandboxRaw = pick(\n official.sandbox as boolean | string | undefined,\n \"QQ_SANDBOX\",\n false as boolean | string,\n \"official.sandbox\"\n );\n const QQ_SANDBOX =\n sandboxRaw === true || sandboxRaw === \"true\" || sandboxRaw === \"1\";\n const QQ_GROUP_OPENID = String(\n pick(official.group_openid, \"QQ_GROUP_OPENID\", \"\", \"official.group_openid\")\n );\n const AUTH_TOKEN = String(pick(dbconfig[\"http_auth\"] as string | undefined, \"HTTP_AUTH\", \"\", \"http_auth\"));\n const MODULES_DIR = dbconfig[\"modulesDir\"]\n ? resolve(PROJECT_ROOT, String(dbconfig[\"modulesDir\"]))\n : join(PROJECT_ROOT, \"modules\");\n const MODULE_CATALOG_PATH = modulePath(MODULES_DIR, \"catalog.json\");\n const MODULE_LOCK_PATH = modulePath(MODULES_DIR, \"module-lock.json\");\n\n return {\n PROJECT_ROOT,\n PORT,\n HOST,\n DB_PATH,\n AUTH_TOKEN,\n LLBOT_HOST,\n LLBOT_PORT,\n LLBOT_TOKEN,\n QQ_GROUP_ID,\n QQ_BACKEND,\n QQ_APP_ID,\n QQ_APP_SECRET,\n QQ_SANDBOX,\n QQ_GROUP_OPENID,\n MODULES_DIR,\n MODULE_CATALOG_PATH,\n MODULE_LOCK_PATH,\n dbconfig,\n qqconfig,\n };\n}\n\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -28,5 +28,5 @@ declare const moduleAuth: import("./module-auth.js").ModuleAuthMap;
28
28
  declare const schemaRegistry: SchemaRegistry;
29
29
  declare const serviceRegistry: ServiceRegistry;
30
30
  declare const txRunner: TxRunner;
31
- export { db, env, query, schemaRegistry, serviceRegistry, txRunner, enabledManifests, moduleAuth };
31
+ export { db, enabledManifests, env, moduleAuth, query, schemaRegistry, serviceRegistry, txRunner };
32
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAcH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAgC1C,QAAA,MAAM,GAAG,8BAAY,CAAC;AACtB,QAAA,MAAM,EAAE,oCAA4B,CAAC;AAGrC,QAAA,MAAM,KAAK,mCAAkB,CAAC;AA4B9B,QAAA,MAAM,gBAAgB,8DAAwE,CAAC;AAU/F,QAAA,MAAM,UAAU,0CAId,CAAC;AAGH,QAAA,MAAM,cAAc,gBAAyB,CAAC;AAC9C,QAAA,MAAM,eAAe,iBAAwB,CAAC;AAE9C,QAAA,MAAM,QAAQ,UAMZ,CAAC;AAwXH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAgBH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AA6B1C,QAAA,MAAM,GAAG,8BAAY,CAAC;AACtB,QAAA,MAAM,EAAE,oCAA4B,CAAC;AAGrC,QAAA,MAAM,KAAK,mCAAkB,CAAC;AAwB9B,QAAA,MAAM,gBAAgB,8DAA0E,CAAC;AAQjG,QAAA,MAAM,UAAU,0CAId,CAAC;AAGH,QAAA,MAAM,cAAc,gBAAyB,CAAC;AAC9C,QAAA,MAAM,eAAe,iBAAwB,CAAC;AAE9C,QAAA,MAAM,QAAQ,UAMZ,CAAC;AA4cH,OAAO,EAAE,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,40 +1,41 @@
1
1
  import http from "node:http";
2
- import { createIdempotencyStore } from "./lib/idempotency-store.js";
2
+ import { SQL } from "sql-template-strings";
3
+ import { createPlatformTables } from "./db-tables.js";
4
+ import { initSchema } from "./domain/schema.js";
5
+ import { syncPlayerSession } from "./domain/player-session.js";
3
6
  import { loadEnv } from "./env.js";
4
- import { buildModuleAuth, verifyModuleAuth } from "./module-auth.js";
5
- import { loadManifestV2 } from "./manifest-loader.js";
7
+ import { createIdempotencyStore } from "./lib/idempotency-store.js";
6
8
  import { log } from "./lib/log.js";
7
9
  import { assertNodeVersion } from "./lib/runtime.js";
8
10
  import { createQuery, openDatabase } from "./lib/sqlite.js";
9
- import { createServer, startConsole } from "./server.js";
10
- import { createPlatformTables } from "./db-tables.js";
11
- import { initSchema } from "./domain/schema.js";
11
+ import { loadManifestV2 } from "./manifest-loader.js";
12
+ import { buildModuleAuth, verifyModuleAuth } from "./module-auth.js";
13
+ import { syncModuleRuntimeState } from "./module-runtime-sync.js";
12
14
  import { SchemaRegistry } from "./schema-registry.js";
15
+ import { createServer, startConsole } from "./server.js";
13
16
  import { ServiceRegistry } from "./service-registry.js";
14
- import { TxRunner } from "./tx-runner.js";
15
17
  import { registerEnabledBuiltinServices } from "./services/builtin-handlers.js";
16
- import { syncModuleRuntimeState } from "./module-runtime-sync.js";
17
- import { ensureJson, patchJson, readJson } from "@sfmc-bds/sdk/node/config";
18
- import { join } from "node:path";
19
- import { createModuleConfigRoutes } from "./routes/module-config-routes.js";
18
+ import { TxRunner } from "./tx-runner.js";
19
+ import { configPath, ensureJson, patchJson, readJson } from "@sfmc-bds/sdk/node/config";
20
+ import path, { join } from "node:path";
21
+ import { jsonV2Fail } from "./routes/_shared.js";
20
22
  import { createDbRoutes } from "./routes/db-routes.js";
23
+ import { createModuleConfigRoutes } from "./routes/module-config-routes.js";
21
24
  import { createServiceRoutes } from "./routes/service-routes.js";
22
- import { jsonV2Fail } from "./routes/_shared.js";
23
- import { createStatusRoutes } from "./routes/status.js";
24
- import { createQqBindRoutes } from "./routes/qq-bind.js";
25
- import { createQqJoinRoutes } from "./routes/qq-join.js";
26
- import { createQqEventsRoutes } from "./routes/qq-events.js";
27
- import { createMessagesRoutes } from "./routes/messages.js";
28
- import { createModuleRoutes } from "./routes/modules.js";
29
- import { createConfigRoutes } from "./routes/config.js";
30
- import { createHealthRoutes } from "./routes/health.js";
31
25
  import { forwardToQQBridge, makeOutboundConfig } from "./domain/bridge.js";
32
- import {
33
- createQqEventsAggregator,
34
- resolveQqEventsConfig
35
- } from "./domain/qq-events.js";
36
- import { isEnabled, loadModuleLock, saveModuleLock, updateModuleState } from "./lib/module-state.js";
26
+ import { createQqEventsAggregator, resolveQqEventsConfig } from "./domain/qq-events.js";
37
27
  import { body as sharedBody, json as sharedJson } from "./lib/http.js";
28
+ import { isEnabled, loadModuleLock, saveModuleLock, updateModuleState } from "./lib/module-state.js";
29
+ import { loadContentSnapshot } from "./domain/installed-content.js";
30
+ import { createConfigRoutes } from "./routes/config.js";
31
+ import { createContentRoutes } from "./routes/content.js";
32
+ import { createHealthRoutes } from "./routes/health.js";
33
+ import { createMessagesRoutes } from "./routes/messages.js";
34
+ import { createModuleRoutes } from "./routes/modules.js";
35
+ import { createQqBindRoutes } from "./routes/qq-bind.js";
36
+ import { createQqEventsRoutes } from "./routes/qq-events.js";
37
+ import { createQqJoinRoutes } from "./routes/qq-join.js";
38
+ import { createStatusRoutes } from "./routes/status.js";
38
39
  if (!assertNodeVersion(22, 13)) {
39
40
  process.exit(2);
40
41
  }
@@ -55,9 +56,7 @@ const catalogIds = new Set(
55
56
  const enabledSet = /* @__PURE__ */ new Set();
56
57
  for (const id of Object.keys(loadedManifest.modules)) {
57
58
  if (!catalogIds.has(id)) continue;
58
- const catalogEntry = moduleCatalog.modules.find(
59
- (m) => String(m.id) === id
60
- );
59
+ const catalogEntry = moduleCatalog.modules.find((m) => String(m.id) === id);
61
60
  if (!catalogEntry) continue;
62
61
  const defaultEnabled = catalogEntry.enabledByDefault !== false;
63
62
  if (isEnabled(lockFile, id, defaultEnabled)) enabledSet.add(id);
@@ -67,9 +66,7 @@ for (const id of enabledSet) {
67
66
  const m = loadedManifest.modules[id];
68
67
  if (m) enabledManifests.set(id, m);
69
68
  }
70
- log.info(
71
- `[manifest v2] enabled: ${[...enabledSet].sort().join(", ") || "(none)"}`
72
- );
69
+ log.info(`[manifest v2] enabled: ${[...enabledSet].sort().join(", ") || "(none)"}`);
73
70
  const moduleAuth = buildModuleAuth({
74
71
  dbPath: env.DB_PATH,
75
72
  envAuthToken: env.AUTH_TOKEN,
@@ -88,9 +85,7 @@ const txRunner = new TxRunner({
88
85
  {
89
86
  const plugins = registerEnabledBuiltinServices(serviceRegistry, { query, db }, enabledSet);
90
87
  if (plugins > 0) {
91
- log.success(
92
- `[service] registered ${serviceRegistry.list().length} handlers from ${plugins} builtin plugin(s)`
93
- );
88
+ log.success(`[service] registered ${serviceRegistry.list().length} handlers from ${plugins} builtin plugin(s)`);
94
89
  }
95
90
  }
96
91
  const json = sharedJson;
@@ -134,6 +129,29 @@ function buildModuleList() {
134
129
  };
135
130
  }).filter(Boolean);
136
131
  }
132
+ function loadContentSnapshotForRequest() {
133
+ const modules = (buildModuleList() ?? []).flatMap((raw) => {
134
+ if (!raw || typeof raw !== "object") return [];
135
+ const row = raw;
136
+ const id = String(row.id ?? "").trim();
137
+ if (!id) return [];
138
+ return [
139
+ {
140
+ id,
141
+ display_name: String(row.display_name || id),
142
+ enabled: row.enabled !== false
143
+ }
144
+ ];
145
+ });
146
+ const cfg = readJson(configPath(env.PROJECT_ROOT, "bds_updater.json"));
147
+ const rawBds = typeof cfg?.bds_path === "string" ? cfg.bds_path.trim() : "";
148
+ const bdsRoot = rawBds ? path.isAbsolute(rawBds) ? rawBds : path.resolve(env.PROJECT_ROOT, rawBds) : null;
149
+ return loadContentSnapshot({
150
+ packagesDir: join(env.MODULES_DIR, "packages"),
151
+ modules,
152
+ bdsRoot
153
+ });
154
+ }
137
155
  function moduleCanDisable(raw) {
138
156
  return raw.canDisable !== false;
139
157
  }
@@ -166,7 +184,7 @@ function setModuleEnabled(mod, enabled) {
166
184
  });
167
185
  }
168
186
  const healthRoutes = createHealthRoutes();
169
- const statusRoutes = createStatusRoutes({ query });
187
+ const statusRoutes = createStatusRoutes({});
170
188
  const qqBindRoutes = createQqBindRoutes({ query, body, json });
171
189
  const QQ_LINK_CONFIG_KEY = "qq_link";
172
190
  const QQ_LINK_DEFAULTS = {
@@ -220,13 +238,24 @@ const qqJoinRoutes = createQqJoinRoutes({
220
238
  body,
221
239
  json,
222
240
  getAdminOpenids: () => {
223
- const raw = env.qqconfig["qq_admin_openids"];
241
+ const raw = env.qqconfig["official"]?.admin_openids;
224
242
  if (!Array.isArray(raw)) return [];
225
243
  return raw.map((x) => String(x).trim()).filter(Boolean);
226
244
  },
227
245
  getJoinFlags: () => readJoinFlags(),
228
246
  setJoinFlags: (partial) => writeJoinFlags(partial)
229
247
  });
248
+ function readQqEventsSettings() {
249
+ const disk = readJson(join(env.PROJECT_ROOT, "configs", "qq_config.json"));
250
+ if (!disk) throw new Error("qq_config.json \u65E0\u6CD5\u8BFB\u53D6\uFF0C\u4E8B\u4EF6\u8BBE\u7F6E\u672A\u4FEE\u6539");
251
+ return resolveQqEventsConfig(disk.qq_events);
252
+ }
253
+ function writeQqEventsSettings(patch) {
254
+ const file = join(env.PROJECT_ROOT, "configs", "qq_config.json");
255
+ const settings = { ...readQqEventsSettings(), ...patch };
256
+ patchJson(file, { qq_events: settings });
257
+ return settings;
258
+ }
230
259
  function currentOutbound() {
231
260
  return makeOutboundConfig({
232
261
  QQ_BACKEND: env.QQ_BACKEND,
@@ -237,25 +266,35 @@ function currentOutbound() {
237
266
  QQ_APP_ID: env.QQ_APP_ID,
238
267
  QQ_APP_SECRET: env.QQ_APP_SECRET,
239
268
  QQ_SANDBOX: env.QQ_SANDBOX,
240
- QQ_GROUP_OPENID: env.QQ_GROUP_OPENID,
241
- MCTOQQ_PREFIX: env.MCTOQQ_PREFIX
269
+ QQ_GROUP_OPENID: env.QQ_GROUP_OPENID
242
270
  });
243
271
  }
244
272
  const qqEventsAggregator = createQqEventsAggregator({
245
- getConfig: () => resolveQqEventsConfig(env.qqconfig["qq_events"]),
273
+ getConfig: readQqEventsSettings,
246
274
  getOutbound: () => currentOutbound()
247
275
  });
248
276
  const qqEventsRoutes = createQqEventsRoutes({
249
277
  body,
250
278
  json,
251
- aggregator: qqEventsAggregator
279
+ aggregator: qqEventsAggregator,
280
+ getSettings: readQqEventsSettings,
281
+ setSettings: writeQqEventsSettings,
282
+ isAdmin: (openid, asGroupAdmin) => {
283
+ const admins = env.qqconfig["official"]?.admin_openids;
284
+ return Array.isArray(admins) && admins.includes(openid) || asGroupAdmin && readJoinFlags().treatGroupAdminsAsAdmins;
285
+ }
252
286
  });
253
287
  const messagesRoutes = createMessagesRoutes({
254
288
  query,
255
289
  body,
256
290
  json,
257
- getBridgeChannelId: () => String(env.QQ_BRIDGE_CHANNEL_ID ?? "").trim(),
258
- forwardToQQBridge: (channelId, fromName, content, fromId) => forwardToQQBridge(currentOutbound(), channelId, fromName, content, fromId)
291
+ getChannelForQQ: (channelId) => {
292
+ const rows = query(
293
+ SQL`SELECT * FROM sfmc_chat_channels WHERE id = ${channelId}`
294
+ );
295
+ return Array.isArray(rows) ? rows[0] ?? null : null;
296
+ },
297
+ forwardToQQBridge: (channelId, prefix, fromName, content, fromId) => forwardToQQBridge(currentOutbound(), channelId, prefix, fromName, content, fromId)
259
298
  });
260
299
  const configRoutes = createConfigRoutes({
261
300
  json,
@@ -264,6 +303,10 @@ const configRoutes = createConfigRoutes({
264
303
  listModules: () => buildModuleList(),
265
304
  getModuleTokens: () => ({ ...moduleAuth.tokens })
266
305
  });
306
+ const contentRoutes = createContentRoutes({
307
+ json,
308
+ loadSnapshot: loadContentSnapshotForRequest
309
+ });
267
310
  const moduleRoutesInstance = createModuleRoutes({
268
311
  loadModuleCatalog,
269
312
  buildModuleList,
@@ -285,7 +328,7 @@ const moduleConfigRoutes = createModuleConfigRoutes({
285
328
  });
286
329
  async function handle(req, res) {
287
330
  const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
288
- const path = url.pathname;
331
+ const path2 = url.pathname;
289
332
  const method = req.method || "GET";
290
333
  const params = url.searchParams;
291
334
  const remote = req.socket.remoteAddress || "";
@@ -294,8 +337,8 @@ async function handle(req, res) {
294
337
  return;
295
338
  }
296
339
  await body(req);
297
- const isLegacyConfigAll = path === "/api/sfmc/configs/all";
298
- const needsModuleAuth = path.startsWith("/api/sfmc/db/") || path.startsWith("/api/sfmc/services") || /^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+(?:\/(?:set|notify))?$/.test(path) && !isLegacyConfigAll;
340
+ const isLegacyConfigAll = path2 === "/api/sfmc/configs/all";
341
+ const needsModuleAuth = path2.startsWith("/api/sfmc/db/") || path2.startsWith("/api/sfmc/services") || /^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+(?:\/(?:set|notify))?$/.test(path2) && !isLegacyConfigAll;
299
342
  let moduleAuthCtx = null;
300
343
  if (needsModuleAuth) {
301
344
  const id = verifyModuleAuth({
@@ -314,8 +357,8 @@ async function handle(req, res) {
314
357
  permissions: manifest?.permissions ?? []
315
358
  };
316
359
  } else {
317
- const PUBLIC_GET = path === "/api/health" || path === "/api/sfmc/status" || path === "/api/sfmc/qq/join/apply-queue" || path === "/api/sfmc/qq/join/settings" || path === "/api/sfmc/qq/admin/action-queue" || method === "GET" && (path === "/api/sfmc/modules" || path === "/api/sfmc/modules/catalog" || path.startsWith("/api/sfmc/modules/") || path === "/api/sfmc/qq/bind/me" || path === "/api/sfmc/qq/join/pending");
318
- const NEEDS_AUTH = !PUBLIC_GET && method !== "GET" && !(path.startsWith("/api/sfmc/qq/bind/") || path.startsWith("/api/sfmc/qq/join/") || path.startsWith("/api/sfmc/qq/admin/") || path.startsWith("/api/sfmc/qq/events"));
360
+ const PUBLIC_GET = path2 === "/api/health" || path2 === "/api/sfmc/status" || path2 === "/api/sfmc/qq/join/apply-queue" || path2 === "/api/sfmc/qq/join/settings" || path2 === "/api/sfmc/qq/admin/action-queue" || method === "GET" && (path2 === "/api/sfmc/content" || path2 === "/api/sfmc/modules" || path2 === "/api/sfmc/modules/catalog" || path2.startsWith("/api/sfmc/modules/") || path2 === "/api/sfmc/qq/bind/me" || path2 === "/api/sfmc/qq/join/pending");
361
+ const NEEDS_AUTH = !PUBLIC_GET && method !== "GET" && !(path2.startsWith("/api/sfmc/qq/bind/") || path2.startsWith("/api/sfmc/qq/join/") || path2.startsWith("/api/sfmc/qq/admin/") || path2.startsWith("/api/sfmc/qq/events"));
319
362
  if (env.AUTH_TOKEN && NEEDS_AUTH) {
320
363
  const auth = req.headers["authorization"] || "";
321
364
  const provided = auth.startsWith("Bearer ") ? auth.slice(7) : req.headers["x-db-token"] || "";
@@ -326,9 +369,21 @@ async function handle(req, res) {
326
369
  }
327
370
  }
328
371
  try {
329
- if (moduleAuthCtx && (path.startsWith("/api/sfmc/db/") || path.startsWith("/api/sfmc/services") || /^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+/.test(path) && !isLegacyConfigAll)) {
372
+ if (path2 === "/api/sfmc/player-session" && method === "POST") {
373
+ const data = await body(req);
374
+ const playerName = String(data.playerName ?? "").trim();
375
+ const xuid = String(data.xuid ?? "").trim();
376
+ if (!playerName || !xuid) {
377
+ json(res, { success: false, error: "playerName_and_xuid_required" }, 400);
378
+ return;
379
+ }
380
+ syncPlayerSession(query, { playerName, xuid });
381
+ json(res, { success: true });
382
+ return;
383
+ }
384
+ if (moduleAuthCtx && (path2.startsWith("/api/sfmc/db/") || path2.startsWith("/api/sfmc/services") || /^\/api\/sfmc\/configs\/[A-Za-z0-9_-]+/.test(path2) && !isLegacyConfigAll)) {
330
385
  const ctx = {
331
- path,
386
+ path: path2,
332
387
  method,
333
388
  params,
334
389
  req,
@@ -336,15 +391,16 @@ async function handle(req, res) {
336
391
  moduleAuth: moduleAuthCtx
337
392
  };
338
393
  ctx["body"] = await body(req);
339
- if (path.startsWith("/api/sfmc/db/")) {
394
+ if (path2.startsWith("/api/sfmc/db/")) {
340
395
  if (await dbRoutes(ctx)) return;
341
- } else if (path.startsWith("/api/sfmc/services")) {
396
+ } else if (path2.startsWith("/api/sfmc/services")) {
342
397
  if (await serviceRoutes(ctx)) return;
343
398
  } else {
344
399
  if (await moduleConfigRoutes(ctx)) return;
345
400
  }
346
401
  }
347
- const ctxBase = { path, method, params, req, res };
402
+ const ctxBase = { path: path2, method, params, req, res };
403
+ if (await contentRoutes(ctxBase)) return;
348
404
  if (await moduleRoutesInstance(ctxBase)) return;
349
405
  if (await healthRoutes(ctxBase)) return;
350
406
  if (await statusRoutes(ctxBase)) return;