Единое мобильное приложение для менеджеров: объединяет Telegram, WhatsApp, Signal, Matrix + локальная LLM для подсказок в реальном времени.
MessengerHub — единый домен "коммуникации менеджера", а не набор отдельных мессенджер-интеграций
src/Bundles/MessengerHub/. Не per-messenger бандлы.
Граница домена — "unified manager communications", а не "telegram integration".
Adapter pattern внутри одного бандла проще поддерживать. Разбиение на 3 бандла (MessengerChannel, MessageStore, MessengerLLM)
создало бы ненужные cross-bundle зависимости.
Нажмите на канал для деталей подключения
Переиспользуем существующий TelegramBotEntity с новым полем is_messenger_hub. Webhook handler роутит MH-бот сообщения на ChannelAdapterManager::dispatch().
| Параметр | Значение |
|---|---|
| E2EE | Нет (bot chats) |
| Статусы доставки | Частичные |
| Multi-tenancy | 1 бот / брокер |
| Код | Существует — расширяем |
Официальный Cloud API. MTProto bridge отклонён (нарушение ToS, ненадёжно). Требуется WhatsApp Business Account на каждого брокера.
| Параметр | Значение |
|---|---|
| E2EE | Да |
| Статусы доставки | Да |
| Multi-tenancy | 1 WABA / брокер |
| Код | С нуля |
signal-cli daemon в Docker-контейнере, JSON-RPC через Unix socket. Один демон на брокера (1 номер = 1 демон). Нет статусов доставки.
| Параметр | Значение |
|---|---|
| E2EE | Да |
| Статусы доставки | Нет |
| Multi-tenancy | 1 номер / брокер |
| Код | С нуля |
Synapse homeserver + Application Service (webhook-style, лучше long-poll). Один бот-пользователь на брокера.
| Параметр | Значение |
|---|---|
| E2EE | Да (Megolm) |
| Статусы доставки | Да |
| Multi-tenancy | 1 bot-user / брокер |
| Код | С нуля |
Интерфейс мобильного приложения менеджера
Нажмите на тип для просмотра примера API-ответа
3-5 вариантов быстрого ответа на сообщение клиента
Краткая сводка диалога + CRM-контекст
AML-триггеры, подозрительные паттерны
Условия сделки на основе истории
Анализ настроения клиента
Запрос: POST /api/v2/messenger/conversations/{id}/assist
Request: { "type": "quick_reply" }
Response: {
"type": "quick_reply",
"suggestions": [
"Курс сейчас 92.5 за USDT, могу зафиксировать на 30 минут",
"Минимальная сумма обмена 1000 USDT",
"Могу предложить 92.3 при объёме от 10,000 USDT"
],
"confidence": 0.85
}
Response: {
"type": "summary",
"text": "Клиент Ivan Petrov (VIP, Москва) хочет обменять
5000 USDT на рубли. Предыдущие 3 сделки:
суммы 2000-8000 USDT, средний курс 91.8.
Клиент лоялен, но чувствителен к курсу."
}
Response: {
"type": "risk_alert",
"alerts": [{
"level": "medium",
"text": "Клиент упоминает третье лицо как получателя
— возможный structuring (дробление операций)"
}]
}
AML red flags: дробление крупных сделок, срочность без объяснений + отказ от KYC, несоответствие суммы профилю, "анонимность" / "без документов" / "серые схемы", страны из FATF black/grey list.
Response: {
"type": "deal_suggest",
"suggestion": {
"instrument": "USDT-TRC20",
"amount": 50000,
"rate": 92.5,
"reason": "Клиент регулярный (3 сделки/мес),
объём растёт. Рекомендуемая скидка 0.3%"
}
}
Response: {
"type": "sentiment",
"sentiment": "neutral_to_positive",
"signals": ["вежливый тон", "конкретные суммы",
"не торгуется агрессивно"],
"recommendation": "Клиент настроен на сделку,
не затягивайте с ответом"
}
От клиента в Telegram до подсказки на экране менеджера
Flutter + Riverpod + SQLCipher. Offline-First: локальная БД = источник правды для UI
// Riverpod: стрим сообщений чата @riverpod Stream<List<Message>> chatMessages(Ref ref, String chatId) async* { // 1. Сначала из локальной БД — мгновенно yield await ref.read(localDbProvider).getMessages(chatId, limit: 50); // 2. Затем подписка на WebSocket дельты yield* ref.read(wsProvider).messageStream(chatId); } // Offline-First алгоритм отправки: // 1. Сохранить в SQLCipher со статусом PENDING // 2. UI показывает с индикатором "отправляется" // 3. Отправить в очередь (dart:isolate) // 4. Успех → статус SENT / Ошибка → статус ERROR + кнопка "повтор"
Какие бандлы переиспользуем и что расширяем
| Бандл | Как используется | Что расширяем |
|---|---|---|
TelegramBots |
TelegramAdapter использует TelegramBotCredentialsService, TelegramHttpClient | TelegramBotEntity + поле is_messenger_hub; webhook — новая ветка для MH-ботов |
CRM |
PartnerEntity в LLM-контексте; привязка чата к сделке | Только чтение, не расширяем |
AiChat |
AiChatOpenAiClient + OpenAiFactory для Ollama | Как есть, BASE_URL = localhost:11435/v1 |
Encryption |
EncryptionRepository для шифрованных сообщений | Не расширяем |
Notification |
NotificationEntity для in-app; новый PushNotificationService для FCM/APNs | + мобильные push-уведомления |
Acl |
Права доступа менеджеров к чатам | Новые ACL-ресурсы: MessengerHub.View/.Send/.Assist/.Admin |
Найденные уязвимости в существующем коде, влияющие на Messenger Hub
Файл app/credentials.txt с plaintext admin-паролем в репозитории
root/pass во всех docker-compose файлах
UserRoleRepository.php (getRawList) — прямая конкатенация строк
Любой может отправить фейковые updates — критично для Messenger Hub
AiChat Redis Storage — брокер A может видеть чаты брокера B
Нет санитизации ввода перед отправкой в LLM. Клиент может инъецировать промпт через сообщение
Данные переписок НЕ уходят на внешние API (OpenAI, Anthropic). Только localhost:11435. Это снимает основные GDPR-проблемы cross-border transfer.
Не более 10 LLM-запросов в минуту на пользователя. Redis counter. Все запросы логируются (без контента) для аудита.
Хранить все коммуникации 5 лет. Retention policy. AML-мониторинг в чатах через risk_alert. SAR-процедура.
Параллельный поток разработки, не блокирует основную архитектуру
Всё в одном месте: Entity, Adapter, Service, LLM, Api, Queue
src/Bundles/MessengerHub/ MessengerHubComponent.php Routes.php adminMenu.php Entity/ ConversationEntity.php // Чат (channel + contact + status) MessageEntity.php // Сообщение (encrypted content) ChannelAccountEntity.php // Подключённый канал брокера MessageAttachmentEntity.php // Медиа-файлы Enum/ ChannelType.php // Telegram | WhatsApp | Signal | Matrix MessageDirection.php // Inbound | Outbound MessageStatus.php // Sent | Delivered | Read | Failed ConversationStatus.php // Active | Archived | Blocked Adapter/ ChannelAdapterInterface.php // connect, disconnect, sendMessage, handleWebhook ChannelAdapterManager.php // Роутинг по ChannelType Telegram/TelegramChannelAdapter.php WhatsApp/WhatsAppChannelAdapter.php Signal/SignalChannelAdapter.php Matrix/MatrixChannelAdapter.php Service/ ConversationService.php // handleInbound, создание/архивация чатов MessageService.php // отправка через адаптер EncryptedMessageStore.php // AES-256-GCM at rest WebSocketBroadcastService.php // push к менеджеру PushNotificationService.php // FCM / APNs LLM/ LLMPipelineService.php // Оркестратор 5 типов подсказок ContextBuilder.php // Сборка контекста: messages + CRM data PromptTemplates.php // System prompts для каждого типа Api/ ConversationsEndpoint.php // GET /api/v2/messenger/conversations MessagesEndpoint.php // GET/POST /api/v2/messenger/messages AssistEndpoint.php // POST /api/v2/messenger/.../assist ChannelsEndpoint.php // CRUD каналов SyncEndpoint.php // Delta sync для мобильного Queue/Handler/ InboundMessageHandler.php // Обработка входящих OutboundMessageHandler.php // Очередь исходящих LLMAnalysisHandler.php // Async LLM inference DTO/ UnifiedMessage.php // Универсальный формат SendMessageRequest.php ConversationListItem.php LLMAssistResponse.php WebSocket/ MessengerHubWsHandler.php // RoadRunner WS plugin