koishi-plugin-msg-router 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/index.js +122 -4
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -203,6 +203,8 @@ class RouteRuntime {
203
203
  queue = [];
204
204
  closed = false;
205
205
  lastPong = 0;
206
+ recentGroupSessions = new Map();
207
+ recentPrivateSessions = new Map();
206
208
  constructor(ctx, config, route) {
207
209
  this.ctx = ctx;
208
210
  this.config = config;
@@ -273,6 +275,14 @@ class RouteRuntime {
273
275
  this.ctx.logger(exports.name).debug(`route ${this.routeLabel} command content: ${JSON.stringify(content)}`);
274
276
  }
275
277
  const event = buildOneBotMessageEvent(session, commandName, content);
278
+ const isGroup = Boolean(session?.guildId != null
279
+ || (session?.channelId != null && String(session.channelId) !== String(session?.userId ?? '')));
280
+ if (isGroup && session?.channelId) {
281
+ this.recentGroupSessions.set(String(session.channelId), session);
282
+ }
283
+ else if (session?.userId) {
284
+ this.recentPrivateSessions.set(String(session.userId), session);
285
+ }
276
286
  this.sendEvent(event);
277
287
  return undefined; // We do not return a reply here. Standard OB11 backends reply using send_msg API calls.
278
288
  }
@@ -469,10 +479,22 @@ class RouteRuntime {
469
479
  return sendResponse({ status: 'failed', retcode: 100, msg: 'Missing user_id or message', data: null });
470
480
  }
471
481
  const bot = this.ctx.bots.find(b => b.selfId === String(data.params?.self_id)) || this.ctx.bots[0];
472
- if (bot) {
482
+ const session = this.recentPrivateSessions.get(String(userId));
483
+ if (session && (!data.params?.self_id || session.bot?.selfId === String(data.params?.self_id))) {
484
+ try {
485
+ const msgIds = await session.send(toElements(message));
486
+ const msgId = (Array.isArray(msgIds) && msgIds.length > 0) ? (Number(msgIds[0]) || Math.floor(Math.random() * 1000000)) : (typeof msgIds === 'string' ? msgIds : Math.floor(Math.random() * 1000000));
487
+ sendResponse({ status: 'ok', retcode: 0, data: { message_id: msgId } });
488
+ }
489
+ catch (e) {
490
+ this.ctx.logger(exports.name).error(`[send_private_msg] Failed to send via session to ${userId}:`, e);
491
+ sendResponse({ status: 'failed', retcode: 100, msg: String(e), data: null });
492
+ }
493
+ }
494
+ else if (bot) {
473
495
  try {
474
496
  const msgIds = await bot.sendPrivateMessage(String(userId), toElements(message));
475
- const msgId = msgIds && msgIds.length > 0 ? (Number(msgIds[0]) || Math.floor(Math.random() * 1000000)) : Math.floor(Math.random() * 1000000);
497
+ const msgId = (Array.isArray(msgIds) && msgIds.length > 0) ? (Number(msgIds[0]) || Math.floor(Math.random() * 1000000)) : (typeof msgIds === 'string' ? msgIds : Math.floor(Math.random() * 1000000));
476
498
  sendResponse({ status: 'ok', retcode: 0, data: { message_id: msgId } });
477
499
  }
478
500
  catch (e) {
@@ -492,10 +514,22 @@ class RouteRuntime {
492
514
  return sendResponse({ status: 'failed', retcode: 100, msg: 'Missing group_id or message', data: null });
493
515
  }
494
516
  const bot = this.ctx.bots.find(b => b.selfId === String(data.params?.self_id)) || this.ctx.bots[0];
495
- if (bot) {
517
+ const session = this.recentGroupSessions.get(String(groupId));
518
+ if (session && (!data.params?.self_id || session.bot?.selfId === String(data.params?.self_id))) {
519
+ try {
520
+ const msgIds = await session.send(toElements(message));
521
+ const msgId = (Array.isArray(msgIds) && msgIds.length > 0) ? (Number(msgIds[0]) || Math.floor(Math.random() * 1000000)) : (typeof msgIds === 'string' ? msgIds : Math.floor(Math.random() * 1000000));
522
+ sendResponse({ status: 'ok', retcode: 0, data: { message_id: msgId } });
523
+ }
524
+ catch (e) {
525
+ this.ctx.logger(exports.name).error(`[send_group_msg] Failed to send via session to ${groupId}:`, e);
526
+ sendResponse({ status: 'failed', retcode: 100, msg: String(e), data: null });
527
+ }
528
+ }
529
+ else if (bot) {
496
530
  try {
497
531
  const msgIds = await bot.sendMessage(String(groupId), toElements(message));
498
- const msgId = msgIds && msgIds.length > 0 ? (Number(msgIds[0]) || Math.floor(Math.random() * 1000000)) : Math.floor(Math.random() * 1000000);
532
+ const msgId = (Array.isArray(msgIds) && msgIds.length > 0) ? (Number(msgIds[0]) || Math.floor(Math.random() * 1000000)) : (typeof msgIds === 'string' ? msgIds : Math.floor(Math.random() * 1000000));
499
533
  sendResponse({ status: 'ok', retcode: 0, data: { message_id: msgId } });
500
534
  }
501
535
  catch (e) {
@@ -508,6 +542,90 @@ class RouteRuntime {
508
542
  }
509
543
  return;
510
544
  }
545
+ const bot = this.ctx.bots.find(b => b.selfId === String(data.params?.self_id)) || this.ctx.bots[0];
546
+ if (!bot) {
547
+ return sendResponse({ status: 'failed', retcode: 100, msg: 'No Koishi bot available', data: null });
548
+ }
549
+ try {
550
+ if (data.action === 'delete_msg') {
551
+ const messageId = String(data.params?.message_id);
552
+ if (!messageId)
553
+ throw new Error('Missing message_id');
554
+ // In OneBot, we only get message_id, not channel_id. But Satori requires channelId to delete.
555
+ // A naive fallback if channel_id is not provided is to try to guess it, but standard OB11 doesn't provide channel_id.
556
+ // We will attempt deletion if channel_id is provided, or fail.
557
+ const channelId = String(data.params?.channel_id || data.params?.group_id || '');
558
+ if (!channelId)
559
+ throw new Error('Cannot delete message without channel_id/group_id context in Satori');
560
+ await bot.deleteMessage(channelId, messageId);
561
+ return sendResponse({ status: 'ok', retcode: 0, data: null });
562
+ }
563
+ if (data.action === 'get_login_info') {
564
+ return sendResponse({
565
+ status: 'ok',
566
+ retcode: 0,
567
+ data: {
568
+ user_id: toOneBotId(bot.selfId),
569
+ nickname: bot.user?.name || bot.user?.nick || 'bot',
570
+ }
571
+ });
572
+ }
573
+ if (data.action === 'set_group_ban') {
574
+ const groupId = String(data.params?.group_id);
575
+ const userId = String(data.params?.user_id);
576
+ const duration = Number(data.params?.duration) * 1000; // OB11 is seconds, Koishi is ms
577
+ if (!groupId || !userId)
578
+ throw new Error('Missing group_id or user_id');
579
+ await bot.muteGuildMember(groupId, userId, duration);
580
+ return sendResponse({ status: 'ok', retcode: 0, data: null });
581
+ }
582
+ if (data.action === 'set_group_kick') {
583
+ const groupId = String(data.params?.group_id);
584
+ const userId = String(data.params?.user_id);
585
+ if (!groupId || !userId)
586
+ throw new Error('Missing group_id or user_id');
587
+ await bot.kickGuildMember(groupId, userId);
588
+ return sendResponse({ status: 'ok', retcode: 0, data: null });
589
+ }
590
+ if (data.action === 'get_group_member_info') {
591
+ const groupId = String(data.params?.group_id);
592
+ const userId = String(data.params?.user_id);
593
+ if (!groupId || !userId)
594
+ throw new Error('Missing group_id or user_id');
595
+ const member = await bot.getGuildMember(groupId, userId);
596
+ return sendResponse({
597
+ status: 'ok',
598
+ retcode: 0,
599
+ data: {
600
+ group_id: toOneBotId(groupId),
601
+ user_id: toOneBotId(userId),
602
+ nickname: member.user?.name || member.nick || '',
603
+ card: member.nick || '',
604
+ role: member.roles?.includes('admin') || member.roles?.includes('owner') ? 'admin' : 'member'
605
+ }
606
+ });
607
+ }
608
+ if (data.action === 'get_group_info') {
609
+ const groupId = String(data.params?.group_id);
610
+ if (!groupId)
611
+ throw new Error('Missing group_id');
612
+ const guild = await bot.getGuild(groupId);
613
+ return sendResponse({
614
+ status: 'ok',
615
+ retcode: 0,
616
+ data: {
617
+ group_id: toOneBotId(groupId),
618
+ group_name: guild.name || '',
619
+ member_count: 0,
620
+ max_member_count: 0,
621
+ }
622
+ });
623
+ }
624
+ }
625
+ catch (e) {
626
+ this.ctx.logger(exports.name).warn(`[${data.action}] Native delegation failed:`, e);
627
+ return sendResponse({ status: 'failed', retcode: 100, msg: String(e), data: null });
628
+ }
511
629
  // Unsupported action fallback
512
630
  sendResponse({ status: 'failed', retcode: 102, msg: 'Unsupported API action', data: null });
513
631
  return;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-msg-router",
3
3
  "description": "OneBot v11 WebSocket 消息转发插件",
4
- "version": "1.0.0",
4
+ "version": "1.0.2",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [