Перейти к основному контенту

Адаптация Telegram-плагина под VK

Название плагина Vk
Код плагина Common.Integrations.Vk
Разработчик Официальные плагины от Metabot
Авторы Metabot
Дата создания 09 Октября 2026
Последняя дата обновления 09 Октября 2026

Описание

Плагин Vk позволяет использовать один и тот же скрипт бота в Telegram, Max и VK. Он не вводит новый класс: плагин «патчит» методы класса TelegramMessage из плагина Common.Integrations.Telegram.

  • Если лид пришёл из Telegram — вызывается исходный метод Telegram (или патч Max, если он подключён раньше).
  • Если лид пришёл из Max — срабатывает Max-патч.
  • Если лид пришёл из VK — те же самые методы (send, edit, addReplyToText, removeInlineKeyboard, removeReplyKeyboard, getMessagePayload, debug) отправляют запросы в VK API.

Плагин поддерживает отправку текстовых сообщений, создание inline-клавиатур (кнопки text и open_link), обработку нажатий и текстового ввода, а также отправку медиагрупп (по одному вложению). PHP-драйвер VK не меняется: часть поведения Telegram/Max в VK осознанно деградирует (см. таблицу совместимости).

Документация VK API: https://dev.vk.com/method/messages.send

Подключение

Сначала подключается Telegram-плагин, затем при необходимости Max, затем — Vk. Порядок важен: Vk патчит уже загруженный класс. Повторное подключение безопасно (патч ставится один раз).

let TelegramMessage = require('Common.Integrations.Telegram')
require('Common.Integrations.Max') // опционально
require('Common.Integrations.Vk')

let msg = new TelegramMessage()

Больше ничего в скрипте менять не нужно: проверять канал (if (isVk)) не требуется.

Основные параметры

msg.text = "Ваше сообщение" // Текст сообщения
msg.parse_mode = "HTML" // В VK разметка снимается до plain text
msg.keyboard = "Да[yes]==Нет[no]" // Создание клавиатуры
msg.entities = [] // В VK игнорируются (текст очищается так же, как при parse_mode)
Параметр Telegram Max VK
text text text message (plain)
parse_mode parse_mode format (HTML → html, Markdown/MarkdownV2 → markdown) strip → plain
keyboard inline-клавиатура вложение inline_keyboard VK keyboard JSON (inline: true)
entities entities преобразуются в HTML strip
protect_content поддерживается игнорируется игнорируется

Форматы клавиатуры

Формат строки клавиатуры полностью совпадает с Telegram-плагином.

  • Вертикальное разделение — используйте ==;
msg.keyboard = "Кнопка1[btn1]==Кнопка2[btn2]" // Кнопки будут расположены вертикально
  • Горизонтальное разделение — используйте ||;
msg.keyboard = "Кнопка1[btn1]||Кнопка2[btn2]" // Кнопки будут расположены горизонтально
  • Комбинированное разделение;
msg.keyboard = "Кнопка1[btn1]||Кнопка2[btn2]==Кнопка3[btn3]||Кнопка4[btn4]"

Значение в квадратных скобках для обычной кнопки отправляется в VK как action.type=text с payload в виде JSON-строки "btn_static_<значение>" (VK требует валидный JSON, иначе ошибка API 911). В getMessagePayload().callback_data кавычки и префикс снимаются — так же, как в Telegram/Max.

Специальные типы кнопок

  • Запрос контакта (request_contact) в VK не поддерживается: кнопка пропускается, пишется отладочное сообщение:
msg.keyboard = "Отправить контакт[telegram_contact]"
  • Запрос локации (request_geo_location) в VK не поддерживается: кнопка пропускается, пишется отладочное сообщение:
msg.keyboard = "Отправить локацию[telegram_location]"
  • Ссылки (open_link):
