koishi-plugin-adapter-onebot-multi 1.0.6 → 2.0.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.
package/lib/index.js CHANGED
@@ -920,65 +920,103 @@ var WsClient = class extends import_koishi5.Adapter.WsClient {
920
920
  WsClient2.Options = import_koishi5.Schema.intersect([
921
921
  import_koishi5.Schema.object({
922
922
  protocol: import_koishi5.Schema.const("ws").required(process.env.KOISHI_ENV !== "browser"),
923
- endpoint: import_koishi5.Schema.string().description("OneBot 实现的 WebSocket 服务器地址。").required(),
924
- responseTimeout: import_koishi5.Schema.natural().role("time").default(import_koishi5.Time.minute).description("等待响应的时间 (单位为毫秒)")
925
- }).description("连接设置"),
923
+ endpoint: import_koishi5.Schema.string().description("OneBot ??? WebSocket ??????").required(),
924
+ responseTimeout: import_koishi5.Schema.natural().role("time").default(import_koishi5.Time.minute).description("??????? (?????)?")
925
+ }).description("????"),
926
926
  import_koishi5.HTTP.createConfig(true),
927
927
  import_koishi5.Adapter.WsClientConfig
928
928
  ]);
929
929
  })(WsClient || (WsClient = {}));
930
930
  var kSocket = Symbol("socket");
