71 lines
2.9 KiB
JavaScript
71 lines
2.9 KiB
JavaScript
|
|
import { isOwner } from '../config.js';
|
|||
|
|
import { detectMediaFromBusiness } from '../core/media.js';
|
|||
|
|
import { logger } from '../core/logger.js';
|
|||
|
|
import { runHook } from '../core/registry.js';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Подписывает бота на бизнес-апдейты Telegram и раздаёт их модулям через хуки.
|
|||
|
|
* Работает через официальное бизнес-подключение (Настройки → Telegram для
|
|||
|
|
* бизнеса → Чат-боты) — никакой сессии, только апдейты от подключённого аккаунта.
|
|||
|
|
*
|
|||
|
|
* Событие удаления (deleted_business_messages) несёт только id сообщений и чат —
|
|||
|
|
* без содержимого. Поэтому модуль cache складывает каждое входящее заранее,
|
|||
|
|
* а antidelete достаёт его из кэша по (chatId, msgId).
|
|||
|
|
*/
|
|||
|
|
export function wireBusiness(bot, registry, ctx) {
|
|||
|
|
bot.on('business_message', (gctx) =>
|
|||
|
|
runHook(registry, 'onMessage', normalizeBusinessMessage(gctx), ctx),
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
bot.on('edited_business_message', (gctx) =>
|
|||
|
|
runHook(registry, 'onEdited', normalizeBusinessMessage(gctx), ctx),
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
bot.on('deleted_business_messages', (gctx) => {
|
|||
|
|
const d = gctx.deletedBusinessMessages;
|
|||
|
|
return runHook(
|
|||
|
|
registry,
|
|||
|
|
'onDeleted',
|
|||
|
|
{ chatId: d.chat?.id, msgIds: d.message_ids ?? [] },
|
|||
|
|
ctx,
|
|||
|
|
);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
bot.on('business_connection', (gctx) => {
|
|||
|
|
const c = gctx.businessConnection;
|
|||
|
|
if (c?.is_enabled) {
|
|||
|
|
logger.info(`Бизнес-подключение активно (id ${c.id})`);
|
|||
|
|
} else {
|
|||
|
|
logger.warn(`Бизнес-подключение отключено владельцем (id ${c?.id}). Перехват приостановлен.`);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
logger.debug('бизнес-апдейты подписаны: message / edited / deleted / connection');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Приводит grammY-контекст бизнес-сообщения к плоскому виду, понятному модулям.
|
|||
|
|
* isPrivateIncoming — входящее в личном 1-на-1 чате, не от самого владельца.
|
|||
|
|
*/
|
|||
|
|
export function normalizeBusinessMessage(gctx) {
|
|||
|
|
const msg = gctx.businessMessage ?? gctx.editedBusinessMessage ?? gctx.msg;
|
|||
|
|
const from = msg?.from;
|
|||
|
|
const chat = msg?.chat;
|
|||
|
|
return {
|
|||
|
|
chatId: chat?.id,
|
|||
|
|
msgId: msg?.message_id,
|
|||
|
|
senderId: from?.id,
|
|||
|
|
sender: senderLabel(from),
|
|||
|
|
text: msg?.text ?? msg?.caption ?? '',
|
|||
|
|
media: detectMediaFromBusiness(msg),
|
|||
|
|
// Свои исходящие отсекаем через isOwner (как раньше через message.out).
|
|||
|
|
isPrivateIncoming: chat?.type === 'private' && !isOwner(from?.id),
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function senderLabel(from) {
|
|||
|
|
if (!from) return '';
|
|||
|
|
const name = [from.first_name, from.last_name].filter(Boolean).join(' ');
|
|||
|
|
return from.username ? `${name} (@${from.username})`.trim() : name;
|
|||
|
|
}
|