157 lines
4.7 KiB
JavaScript
157 lines
4.7 KiB
JavaScript
import { getLockingBot } from './session.js'
|
||
import { findCommandTargetBot } from './commandMatcher.js'
|
||
import { routeByLLM } from './llmRouter.js'
|
||
import { getOrCreateUserAndGroups } from '../userService.js'
|
||
import { filterBotsAndCommandsByUserGroups } from '../groupFilter.js'
|
||
import { checkUserBotRights, checkUserCommandRights } from './rights.js'
|
||
import { getChannel } from '../utils/rmq.js' // <-- импорт канала
|
||
|
||
|
||
const updateKeys = [
|
||
'message',
|
||
'edited_message',
|
||
'channel_post',
|
||
'edited_channel_post',
|
||
'business_connection',
|
||
'business_message',
|
||
'edited_business_message',
|
||
'deleted_business_messages',
|
||
'message_reaction',
|
||
'message_reaction_count',
|
||
'inline_query',
|
||
'chosen_inline_result',
|
||
'callback_query',
|
||
'shipping_query',
|
||
'pre_checkout_query',
|
||
'purchased_paid_media',
|
||
'poll',
|
||
'poll_answer',
|
||
'my_chat_member',
|
||
'chat_member',
|
||
'chat_join_request',
|
||
'chat_boost',
|
||
'removed_chat_boost'
|
||
];
|
||
|
||
export async function handleIncomingMessage(ctx) {
|
||
|
||
//console.log('ctx',ctx);
|
||
const { update, ext, prisma } = ctx
|
||
|
||
const foundKey = updateKeys.find(key => update[key] !== undefined);
|
||
|
||
const msg = update[foundKey];
|
||
|
||
const channel = getChannel()
|
||
|
||
// 1) Пользователь и группы
|
||
const { user, userId, groups } = await getOrCreateUserAndGroups(ctx.prisma, msg.from)
|
||
|
||
msg['innerUserId'] = userId;
|
||
|
||
console.log('ext',ext);
|
||
|
||
// 0) Подтягиваем актуальный externalBot вместе с bots, commands и groups
|
||
const fullExt = await prisma.externalBot.findUnique({
|
||
where: { id: ext.id },
|
||
include: {
|
||
bots: {
|
||
include: {
|
||
commands: { include: { groupIds: true } },
|
||
groups: true
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
console.log('fullExt',fullExt);
|
||
|
||
if (!fullExt) {
|
||
return ctx.bot.sendMessage(msg.chat.id, 'Internal error: external bot not found')
|
||
}
|
||
|
||
// 2) Доступные боты
|
||
const availableBots = filterBotsAndCommandsByUserGroups(fullExt.bots, groups)
|
||
.filter(b => b.isActive)
|
||
|
||
console.log('availableBots',availableBots);
|
||
|
||
// 3) Захват внимания в сессии
|
||
const sessionBotID = await getLockingBot(userId,ext.id);
|
||
console.log('sessionBotID',sessionBotID);
|
||
if (sessionBotID) {
|
||
const sessionBotName = (availableBots.find(b => b.id === sessionBotID) || {}).name || null
|
||
if(sessionBotName){
|
||
if (!checkUserBotRights(availableBots, sessionBotName)) {
|
||
return ctx.bot.sendMessage(msg.chat.id, 'Нет доступа к боту.')
|
||
}
|
||
// Публикуем в очередь
|
||
const inQ = `InMessage${sessionBotName}`
|
||
channel.sendToQueue(inQ, Buffer.from(JSON.stringify({
|
||
update,
|
||
userId,
|
||
reason: 'session_capture'
|
||
})), { persistent: true })
|
||
return
|
||
}else{
|
||
await unlockSession(userId,ext.id)
|
||
return ctx.bot.sendMessage(msg.chat.id, 'Нет доступа к выбранному боту.')
|
||
}
|
||
}
|
||
|
||
// 4) Чёткая команда
|
||
if(msg?.text){
|
||
const commandMatch = findCommandTargetBot(msg.text, availableBots)
|
||
if (commandMatch) {
|
||
const { botName, commandName } = commandMatch
|
||
if (!checkUserCommandRights(availableBots, botName, commandName)) {
|
||
return ctx.bot.sendMessage(msg.chat.id, 'Нет доступа к команде.')
|
||
}
|
||
const inQ = `InMessage${botName}`
|
||
channel.sendToQueue(inQ, Buffer.from(JSON.stringify({
|
||
update,
|
||
userId,
|
||
command: commandName,
|
||
reason: 'explicit_command'
|
||
})), { persistent: true })
|
||
return
|
||
}
|
||
|
||
// 5) LLM‑роутинг
|
||
const llmInput = availableBots.map(b => ({
|
||
name: b.name,
|
||
description: b.description || 'Без описания'
|
||
}))
|
||
const llmResult = await routeByLLM(msg.text, llmInput)
|
||
const targetBot = llmResult.bot
|
||
|
||
if (targetBot && targetBot !== 'unknown') {
|
||
if (!checkUserBotRights(availableBots, targetBot)) {
|
||
return ctx.bot.sendMessage(msg.chat.id, 'Нет доступа к выбранному боту.')
|
||
}
|
||
const inQ = `InMessage${targetBot}`
|
||
const ok = channel.sendToQueue(inQ, Buffer.from(JSON.stringify({
|
||
update,
|
||
userId,
|
||
reason: llmResult.reason
|
||
})), { persistent: true })
|
||
|
||
if (!ok) {
|
||
// буфер переполнен, подождём drain
|
||
channel.once('drain', () => {
|
||
console.log('Канал освободился, можно отправлять дальше')
|
||
})
|
||
}else{
|
||
console.log('Отправили в ',inQ)
|
||
}
|
||
return
|
||
}
|
||
|
||
// 6) Не смогли определить бота — уведомляем сразу
|
||
return ctx.bot.sendMessage(
|
||
msg.chat.id,
|
||
'Не удалось определить, какому боту передать сообщение.'
|
||
)
|
||
}
|
||
}
|