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, 'Не удалось определить, какому боту передать сообщение.' ) } }