931
- var WsServer = class extends import_koishi5.Adapter {
932
- static {
933
- __name(this, "WsServer");
934
- }
935
- static inject = ["server"];
936
- logger;
937
- wsServer;
938
- constructor(ctx, bot) {
939
- super(ctx);
931
+ var reverseHubs = /* @__PURE__ */ new WeakMap();
932
+ var ReverseHub = class {
933
+ constructor(ctx, path2) {
934
+ this.ctx = ctx;
935
+ this.path = path2;
940
936
  this.logger = ctx.logger("onebot");
941
- const { path: path2 = "/onebot" } = bot.config;
942
937
  this.wsServer = ctx.server.ws(path2, (socket, { headers }) => {
943
938
  this.logger.debug("connected with", headers);
944
939
  if (headers["x-client-role"] !== "Universal") {
945
940
  return socket.close(1008, "invalid x-client-role");
946
941
  }
947
942
  const selfId = headers["x-self-id"]?.toString();
948
- let bot2 = this.bots.find((bot3) => bot3.selfId === selfId);
949
- if (!bot2 && selfId) {
950
- const pending = this.bots.find((item) => {
951
- const managedKey = String(item.config?.managedKey || "");
952
- return managedKey.startsWith("pending_") || String(item.selfId || "").startsWith("pending_");
953
- });
954
- if (pending) {
955
- this.logger.info(`Bot ${pending.selfId} 自动绑定真实 selfId: ${selfId}`);
956
- pending.selfId = selfId;
957
- pending.config.selfId = selfId;
958
- bot2 = pending;
959
- }
943
+ let bot = selfId ? this.findBot(selfId) : void 0;
944
+ if (!bot && selfId) {
945
+ const ensureReverseBot = this.ctx._onebotMultiEnsureReverseBot;
946
+ bot = ensureReverseBot?.(selfId, this.path);
960
947
  }
961
- if (!bot2) return socket.close(1008, "invalid x-self-id");
962
- this.logger.info(`Bot ${selfId} 已连接 (ws-reverse)`);
963
- bot2[kSocket] = socket;
964
- accept(socket, bot2);
948
+ if (!bot) return socket.close(1008, "invalid x-self-id");
949
+ this.logger.info(`Bot ${selfId} ??? (ws-reverse)`);
950
+ bot[kSocket] = socket;
951
+ accept(socket, bot);
965
952
  });
966
953
  ctx.on("dispose", () => {
967
954
  this.logger.debug("ws server closing");
968
- this.wsServer.close();
955
+ this.wsServer?.close();
956
+ });
957
+ }
958
+ static {
959
+ __name(this, "ReverseHub");
960
+ }
961
+ logger;
962
+ wsServer;
963
+ findBot(selfId) {
964
+ for (const bot of this.ctx.bots) {
965
+ if (bot.platform !== "onebot") continue;
966
+ if (String(bot.selfId) !== selfId) continue;
967
+ return bot;
968
+ }
969
+ return void 0;
970
+ }
971
+ register(_bot) {
972
+ }
973
+ unregister(_bot) {
974
+ }
975
+ };
976
+ function getReverseHub(ctx, path2) {
977
+ let byPath = reverseHubs.get(ctx);
978
+ if (!byPath) {
979
+ byPath = /* @__PURE__ */ new Map();
980
+ reverseHubs.set(ctx, byPath);
981
+ }
982
+ let hub = byPath.get(path2);
983
+ if (!hub) {
984
+ hub = new ReverseHub(ctx, path2);
985
+ byPath.set(path2, hub);
986
+ }
987
+ return hub;
988
+ }
989
+ __name(getReverseHub, "getReverseHub");
990
+ var WsServer = class extends import_koishi5.Adapter {
991
+ static {
992
+ __name(this, "WsServer");
993
+ }
994
+ static inject = ["server"];
995
+ logger;
996
+ hub;
997
+ constructor(ctx, bot) {
998
+ super(ctx);
999
+ this.logger = ctx.logger("onebot");
1000
+ const { path: path2 = "/onebot" } = bot.config;
1001
+ this.hub = getReverseHub(ctx, path2);
1002
+ this.hub.register(bot);
1003
+ ctx.on("dispose", () => {
1004
+ this.hub.unregister(bot);
969
1005
  });
970
1006
  }
971
1007
  async disconnect(bot) {
1008
+ ;
972
1009
  bot[kSocket]?.close();
973
1010
  bot[kSocket] = null;
1011
+ this.hub.unregister(bot);
974
1012
  }
975
1013
  };
976
1014
  ((WsServer2) => {
977
1015
  WsServer2.Options = import_koishi5.Schema.object({
978
1016
  protocol: import_koishi5.Schema.const("ws-reverse").required(process.env.KOISHI_ENV === "browser"),
979
- path: import_koishi5.Schema.string().description("服务器监听的路径。").default("/onebot"),
980
- responseTimeout: import_koishi5.Schema.natural().role("time").default(import_koishi5.Time.minute).description("等待响应的时间 (单位为毫秒)")
981
- }).description("连接设置");
1017
+ path: import_koishi5.Schema.string().description("?????????").default("/onebot"),
1018
+ responseTimeout: import_koishi5.Schema.natural().role("time").default(import_koishi5.Time.minute).description("??????? (?????)?")
1019
+ }).description("????");
982
1020
  })(WsServer || (WsServer = {}));
983
1021
  var counter = 0;
984
1022
  var listeners = {};
@@ -1000,15 +1038,15 @@ function accept(socket, bot) {
1000
1038
  }
1001
1039
  });
1002
1040
  socket.addEventListener("error", (event) => {
1003
- bot.logger.warn(`WebSocket 错误: ${event.message || "未知错误"}`);
1041
+ bot.logger.warn(`WebSocket ??: ${event.message || "????"}`);
1004
1042
  });
1005
1043
  socket.addEventListener("close", (event) => {
1006
1044
  delete bot.internal._request;
1007
- const closeInfo = `code: ${event.code}, reason: ${event.reason || ""}`;
1045
+ const closeInfo = `code: ${event.code}, reason: ${event.reason || "?"}`;
1008
1046
  if (event.code === 1009) {
1009
- bot.logger.error(`WebSocket 因消息过大断开 (${closeInfo}),协议端可能发送了超大消息`);
1047
+ bot.logger.error(`WebSocket ??????? (${closeInfo})?????????????`);
1010
1048
  } else if (event.code !== 1e3 && event.code !== 1001) {
1011
- bot.logger.warn(`WebSocket 连接关闭 (${closeInfo})`);
1049
+ bot.logger.warn(`WebSocket ???? (${closeInfo})`);
1012
1050
  }
1013
1051
  ;
1014
1052
  bot.ctx.emit("onebot-multi/bot-offline", bot);
@@ -1453,6 +1491,9 @@ var LoadBalancer = class {
1453
1491
  /**
1454
1492
  * 检查 Bot 是否在线
1455
1493
  */
1494
+ getEffectivePriorityChannels() {
1495
+ return new Set(this.config.priorityChannels || []);
1496
+ }
1456
1497
  isBotOnline(selfId) {
1457
1498
  const bot = this.ctx.bots.find((b) => b.selfId === selfId && b.platform === "onebot");
1458
1499
  return bot?.status === STATUS_ONLINE3;
@@ -1655,7 +1696,7 @@ var LoadBalancer = class {
1655
1696
  return;
1656
1697
  }
1657
1698
  const channels = [];
1658
- const prioritySet = new Set((this.config.priorityChannels || []).map((id) => String(id).trim()).filter(Boolean));
1699
+ const prioritySet = this.getEffectivePriorityChannels();
1659
1700
  for (const [channelId, bots] of this.allChannels.entries()) {
1660
1701
  channels.push({
1661
1702
  channelId,
@@ -1730,13 +1771,8 @@ var LoadBalancer = class {
1730
1771
  }
1731
1772
  }
1732
1773
  if (assignments.length > 0) {
1733
- const batchSize = 100;
1734
- for (let i = 0; i < assignments.length; i += batchSize) {
1735
- const slice = assignments.slice(i, i + batchSize);
1736
- await Promise.all(slice.map(async ({ channelId, assignee }) => {
1737
- await this.ctx.database.setChannel("onebot", channelId, { assignee });
1738
- this.lastAssignees.set(channelId, assignee);
1739
- }));
1774
+ for (const { channelId, assignee } of assignments) {
1775
+ this.lastAssignees.set(channelId, assignee);
1740
1776
  }
1741
1777
  }
1742
1778
  const botsWithData = onlineBots.filter((id) => {
@@ -2138,7 +2174,7 @@ var ConfigStore = class {
2138
2174
  var Config = import_koishi9.Schema.object({}).description("在侧边栏webui使用,配置文件在data/adapter-onebot-multi/config.yaml");
2139
2175
  var name = "adapter-onebot-multi";
2140
2176
  var inject = {
2141
- required: ["server", "database"],
2177
+ required: ["server"],
2142
2178
  optional: ["console"]
2143
2179
  };
2144
2180
  function apply(ctx, _config) {
@@ -2148,6 +2184,49 @@ function apply(ctx, _config) {
2148
2184
  const managedBotIds = /* @__PURE__ */ new Set();
2149
2185
  const botForks = /* @__PURE__ */ new Map();
2150
2186
  const getRuntimeConfig = /* @__PURE__ */ __name(() => configStore.getRuntime(), "getRuntimeConfig");
2187
+ const createPendingSelfId = /* @__PURE__ */ __name(() => {
2188
+ let candidate = `pending_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
2189
+ const exists = /* @__PURE__ */ __name((id) => configStore.getBots().some((bot) => bot.selfId === id), "exists");
2190
+ while (exists(candidate)) {
2191
+ candidate = `pending_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
2192
+ }
2193
+ return candidate;
2194
+ }, "createPendingSelfId");
2195
+ const isReverseTemplateBot = /* @__PURE__ */ __name((bot) => {
2196
+ return (bot.protocol || "ws-reverse") === "ws-reverse" && String(bot.selfId || "").startsWith("pending_");
2197
+ }, "isReverseTemplateBot");
2198
+ const findReverseTemplate = /* @__PURE__ */ __name((path2) => {
2199
+ return configStore.getBots().find((bot) => {
2200
+ if (bot.enabled === false) return false;
2201
+ if (!isReverseTemplateBot(bot)) return false;
2202
+ return (bot.path || "/onebot") === path2;
2203
+ });
2204
+ }, "findReverseTemplate");
2205
+ const findReverseSeedBot = /* @__PURE__ */ __name((path2) => {
2206
+ const bots = configStore.getBots().filter((bot) => {
2207
+ if (bot.enabled === false) return false;
2208
+ return (bot.protocol || "ws-reverse") === "ws-reverse" && (bot.path || "/onebot") === path2;
2209
+ });
2210
+ return bots.find(isReverseTemplateBot) || bots[0];
2211
+ }, "findReverseSeedBot");
2212
+ const ensureReverseTemplateRecord = /* @__PURE__ */ __name((path2) => {
2213
+ const normalizedPath = path2 || "/onebot";
2214
+ if (findReverseTemplate(normalizedPath)) return;
2215
+ const seedBot = findReverseSeedBot(normalizedPath);
2216
+ if (!seedBot) return;
2217
+ configStore.setBots([
2218
+ ...configStore.getBots(),
2219
+ {
2220
+ selfId: createPendingSelfId(),
2221
+ token: seedBot.token,
2222
+ protocol: "ws-reverse",
2223
+ path: normalizedPath,
2224
+ name: "服务器",
2225
+ enabled: true
2226
+ }
2227
+ ]);
2228
+ logger.info(`已为 path=${normalizedPath} 自动补齐 ws 服务器模板记录`);
2229
+ }, "ensureReverseTemplateRecord");
2151
2230
  const getGlobalConfig = /* @__PURE__ */ __name(() => {
2152
2231
  const runtime = getRuntimeConfig();
2153
2232
  return {
@@ -2246,6 +2325,42 @@ function apply(ctx, _config) {
2246
2325
  botForks.set(selfId, fork);
2247
2326
  managedBotIds.add(selfId);
2248
2327
  }, "startBot");
2328
+ const ensureReverseBot = /* @__PURE__ */ __name((selfId, path2) => {
2329
+ const normalizedSelfId = String(selfId || "").trim();
2330
+ const normalizedPath = path2 || "/onebot";
2331
+ if (!normalizedSelfId) return;
2332
+ const live = ctx.bots.find((bot) => bot.selfId === normalizedSelfId && bot.platform === "onebot");
2333
+ if (live) return live;
2334
+ const existing = configStore.getBots().find((bot) => {
2335
+ return bot.selfId === normalizedSelfId && (bot.protocol || "ws-reverse") === "ws-reverse";
2336
+ });
2337
+ if (existing) {
2338
+ startBot(existing);
2339
+ return ctx.bots.find((bot) => bot.selfId === normalizedSelfId && bot.platform === "onebot");
2340
+ }
2341
+ const template = findReverseTemplate(normalizedPath);
2342
+ const seedBot = template || findReverseSeedBot(normalizedPath);
2343
+ if (!seedBot) {
2344
+ logger.warn(`未找到 path=${normalizedPath} 的 ws-reverse 配置,拒绝动态创建 Bot ${normalizedSelfId}`);
2345
+ return;
2346
+ }
2347
+ if (!template) {
2348
+ ensureReverseTemplateRecord(normalizedPath);
2349
+ }
2350
+ const dynamicBot = {
2351
+ selfId: normalizedSelfId,
2352
+ token: seedBot.token,
2353
+ protocol: "ws-reverse",
2354
+ path: normalizedPath,
2355
+ name: seedBot.name && seedBot.name !== "服务器" ? seedBot.name : void 0,
2356
+ enabled: true
2357
+ };
2358
+ configStore.setBots([...configStore.getBots(), dynamicBot]);
2359
+ startBot(dynamicBot);
2360
+ logger.info(`已为反向 WS 连接动态创建 Bot ${normalizedSelfId} (${normalizedPath})`);
2361
+ return ctx.bots.find((bot) => bot.selfId === normalizedSelfId && bot.platform === "onebot");
2362
+ }, "ensureReverseBot");
2363
+ ctx._onebotMultiEnsureReverseBot = ensureReverseBot;
2249
2364
  const stopBot = /* @__PURE__ */ __name(async (selfId) => {
2250
2365
  try {
2251
2366
  const fork = botForks.get(selfId);
@@ -2269,6 +2384,13 @@ function apply(ctx, _config) {
2269
2384
  startBot(target);
2270
2385
  }, "restartBot");
2271
2386
  const syncBots = /* @__PURE__ */ __name(async () => {
2387
+ const currentBots = configStore.getBots();
2388
+ const reversePaths = new Set(
2389
+ currentBots.filter((bot) => (bot.protocol || "ws-reverse") === "ws-reverse").map((bot) => bot.path || "/onebot")
2390
+ );
2391
+ for (const path2 of reversePaths) {
2392
+ ensureReverseTemplateRecord(path2);
2393
+ }
2272
2394
  const bots = configStore.getBots();
2273
2395
  const enabledIds = new Set(bots.filter((b) => b.enabled !== false).map((b) => b.selfId));
2274
2396
  for (const selfId of Array.from(managedBotIds)) {
@@ -2284,14 +2406,6 @@ function apply(ctx, _config) {
2284
2406
  }
2285
2407
  }, "syncBots");
2286
2408
  const upsertBot = /* @__PURE__ */ __name((nextBot, oldSelfId) => {
2287
- const createPendingSelfId = /* @__PURE__ */ __name(() => {
2288
- let candidate = `pending_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
2289
- const exists = /* @__PURE__ */ __name((id) => configStore.getBots().some((bot) => bot.selfId === id), "exists");
2290
- while (exists(candidate)) {
2291
- candidate = `pending_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
2292
- }
2293
- return candidate;
2294
- }, "createPendingSelfId");
2295
2409
  const inputSelfId = String(nextBot.selfId || "").trim();
2296
2410
  const nextSelfId = inputSelfId || oldSelfId || createPendingSelfId();
2297
2411
  const all = configStore.getBots();
@@ -2312,39 +2426,39 @@ function apply(ctx, _config) {
2312
2426
  configStore.setBots(filtered);
2313
2427
  return nextSelfId;
2314
2428
  }, "upsertBot");
2315
- ctx.command("onebot.balance", "查看 OneBot 负载均衡状态").alias("ob.balance").alias("负载均衡").action(async () => {
2429
+ ctx.command("onebot.balance", "?? OneBot ??????").alias("ob.balance").alias("????").action(async () => {
2316
2430
  if (!configStore.getLoadBalance().enabled) {
2317
- return "负载均衡未启用。";
2431
+ return "????????";
2318
2432
  }
2319
2433
  const status = loadBalancer.getDetailedStatus();
2320
2434
  const elements = [];
2321
- elements.push(import_koishi9.h.text("═══ OneBot 负载均衡状态 ═══\n\n"));
2322
- elements.push(import_koishi9.h.text(`📊 总览
2435
+ elements.push(import_koishi9.h.text("??? OneBot ?????? ???\n\n"));
2436
+ elements.push(import_koishi9.h.text(`?? ??
2323
2437
  `));
2324
- elements.push(import_koishi9.h.text(` 在线 Bot: ${status.onlineBots}
2438
+ elements.push(import_koishi9.h.text(` ?? Bot: ${status.onlineBots} ?
2325
2439
  `));
2326
- elements.push(import_koishi9.h.text(` 管理群数: ${status.totalChannels}
2440
+ elements.push(import_koishi9.h.text(` ????: ${status.totalChannels} ?
2327
2441
  `));
2328
- elements.push(import_koishi9.h.text(` 已分配群: ${status.assignedChannels}
2442
+ elements.push(import_koishi9.h.text(` ????: ${status.assignedChannels} ?
2329
2443
  `));
2330
- elements.push(import_koishi9.h.text(` 未分配群: ${status.unassignedChannels}
2444
+ elements.push(import_koishi9.h.text(` ????: ${status.unassignedChannels} ?
2331
2445
 
2332
2446
  `));
2333
- elements.push(import_koishi9.h.text(`🤖 Bot 负载详情
2447
+ elements.push(import_koishi9.h.text(`?? Bot ????
2334
2448
  `));
2335
2449
  for (const bot of status.bots) {
2336
- const maxLoadStr = bot.maxLoad === 0 ? "无限制" : `${bot.maxLoad}`;
2337
- const remainingStr = bot.maxLoad === 0 ? "" : `${bot.remaining}`;
2450
+ const maxLoadStr = bot.maxLoad === 0 ? "???" : `${bot.maxLoad}`;
2451
+ const remainingStr = bot.maxLoad === 0 ? "?" : `${bot.remaining}`;
2338
2452
  const barLength = 20;
2339
2453
  const usedLength = bot.maxLoad === 0 ? Math.min(Math.round(bot.assignedCount / Math.max(bot.channelCount, 1) * barLength), barLength) : Math.round(bot.assignedCount / bot.maxLoad * barLength);
2340
- const bar = "".repeat(usedLength) + "".repeat(barLength - usedLength);
2454
+ const bar = "?".repeat(usedLength) + "?".repeat(barLength - usedLength);
2341
2455
  elements.push(import_koishi9.h.image(bot.avatarUrl));
2342
2456
  elements.push(import_koishi9.h.text("\n"));
2343
2457
  elements.push(import_koishi9.h.text(` ${bot.nickname} (${bot.selfId})
2344
2458
  `));
2345
- elements.push(import_koishi9.h.text(` 所在群: ${bot.channelCount} | 负责群: ${bot.assignedCount} | 上限: ${maxLoadStr}
2459
+ elements.push(import_koishi9.h.text(` ???: ${bot.channelCount} | ???: ${bot.assignedCount} | ??: ${maxLoadStr}
2346
2460
  `));
2347
- elements.push(import_koishi9.h.text(` 剩余容量: ${remainingStr}
2461
+ elements.push(import_koishi9.h.text(` ????: ${remainingStr}
2348
2462
  `));
2349
2463
  elements.push(import_koishi9.h.text(` [${bar}]
2350
2464
 
@@ -2407,7 +2521,7 @@ function apply(ctx, _config) {
2407
2521
  }, { authority: 4 });
2408
2522
  ctx2.console.addListener("onebot-multi/bots/profile", async ({ selfId, nickname }) => {
2409
2523
  const bot = ctx2.bots.find((b) => b.selfId === selfId && b.platform === "onebot");
2410
- if (!bot) return { success: false, error: `Bot ${selfId} 未在线` };
2524
+ if (!bot) return { success: false, error: `Bot ${selfId} ???` };
2411
2525
  await bot.internal.setQqProfile(nickname || "", "", "", "", "");
2412
2526
  const loginInfo = await bot.internal.getLoginInfo();
2413
2527
  if (loginInfo?.nickname) {
@@ -2417,7 +2531,7 @@ function apply(ctx, _config) {
2417
2531
  }, { authority: 4 });
2418
2532
  ctx2.console.addListener("onebot-multi/bots/avatar", async ({ selfId, file }) => {
2419
2533
  const bot = ctx2.bots.find((b) => b.selfId === selfId && b.platform === "onebot");
2420
- if (!bot) return { success: false, error: `Bot ${selfId} 未在线` };
2534
+ if (!bot) return { success: false, error: `Bot ${selfId} ???` };
2421
2535
  await bot.internal.setQqAvatar(file);
2422
2536
  return { success: true };
2423
2537
  }, { authority: 4 });
@@ -2443,7 +2557,7 @@ function apply(ctx, _config) {
2443
2557
  }, { authority: 4 });
2444
2558
  });
2445
2559
  ctx.on("ready", () => {
2446
- syncBots().catch((error) => logger.error("同步 Bot 启动状态失败: %s", error));
2560
+ syncBots().catch((error) => logger.error("?? Bot ??????: %s", error));
2447
2561
  });
2448
2562
  ctx.on("onebot-multi/bot-online", (bot) => {
2449
2563
  const configKey = String(bot.config?.managedKey || bot.selfId);
@@ -2458,7 +2572,7 @@ function apply(ctx, _config) {
2458
2572
  bot.config.managedKey = runtimeSelfId;
2459
2573
  managedBotIds.delete(configKey);
2460
2574
  managedBotIds.add(runtimeSelfId);
2461
- logger.info(`Bot 配置 selfId 自动更新: ${configKey} -> ${runtimeSelfId}`);
2575
+ logger.info(`Bot ?? selfId ????: ${configKey} -> ${runtimeSelfId}`);
2462
2576
  });
2463
2577
  ctx.on("dispose", async () => {
2464
2578
  stopConfigWatcher();
@@ -30,6 +30,7 @@ export declare class LoadBalancer {
30
30
  /**
31
31
  * 检查 Bot 是否在线
32
32
  */
33
+ private getEffectivePriorityChannels;
33
34
  private isBotOnline;
34
35
  /**
35
36
  * 获取所有在线的 OneBot
package/lib/ws.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Adapter, Context, HTTP, Logger, Schema, Universal } from 'koishi';
2
- import { WebSocketLayer } from '@koishijs/plugin-server';
3
2
  import type { OneBotBot } from './bot';
4
3
  export interface SharedConfig<T = 'ws' | 'ws-reverse'> {
5
4
  protocol: T;
@@ -19,7 +18,7 @@ export declare namespace WsClient {
19
18
  export declare class WsServer<C extends Context> extends Adapter<C, OneBotBot<C, any>> {
20
19
  static inject: string[];
21
20
  logger: Logger;
22
- wsServer?: WebSocketLayer;
21
+ private hub;
23
22
  constructor(ctx: C, bot: OneBotBot<C>);
24
23
  disconnect(bot: OneBotBot<C>): Promise<void>;
25
24
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-adapter-onebot-multi",
3
3
  "description": "奶龙bot定制版onebot适配器,支持自动负载均衡与黑白名单,控制台侧边栏管理",
4
- "version": "1.0.6",
4
+ "version": "2.0.1",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/lib/admin.d.ts DELETED
@@ -1,52 +0,0 @@
1
- import { Context } from 'koishi';
2
- import { ConfigManager, BotConfigRecord } from './config-manager';
3
- import { StatusManager, BotStatus } from './status';
4
- export interface BotFullInfo extends BotStatus {
5
- config: Omit<BotConfigRecord, 'token'>;
6
- }
7
- export interface AdminPanelData {
8
- bots: BotFullInfo[];
9
- updatedAt: number;
10
- }
11
- /**
12
- * Console 管理面板服务
13
- * 提供 Bot 配置的增删改查 API
14
- */
15
- export declare function setupAdminPanel(ctx: Context, configManager: ConfigManager, statusManager: StatusManager): void;
16
- declare module '@koishijs/console' {
17
- interface Events {
18
- 'onebot-multi/admin/list'(): Promise<AdminPanelData>;
19
- 'onebot-multi/admin/create'(data: {
20
- selfId: string;
21
- token?: string;
22
- protocol: 'ws' | 'ws-reverse';
23
- endpoint?: string;
24
- path?: string;
25
- }): Promise<{
26
- success: boolean;
27
- record: BotConfigRecord;
28
- }>;
29
- 'onebot-multi/admin/update'(data: {
30
- selfId: string;
31
- updates: {
32
- token?: string;
33
- protocol?: 'ws' | 'ws-reverse';
34
- endpoint?: string;
35
- path?: string;
36
- };
37
- }): Promise<{
38
- success: boolean;
39
- needRestart: boolean;
40
- }>;
41
- 'onebot-multi/admin/delete'(selfId: string): Promise<{
42
- success: boolean;
43
- }>;
44
- 'onebot-multi/admin/toggle'(selfId: string): Promise<{
45
- success: boolean;
46
- enabled: boolean;
47
- }>;
48
- 'onebot-multi/admin/restart'(selfId: string): Promise<{
49
- success: boolean;
50
- }>;
51
- }
52
- }
@@ -1,83 +0,0 @@
1
- import { Context } from 'koishi';
2
- import type { BotConfig } from './index';
3
- declare module 'koishi' {
4
- interface Tables {
5
- 'onebot_multi_bots': BotConfigRecord;
6
- }
7
- }
8
- export interface BotConfigRecord {
9
- id: number;
10
- name: string;
11
- selfId?: string;
12
- token?: string;
13
- protocol: 'ws' | 'ws-reverse';
14
- endpoint?: string;
15
- path?: string;
16
- enabled: boolean;
17
- createdAt: Date;
18
- updatedAt: Date;
19
- }
20
- export declare class ConfigManager {
21
- private ctx;
22
- constructor(ctx: Context);
23
- /**
24
- * 获取存储的密码哈希
25
- */
26
- private getStoredPasswordHash;
27
- /**
28
- * 设置管理密码(哈希存储)
29
- */
30
- setAdminPassword(password: string): Promise<void>;
31
- /**
32
- * 检查是否已设置密码
33
- */
34
- hasAdminPassword(): Promise<boolean>;
35
- /**
36
- * 验证管理密码
37
- */
38
- verifyAdminPassword(password: string): Promise<boolean>;
39
- /**
40
- * 获取所有 Bot 配置(排除系统配置)
41
- */
42
- getAllConfigs(): Promise<BotConfigRecord[]>;
43
- /**
44
- * 获取启用的 Bot 配置(排除系统配置)
45
- */
46
- getEnabledConfigs(): Promise<BotConfigRecord[]>;
47
- /**
48
- * 根据 ID 获取单个 Bot 配置
49
- */
50
- getConfigById(id: number): Promise<BotConfigRecord | undefined>;
51
- /**
52
- * 根据 selfId 获取配置(用于关联运行时 Bot)
53
- */
54
- getConfigBySelfId(selfId: string): Promise<BotConfigRecord | undefined>;
55
- /**
56
- * 创建 Bot 配置
57
- */
58
- createConfig(config: Omit<BotConfigRecord, 'id' | 'selfId' | 'createdAt' | 'updatedAt'> & {
59
- selfId?: string;
60
- }): Promise<BotConfigRecord>;
61
- /**
62
- * 更新 Bot 配置(根据 ID)
63
- */
64
- updateConfigById(id: number, updates: Partial<Omit<BotConfigRecord, 'id' | 'createdAt'>>): Promise<boolean>;
65
- /**
66
- * 删除 Bot 配置(根据 ID)
67
- */
68
- deleteConfigById(id: number): Promise<boolean>;
69
- /**
70
- * 切换 Bot 启用状态
71
- */
72
- toggleEnabled(id: number): Promise<boolean>;
73
- /**
74
- * 更新配置的 selfId(Bot 连接成功后调用)
75
- */
76
- updateSelfId(id: number, selfId: string): Promise<boolean>;
77
- /**
78
- * 将数据库配置转换为 BotConfig 格式(用于启动 Bot)
79
- */
80
- toBotConfig(record: BotConfigRecord): BotConfig & {
81
- configId: number;
82
- };
83
- }
package/lib/csv-sync.d.ts DELETED
@@ -1,19 +0,0 @@
1
- import { Context } from 'koishi';
2
- import { ConfigStore } from './config-store';
3
- import { LoadBalancer } from './load-balancer';
4
- export declare class CsvSyncManager {
5
- private ctx;
6
- private configStore;
7
- private loadBalancer;
8
- private logger;
9
- private csvPath;
10
- constructor(ctx: Context, configStore: ConfigStore, loadBalancer: LoadBalancer);
11
- /**
12
- * 手动触发同步 CSV 到 PriorityChannels
13
- */
14
- syncFromCsv(): {
15
- success: boolean;
16
- count: number;
17
- error?: string;
18
- };
19
- }
package/lib/panel.d.ts DELETED
@@ -1,25 +0,0 @@
1
- import { Context, Schema } from 'koishi';
2
- import { StatusManager } from './status';
3
- import { ConfigManager } from './config-manager';
4
- export interface PanelConfig {
5
- enabled?: boolean;
6
- basePath?: string;
7
- port?: number;
8
- }
9
- export declare const PanelConfig: Schema<PanelConfig>;
10
- export declare class StatusPanel {
11
- private ctx;
12
- private config;
13
- private statusManager;
14
- private configManager;
15
- private app?;
16
- private server?;
17
- constructor(ctx: Context, config: PanelConfig, statusManager: StatusManager, configManager: ConfigManager);
18
- private parseJsonBody;
19
- private setupRoutes;
20
- private startBot;
21
- private stopBot;
22
- private renderAdminApp;
23
- private renderStatusPage;
24
- private formatUptime;
25
- }