msg.keyboard = "Посетить сайт[https://example.com]"
  • Web App. Запись {https://...} в VK не поддерживается: кнопка пропускается, пишется отладочное сообщение:
msg.keyboard = "Открыть приложение{https://webapp-url.com}"
  • Ссылка на пользователя tg://user?id=... в VK не поддерживается: кнопка пропускается, пишется отладочное сообщение.
  • Reply-клавиатура (msg.reply_markup = 'keyboard') в VK эмулируется теми же inline-кнопками; нажатие с payload при _reply_markup == 'keyboard' в getMessagePayload() даёт input_type: 'write'.

Лимит подписи кнопки VK — 40 символов (плагин обрезает).

Примеры использования

Простое меню с обработкой ответов

Код будет работать корректно только в команде JS Callback. Один и тот же код работает для Telegram, Max и VK.

let TelegramMessage = require('Common.Integrations.Telegram')
require('Common.Integrations.Max')
require('Common.Integrations.Vk')

let msg = new TelegramMessage()
msg.text = "Выберите действие:"
msg.keyboard = "Информация[info]==Помощь[help]==Настройки[settings]"
msg.parse_mode = "HTML"

switch (true) {
case (isFirstImmediateCall):
    msg.send()
    return false

case (msg.getMessagePayload()?.callback_data == "info"):
    msg.addReplyToText()
    bot.sendMessage("Информация о боте...")
    return false

case (msg.getMessagePayload()?.callback_data == "help"):
    msg.addReplyToText()
    bot.sendMessage("Справка по использованию...")
    return false

case (msg.getMessagePayload()?.callback_data == "settings"):
    msg.addReplyToText()
    bot.runScriptForLead(123, leadId) // Запуск скрипта настроек
    return false
}

Минимальное демо: кнопки + переход дальше

const TelegramMessage = require('Common.Integrations.Telegram')
require('Common.Integrations.Max')
require('Common.Integrations.Vk')

const msg = new TelegramMessage()
msg.text = 'VK+Telegram+Max demo\n\nВыберите кнопку:'
msg.keyboard = 'Кнопка A[a]==Кнопка B[b]'
msg.parse_mode = 'HTML'

if (isFirstImmediateCall) {
  msg.send()
  return false
}

msg.addReplyToText()
return true

В Telegram и Max после нажатия клавиатура исчезнет, а к тексту сообщения добавится строка ➤ Кнопка A. В VK подпись кнопки уже приходит в чат как сообщение пользователя (эхо text-кнопки), поэтому addReplyToText() ничего не отправляет — только очищает _keyboard и возвращает getMessagePayload().

Справочник методов

Основные методы отправки

  • send() — отправка нового сообщения (messages.send). ID сохраняется в атрибуты лида vk_last_message_id и telegram_last_message_id. Клавиатура уходит напрямую в теле messages.send (драйвер VK не передаёт keyboard из sendMessage);
  • edit() — в VK нет редактирования сообщений бота, поэтому отправляется новое сообщение (как send);=
  • addReplyToText() — в VK no-op: сообщение не отправляется (выбор уже виден как эхо подписи кнопки). Возвращает getMessagePayload() и очищает _keyboard;
  • removeInlineKeyboard() — в VK нельзя убрать кнопки из уже отправленного сообщения, поэтому метод только очищает _keyboard и возвращает getMessagePayload();
  • removeReplyKeyboard() — отправляет текст _remove_keyboard_text через messages.send без клавиатуры (как уведомление в Telegram).

Получение информации

  • getMessagePayload() — получение информации о сообщении из вебхука:
    • message_id — ID сообщения VK;
    • text — текст сообщения / подпись кнопки;
    • input_type — тип ввода ('write' / 'press');
    • callback_data — данные колбэка (без префикса btn_static_);
    • original_reply_markup — какой тип клавиатуры хотели получить (inline_keyboard / keyboard);
    • payload — полные данные вебхука.

Обработка ответов пользователя:

// Проверка типа ввода
if (msg.getMessagePayload()?.input_type == "write") {
    // Пользователь написал текст
}

// Проверка нажатия кнопки
if (msg.getMessagePayload()?.callback_data == "button_id") {
    // Пользователь нажал кнопку
}

Структура вебхука VK отличается от Telegram: событие всегда message_new. Сообщение лежит в object.message (API ≥ 5.103) или прямо в object. Нажатие text-кнопки приходит как message_new с полем payload (JSON-строка); плагин декодирует его, ищет кнопку в _keyboard и выставляет input_type=press. Текст без payload — input_type=write; если подпись совпала с кнопкой текущей клавиатуры, callback_data берётся из неё.

Отладка

msg.debug("Отладочное сообщение")

В Telegram при bot_debug_level == 0 используется «тихий» getMe. В VK такого метода нет: при уровне 0 отладка не отправляется пользователю. При ненулевом уровне сообщение уходит в чат (как и в Telegram-плагине).

Лучшие практики

  • Всегда проверяйте первый вызов:
if (isFirstImmediateCall) {
    msg.send()
    return false
}
  • Добавляйте обработку текстовых сообщений:
if (msg.getMessagePayload()?.input_type == "write") {
    bot.sendMessage('Пожалуйста, используйте кнопки')
    return false
}
  • После нажатия кнопки вызывайте addReplyToText() — в Telegram/Max это скроет клавиатуру и допишет ➤ …, в VK вызов безопасен (no-op) и сохраняет единый код скрипта:
msg.addReplyToText()
  • Подключайте Common.Integrations.Vk сразу после Telegram (и Max, если он нужен) в начале скрипта.
  • Не используйте в тексте кнопок больше 40 символов; payload кнопки VK — до 255 байт.
  • Для кросс-канальных скриптов всё равно задавайте parse_mode = 'HTML': в Telegram/Max форматирование сохранится, в VK плагин снимет разметку сам.
  • В настройках сообщества VK включите «Возможности ботов» — иначе messages.send с клавиатурой вернёт ошибку 912.

Форматирование текста и entities

VK не принимает HTML/Markdown в messages.send так же, как Telegram/Max. Если заданы parse_mode или entities, плагин удаляет HTML-теги, типичные entities и маркеры Markdown и отправляет plain text.

msg.text = "<b>Жирный текст</b>\n<i>Курсив</i>\n<code>Моноширинный текст</code>"
msg.parse_mode = "HTML"
// В VK уйдёт: "Жирный текст\nКурсив\nМоноширинный текст"

Работа с entities

msg.entities в VK не отправляются. Текст очищается так же, как при parse_mode.

let TelegramMessage = require('Common.Integrations.Telegram')
require('Common.Integrations.Max')
require('Common.Integrations.Vk')

let msg = new TelegramMessage()
let messageData = lead.getJsonAttr("messageData")

msg.text = messageData?.text
msg.entities = messageData?.entities

// Не используйте одновременно parse_mode и entities

Отправка медиагрупп

Глобальная функция sendMediaGroup для лидов VK отправляет вложения по одному через bot.sendMessage с { type, url }. Типы элементов приводятся так: photo/image → image, document/file → file, video → video, audio → audio. Подпись очищается от разметки. Для Telegram/Max-лидов вызывается исходная (или Max) реализация.

Работа с файлами

Входящие файлы обрабатываются стандартными методами бота — так же, как в Telegram-плагине. Вы можете получить URL файла и сохранить его в карточку лида.

let TelegramMessage = require('Common.Integrations.Telegram')
require('Common.Integrations.Max')
require('Common.Integrations.Vk')
let msg = new TelegramMessage()

// Все входящие файлы
let attachments = bot.getAllAttachments()

if (Boolean(attachments?.[0]?.url)) {
    let uploadData = bot.downloadFileFromUrl(attachments[0].url)

    msg.debug('Пользователь отправил файл: ' + uploadData.url)
    lead.setAttr('file', uploadData.url)

    // Запуск скрипта обработки
    bot.runScriptByCodeForLead("recieveFile", lead.getData('id'))

    bot.stop()
}

Пример ожидания фото:

let TelegramMessage = require('Common.Integrations.Telegram')
require('Common.Integrations.Max')
require('Common.Integrations.Vk')
let msg = new TelegramMessage()

msg.text = 'А теперь жду твоё фото 😉'
msg.parse_mode = 'HTML'

let data = bot.getAllAttachments()

switch (true) {
case (isFirstImmediateCall):
    msg.send()
    return false

case (Boolean(data?.[0]?.type != 'image')):
    bot.sendMessage('Отправь изображение. Такой формат не подходит')
    return false

case (Boolean(data?.[0]?.type == 'image')):
    let uploadData = bot.downloadFileFromUrl(data[0].url)
    msg.debug('Пользователь отправил файл: ' + uploadData.url)
    lead.setAttr('photo', uploadData.url)
    bot.sendMessage('Класс! Фото загрузил')
    return true

default:
    msg.addReplyToText()
    return true
}

Рекомендации по работе с файлами

  • Всегда проверяйте наличие вложения (attachments?.[0]?.url) перед скачиванием.
  • Сохраняйте URL, который вернул bot.downloadFileFromUrl(), а не исходный URL канала — он может устареть.
  • Не используйте Telegram file_id для VK: идентификаторы вложений в каналах разные.

Совместимость с Telegram-плагином

Возможность Telegram Max VK Комментарий
send() ✅ ✅ ✅ VK: messages.send
edit() ✅ ✅ ⚠️ VK: новое сообщение
addReplyToText() ✅ ✅ ⚠️ VK: ничего не отправляет (эхо кнопки уже в чате)
removeInlineKeyboard() ✅ ✅ ⚠️ VK: ничего не отправляет
removeReplyKeyboard() ✅ ⚠️ ⚠️ VK: send _remove_keyboard_text
getMessagePayload() ✅ ✅ ✅
debug() ✅ ✅ ⚠️ при bot_debug_level == 0 — silent no-op
parse_mode = HTML ✅ ✅ ❌ strip → plain
parse_mode = MarkdownV2 ✅ ⚠️ ❌ strip → plain
entities ✅ ⚠️ ❌ strip
Кнопки contact / location ✅ ✅ ❌ кнопка пропускается + debug
Кнопки-ссылки ✅ ✅ ✅ open_link
Web App {url} ✅ ⚠️ ❌ кнопка пропускается + debug
tg://user?id= ✅ ❌ ❌ кнопка пропускается
protect_content ✅ ❌ ❌ игнорируется
TelegramPhoto ✅ ❌ ❌ не патчится, используйте sendMediaGroup
sendMediaGroup ✅ ✅ ⚠️ по одному вложению
Эхо подписи кнопки нет нет да особенность VK text-кнопок

Ограничения VK

  • Текст кнопки — до 40 символов, payload кнопки — до 255 байт.
  • payload должен быть валидной JSON-строкой (плагин кодирует сам); иначе ошибка 911.
  • Для клавиатур в сообществе должны быть включены «Возможности ботов»; иначе ошибка 912.
  • Нет in-place edit / снятия inline-клавиатуры без правок PHP-драйвера.
  • Нет message_event (callback без эха подписи) без правок PHP-драйвера.
  • Вебхук Callback API требует публичный HTTPS URL (для локальной разработки — туннель; APP_URL может оставаться на localhost).