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.
- package/lib/index.js +122 -4
- 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
|
-
|
|
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
|
-
|
|
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;
|