All Projects → danyadev → longpoll-doc

danyadev / longpoll-doc

Licence: Apache-2.0 License
Документация для (почти) последней версии User LongPoll API

Projects that are alternatives of or similar to longpoll-doc

Swiftyvk
Easy and powerful way to interact with VK API for iOS and macOS
Stars: ✭ 247 (+341.07%)
Mutual labels:  vkontakte, vk-api
py-vkontakte
A Python wrapper around the vk.com
Stars: ✭ 17 (-69.64%)
Mutual labels:  vkontakte, vk-api
vk-api
VK SDK | VKontakte wrapper for standalone apps
Stars: ✭ 30 (-46.43%)
Mutual labels:  vkontakte, vk-api
Vk Api Schema
JSON Schema of VK API
Stars: ✭ 158 (+182.14%)
Mutual labels:  vkontakte, vk-api
vk-mini-app-boilerplate
Стартовый кит для создания сервиса на платформе VK Mini Apps с использованием React + Redux
Stars: ✭ 61 (+8.93%)
Mutual labels:  vkontakte, vk-api
Vk Requests
vk.com requests for humans. API library for vk.com
Stars: ✭ 162 (+189.29%)
Mutual labels:  vkontakte, vk-api
vk-spammer
Спаммер сообщений для вк
Stars: ✭ 47 (-16.07%)
Mutual labels:  vkontakte, vk-api
Vkrss
Generates RSS feed of opened/closed vk.com wall or global searched opened posts. Features: post filtering (include/exclude by regexp and/or by owner type), ads skipping, automatic title generation, hash-tags extraction as RSS categories, initial author extraction, HTML formatting
Stars: ✭ 59 (+5.36%)
Mutual labels:  vkontakte, vk-api
easyvk
This app helps you create an apps with vk api easy!
Stars: ✭ 97 (+73.21%)
Mutual labels:  vk-api, longpoll
InTouch
👥 InTouch - is a programming SDK build around vk.com API exposing most of the social platform features including messaging, news feed fetching, communities, and media management.
Stars: ✭ 33 (-41.07%)
Mutual labels:  vkontakte, vk-api
easyvk-go
Simple way to work with VK API
Stars: ✭ 47 (-16.07%)
Mutual labels:  vkontakte, vk-api
kasthack.osp
Генератор сырых дампов пользователей VK.
Stars: ✭ 15 (-73.21%)
Mutual labels:  vkontakte, vk-api
Sketal
Бот для ВКонтакте. Беседы / группы / развлечения.
Stars: ✭ 119 (+112.5%)
Mutual labels:  vkontakte, vk-api
Node Vk Bot Api
🤖 VK bot framework for Node.js, based on Bots Long Poll API and Callback API.
Stars: ✭ 195 (+248.21%)
Mutual labels:  vkontakte, vk-api
Vk To Telegram Bot
Bot for auto-reposting posts from VK to Telegram channel
Stars: ✭ 103 (+83.93%)
Mutual labels:  vkontakte, vk-api
VideoforVk
Video for Vk (or VT) is client for Vk video API.
Stars: ✭ 27 (-51.79%)
Mutual labels:  vkontakte, vk-api
Vk.py
Extremely-fast, easy-to-use, [not] ready for production. The asyncio based library for Python and Humans written to be efficient and reliable. [Unmaintained]
Stars: ✭ 38 (-32.14%)
Mutual labels:  vkontakte, vk-api
Vk api
Модуль для создания скриптов для ВКонтакте | vk.com API wrapper
Stars: ✭ 1,070 (+1810.71%)
Mutual labels:  vkontakte, vk-api
java-vk-bots-long-poll-api
A Java library to create VK bots using Bots Long Poll API
Stars: ✭ 30 (-46.43%)
Mutual labels:  vk-api, longpoll
vbio
Python модуль для написания скриптов, использующих Bots API для социальной сети Вконтакте (vk.com)
Stars: ✭ 10 (-82.14%)
Mutual labels:  vkontakte, vk-api

User LongPoll API

План документации:

  1. Отказ от ответственности
  2. Подключение
  3. Возвращаемые ошибки
  4. Получение истории событий
  5. Структура сообщения
  6. Описание событий
  7. Дополнительная информация

Документация написана для 10 версии LongPoll.

Отказ от ответственности

Автор не несет ответственности за точность, полноту или качество предоставленной информации. Используйте последующую информацию на свой страх и риск.

Правила пользования сайтом, пункт 6.7:

6.7. Создаваемые Пользователями приложения API должны использовать только опубликованные на Сайте методы API, а также ID, защищенный ключ и сервисный ключ доступа, указанные в настройках данных приложений. Использование других методов API, а также ID, защищенного ключа и сервисного ключа доступа приложений API третьих лиц, в т.ч. приложения API Администрации Сайта, строго запрещено. Пользователь обязуется регулярно проверять перечень разрешённых методов и незамедлительно вносить корректировки в функциональность своих приложений API в соответствии с изменениями перечня. За нарушение настоящего пункта Пользователь несет предусмотренную применимым законодательством, настоящими Правилами и иными документами Администрации Сайта ответственность. Администрация Сайта при этом оставляет за собой право на защиту собственных прав и законных интересов.

Подключение

Long Polling - это технология, используемая для получения событий в реальном времени, которая работает так:

  1. Запрос отправляется на сервер
  2. Сервер ждет нового события или таймаута
  3. Сервер возвращает список только что пришедших событий (или пустой список, если вернул ответ по таймауту)

Подробнее про данную технологию можно прочитать здесь.

Ссылка для запроса составляется следующим образом:

https://server?act=a_check&key=key&ts=ts&wait=wait&mode=mode&version=version

  • server, key и ts получаются методом messages.getLongPollServer
  • version - Версия LongPoll
  • wait - Время ожидания нового события в секундах, максимум 90
  • mode - Дополнительные опции ответа:
    • 2 - Возвращать вложения и дополнительные данные сообщения (additional и attachments в структуре сообщения)
    • 8 - Возвращать данные в 114, 115 и 119 событиях
    • 32 - Возвращать pts
    • 64 - Возвращать данные о платформе в событии онлайна друга
    • 128 - Возвращать random_id
    • 512 - Возвращать бизнес-уведомления

В JS ссылку можно составить следующим образом:

function toUrlParams(object) {
  return new URLSearchParams(object).toString();
}

// server, key и ts нужно получить заранее с помощью метода messages.getLongPollServer.
const link = `https://${server}?` + toUrlParams({
  act: 'a_check',
  key: key,
  ts: ts,
  wait: 10,
  mode: 2 | 8 | 32 | 64 | 128 | 512,
  version: 10
});

После выполнения запроса сервер вернет ответ следующего вида:

interface LongPollResult {
  // Приходит, если нет ошибок или при failed: 1
  ts?: number
  // Приходит, если нет ошибок (необходим флаг 32)
  pts?: number
  // Приходит, если нет ошибок
  updates?: any[]

  failed?: 1 | 2 | 3 | 4

  // Приходят только при failed: 4
  min_version?: 0
  max_version?: 15
}

После обработки ответа нужно повторить запрос, перед этим заменив ts и pts на новые из ответа.

Возвращаемые ошибки

Иногда вместо поля updates в ответе может прийти поле failed. Чаще всего приходит 2 ошибка, но могут прийти и другие:

  1. Устарела история событий. Решается получением пропущенной истории событий и использованием ts из ответа LongPoll.
  2. Истекло время действия ключа. Решается получением нового key через метод messages.getLongPollServer.
  3. Информация о пользователе утрачена. Решается получением пропущенной истории событий и получением key и ts методом messages.getLongPollServer.
  4. Передана неправильная версия. В ответе приходят поля min_version и max_version, в пределах которых следует указать версию.

Получение истории событий

Для получения истории событий нам необходим pts, который можно получить указав need_pts: 1 при вызове метода messages.getLongPollServer и добавлением в mode флага 32 при выполнении запроса.

Для получения истории мы будем использовать метод messages.getLongPollHistory с указанием следующих параметров:

  • pts - Последний полученный pts из LongPoll
  • msgs_limit - Максимальное количество передаваемых сообщений. Минимум 200, рекомендую 500, максимум 1000
  • onlines - 1 если возвращать события 8 и 9 (онлайн и оффлайн друга), 0 если нет
  • lp_version - Версия LongPoll
  • fields - Поля пользователей и групп, которые могут прийти вместе с историей

Ответ выглядит следующим образом:

// Описание типов:
// https://github.com/danyadev/vk-types#объекты
interface LongPollHistoryResult {
  history: any[][]
  from_pts: number
  new_pts: number
  conversations: VKConversation[]
  messages: {
    count: number
    items: VKMessage[]
  }
  profiles?: VKUser[]
  groups?: VKGroup[]
  more?: true
}

Поле history идентично полю updates, которое приходит из LongPoll, за исключением удаления некоторых лишних событий (т.к. приходит просто измененный объект беседы или сообщения) и сокращения некоторых событий:

Структура этих событий выглядит так:

type LongPollHistoryMessageEvent = [
  type: 3 | 4 | 5 | 18,
  messageId: number,
  flags: number,
  peerId: number
];

Всю информацию о сообщениях и беседах можно взять из полей messages и conversations, где содержатся данные из API.

Если в ответе придет поле more, то после обработки всех событий нужно будет повторить запрос, указав в поле pts пришедший new_pts.

Структура сообщения

Подробнее про некоторые части структуры можно почитать здесь:

Структура описывает массив, ключи используются только для описания значений

type LongPollMessage = [
  type: 3 | 4 | 5 | 18,
  messageId: number,
  flags: number,
  peerId: number,
  timestamp: number,
  text: string,

  // Объект приходит только при указании флага 2 при подключении к LongPoll
  additional: {
    // ' ... ' приходит только в лс
    // '' приходит при редактировании любого сообщения
    // string приходит при написании в лс через vk.com с указанием темы
    // Устаревшее поле, не следует использовать
    title?: ' ... ' | '' | string
    // Наличие emoji в сообщении
    emoji?: '1'
    // id автора сообщения. Приходит только в беседах
    from?: string
    // Наличие шаблона (для получения шаблона нужно получить сообщение из API)
    has_template?: '1'
    marked_users?: [
      // Список упомянутых людей, @online, ответ на сообщение
      | [1, number[]]
      // @all
      | [1, 'all']
      // Исчезающее сообщение в обычном чате
      | [2, 'all']
    ]
    // Клавиатура для ботов (для беседы или сообщения)
    keyboard?: MessageKeyboard
    // Количество секунд до исчезновения сообщения в обычном чате
    expire_ttl?: string
    // Количество секунд до исчезновения сообщения в фантомном чате
    ttl?: number
    // Сообщение исчезло, приходит в 18 событии
    is_expired?: '1'
    // Приходит, если при отправке сообщения указать параметр payload.
    // Возвращает всегда JSON, который может содержать любую информацию.
    // Там может содержаться отладочная информация, которая может пригодиться разработчику.
    payload?: string

    // Сервисное сообщение
    // см. ссылку выше
  },

  // Объект приходит только при указании флага 2 при подключении к LongPoll
  attachments: {
    // Есть пересланное сообщение или ответ на сообщение
    fwd?: '0_0'
    // Ответ на сообщение: '{"conversation_message_id":number}'
    // Приходит только в 4 и 18 событиях
    reply?: string

    // Количество вложений в поле attachments
    // Число в строке
    attachments_count?: string
    // JSON с массивом вложений
    // Приходит только для некоторых типов вложений
    attachments?: string

    // Описание вложений вида { attach1_type, attach1, ... }
    // Все значения здесь имеют тип строки (и могут быть объектом в строке по типу '{"id":1}')
    // см. ссылку выше
  },

  // Возвращается, если в mode есть флаг 128
  randomId: number,
  // id сообщения относительно беседы
  conversationMsgId: number,
  // 0 (не редактировалось) или timestamp (время редактирования)
  updateTimestamp: number
];

Стоит отметить, что в поле text переносы строк обозначаются как <br>, а символы ", &, < и > экранируются.

В очень редких случаях может прийти урезанный вариант сообщения

Он приходит, если сообщение на момент возвращения событий уже было удалено для всех. Его следует игнорировать, потому что после него приходит событие удаления сообщения, которое удалит сообщение с вашей стороны, если оно уже было сохранено

type LongPollMessageShort = [
  type: 3 | 4 | 5 | 18,
  messageId: number,
  flags: number
];

Описание событий

Событие 2. Установка флагов сообщения

Возможные значения флагов сообщения:

  1. Пометка важным (8 important)
  2. Пометка как спам (64 spam)
  3. Удаление сообщения (128 deleted)
  4. Удаление для всех (128 deleted и 131072 deleted_all)
  5. Прослушивание голосового сообщения (4096 audio_listened)

Событие приходит как при прослушивании собеседником вашего голосового сообщения, так и при прослушивании вами голосового сообщения собеседника.

Вручную прослушать голосовое сообщение собеседника можно с помощью метода messages.markAsListened с параметром message_id. Метод вернет 1 при первом прослушивании голосового сообщения, а 0 при последующих или при попытке прослушать свое сообщение.

type Event2 = [
  type: 2,
  messageId: number,
  flags: number,
  peerId: number
];

Событие 3. Сброс флагов сообщения

Возможные значения флагов сообщения:

  1. Прочитано сообщение (1 unread). Устаревший флаг
  2. Отмена пометки важным (8 important)
  3. Отмена пометки сообщения как спам (64 spam и 32768 cancel_spam)
  4. Восстановление удаленного сообщения (128 deleted)

В 3 и 4 случаях возвращается сообщение.

type Event3 = [
  type: 3,
  messageId: number,
  flags: number,
  peerId: number
] | LongPollMessage;

Событие 4. Новое сообщение

Данное событие возвращает новое сообщение.

type Event4 = LongPollMessage;

Событие 5. Редактирование сообщения

Данное событие возвращает отредактированное сообщение.

type Event5 = LongPollMessage;

Событие 6. Прочтение входящих сообщений

Вы прочитали в диалоге peer_id сообщения до msg_id включительно.
count - количество непрочитанных сообщений в диалоге.

type Event6 = [
  type: 6,
  peerId: number,
  messageId: number,
  count: number
];

Событие 7. Прочтение исходящих сообщений

Собеседник прочитал в диалоге peer_id сообщения до msg_id включительно.
count - количество ваших непрочитанных сообщений в диалоге.

type Event7 = [
  type: 7,
  peerId: number,
  messageId: number,
  count: number
];

Событие 8. Друг появился в сети

Событие не приходит, если у друга включена невидимка хотя бы для одного пользователя.

type Event8 = [
  type: 8,
  // отрицательный id друга
  userId: number,
  // 1 - m.vk.com или неизвестное мобильное приложение
  // 2 - iPhone
  // 3 - iPad
  // 4 - Android
  // 5 - Windows Phone
  // 6 - Windows 8
  // 7 - vk.com или неизвестное десктопное приложение
  platform: 1 | 2 | 3 | 4 | 5 | 6 | 7,
  // время онлайна в секундах
  timestamp: number,
  // id приложения, с которого онлайн друг
  // 0 если онлайн был вызван не приложением (например веб)
  appId: 0 | number,
  // 1 если онлайн с мобильного, 0 если нет
  isMobile: 0 | 1,
  // Всегда приходит 0
  hasInvisibleMode: 0 | 1
];

Событие 9. Друг вышел из сети

Событие не приходит, если у друга включена невидимка хотя бы для одного пользователя.

type Event9 = [
  type: 9,
  // отрицательный id друга
  userId: number,
  // 1 если бездействовал 5 минут, 0 если покинул сайт
  isTimeout: 0 | 1,
  // время наступления офлайна в секундах
  timestamp: number,
  // id приложения, с которого был онлайн друг
  // 0 если онлайн был вызван не приложением (например веб)
  appId: 0 | number,
  // 1 если онлайн с мобильного, 0 если нет
  isMobile: 0 | 1,
  // Всегда приходит 0
  hasInvisibleMode: 0 | 1
];

Событие 10. Сброс флагов беседы

Все возможные флаги описаны в 12 событии

Вместе со сбросом 14 флага сбрасывается и 10, который мог вообще не быть в списке флагов. Сделано это для обратной совместимости

type Event10 = [
  type: 10,
  peerId: number,
  flags: number
];

Событие 12. Установка флагов беседы

Возможные флаги беседы:

1 << 4 (16) - Беседа замьючена

1 << 5 (32) - Звук в беседе выключен (сомнительный флаг)

1 << 8 (256) - Входящий запрос на переписку / вступление в беседу

1 << 9 (512) - Отклоненный запрос на переписку / вступление в беседу

1 << 10 (1024) - Наличие упоминания

1 << 11 (2048) - Не отображать беседу при поиске

1 << 12 (4096) - Внутренний флаг

1 << 13 (8192) - Беседа в статусе бизнес-уведомления

1 << 14 (16384) - Наличие маркированного сообщения: упоминание или исчезающее сообщение

1 << 16 (65536) - Фантомный чат

1 << 18 (262144) - Не присылать уведомлений о @all и @online

1 << 19 (524288) - Не присылать уведомлений о всех упоминаниях

1 << 20 (1048576) - Беседа помечена как непрочитанная

1 << 22 (4194304) - Беседа в статусе входящего запроса на переписку (наличие флага 8 или 9)

1 << 23 (8388608) - Беседа помещена в архив

1 << 24 (16777216) - Беседа, в которой идет звонок

1 << 26 (67108864) - Признак того, что это чат

  • при создании фантомного чата добавляется этот флаг и 1 << 16
  • при создании канала с чата снимается этот флаг
type Event12 = [
  type: 12,
  peerId: number,
  flags: number
];

Событие 13. Удаление всех сообщений в диалоге

В беседе peerId были удалены все сообщения до messageId включительно.

type Event13 = [
  type: 13,
  peerId: number,
  messageId: number
];

Событие 18. Обновление сообщения

Приходит при следующих событиях:

  1. Добавился сниппет (ссылка) - к вложениям добавляется link.
  2. Сообщение исчезло — удаляется текст и все вложения, добавляется ключ is_expired: true.
  3. Пришел перевод голосового сообщения.

Данное событие возвращает сообщение.

type Event18 = LongPollMessage;

Событие 19. Сброс кеша сообщения

Приходит в двух случаях:

  1. По какой-либо причине изменилось сообщение (без явного редактирования). Необходимо переполучить сообщение через API.
  2. Сообщение исчезло. В данном случае можно игнорировать это событие, если вы обработали исчезновение сообщения в 18 событии.

ВАЖНО: если вы собираетесь обрабатывать исчезновение сообщений, то я рекомендую игнорировать 19 событие и обрабатывать только 18 событие. Однако сначала приходит 19 событие, а потом уже 18, поэтому нужно сначала дождаться, пока обработается 18 событие и там к сообщению добавится поле is_expired, и только затем здесь проверять это сообщение на наличие этого поля.

type Event19 = [
  type: 19,
  messageId: number
];

Событие 20. Закрепление и открепление беседы (изменился majorId)

majorId и minorId - это дополнительные айдишники для беседы, которые используются для ее сортировки в списке всех бесед.

Сначала список сортируется по majorId, а если есть беседы с одинаковыми majorId, то они сортируются по minorId

majorId принимает следующие значения: 0, 16, 32, 48, 64, 80. Чем больше значение, тем выше беседа в списке закрепленных. 0 означает незакрепленную беседу.

При закреплении беседы ей присваивается наибольшее доступное значение majorId, то есть она закрепляется в самый верх списка.

Если закрепленная беседа всего одна, то ей присваивается majorId = 16, если две — верхней присваивается 32 и так далее.

type Event20 = [
  type: 20,
  peerId: number,
  majorId: number,
  0
];

Событие 21. Изменился minorId

Для 10 версии LongPoll событие приходит только в методе messages.getLongPollHistory

В версиях LongPoll выше 10 событие приходит еще в некоторых сценариях, но это будет подробно расписано только при обновлении документации на новую версию LongPoll

minorId означает id последнего сообщения в беседе, но с одним отличием. В фантомном чате последнее сообщение может исчезнуть, и чтобы диалог после этого полностью не пропал из списка, minorId сохраняет в себе id последнего даже исчезнувшего сообщения.

type Event21 = [
  type: 21,
  peerId: number,
  minorId: number
];

Событие 51. Изменение данных чата (устарело)

Событие означает, что в беседе chatId изменились какие-то данные. Более подробно все расписано в 52 событии.

type Event51 = [
  type: 51,
  chatId: number
];

Событие 52. Изменение данных чата

Тип Описание Дополнительная информация
0 Из беседы был создан фантомный чат 0
1 Изменилось название беседы 0
2 Обновилась аватарка беседы 0
3 Назначен новый администратор id администратора
4 Изменение прав доступа в беседе mask с правами доступа
5 Закрепление или открепление сообщения conversationMsgId или 0
6 Вступление в беседу id вступившего
7 Выход из беседы id вышедшего
8 Исключение из беседы id исключенного
9 Разжалован администратор id бывшего админа
10 Изменился баннер (какая-то инфа под шапкой в личке) 0
11 Появление или скрытие клавиатуры peerId
12 Отозвано / подтверждено / отклонено / пришло приглашение в чат 0 / 1 / 2 / 3
13 Контакт был сконвертирован в юзера (contactId -> userId) contactId
14 Произошло любое действие с бизнес-уведомлением 0
15 Вы отозвали приглашение контакта или юзера в чат contactId или userId
16 Контакт или юзер отклонил приглашение в чат contactId или userId
17 Контакт или юзер принял приглашение в чат contactId или userId
18 Контакт или юзера пригласили в чат contactId или userId
19 Начало или окончание группового звонка 1 в начале, 0 в конце
22 Чат больше не новый: пришло первое сообщение (только в лс) 0
23 Изменено оформление чата

При изменении названия (1) и обновлении аватарки беседы (2) нужные данные можно взять из сервисного сообщения в 4 событии.

type Event52 = [
  type: 52,
  // 0-19, 22
  updateType: number,
  peerId: number,
  extra: number
];

Событие 63. Статус набора сообщения

Означает, что в беседе peerId начали писать текст totalCount людей. Их id записаны в userIds. В массиве userIds может появиться и ваш id, так что нужно фильтровать этот список.

type Event63 = [
  type: 63,
  peerId: number,
  userIds: number[],
  totalCount: number,
  timestamp: number
];

Событие 64. Статус записи голосового сообщения

Вызывается при записи голосового сообщения.
Идентичен событию 63.

Событие 65. Статус загрузки фотографии

Вызывается при загрузке фотографии.
Идентичен событию 63.

Событие 66. Статус загрузки видеозаписи

Вызывается при загрузке видеозаписи.
Идентичен событию 63.

Событие 67. Статус загрузки файла

Вызывается при загрузке файла.
Идентичен событию 63.

Событие 80. Изменение количества непрочитанных диалогов

Все счетчики возвращаются без учета сообщений в архиве

type Event80 = [
  type: 80,
  // Количество непрочитанных бесед
  unreadCount: number,
  // Количество непрочитанных незамьюченных бесед
  unreadUnmutedCount: number,
  // 0 - показывать количество всех бесед, 1 - только незамьюченные
  showOnlyUnmuted: 0 | 1,
  // Количество непрочитанных бизнес-уведомлений
  businessNotifyUnreadCount: number,
  // Количество непрочитанных бесед в мессенджере в шапке
  // Эти два счетчика можно сбросить, просто открыв мессенджер в шапке на вебе
  headerUnreadCount: number,
  // Количество непрочитанных незамьюченных бесед в мессенджере в шапке
  headerUnreadUnmutedCount: number,
  // Количество непрочитанных бесед в архиве
  archiveUnreadCount: number,
  // Количество непрочитанных незамьюченных бесед в архиве
  archiveUnreadUnmutedCount: number,
  // Количество бесед с упоминаниями в архиве
  archiveMentionsCount: number
];

Событие 81. Изменение состояния невидимки друга

Если невидимка будет выключена не для всех, то метод так же вернет state: 1, хотя для нас онлайн может быть так же виден

type Event81 = [
  type: 81,
  // Отрицательный id друга
  userId: number,
  // 0 - невидимка выключена, 1 - включена
  state: 0 | 1,
  // время последнего онлайна друга
  timestamp: number,
  -1,
  // При настройке невидимки через VK Me приходит 0, в других случаях не проверял
  appId: 0 | number
];

Событие 90. Добавление или удаление из друзей

Событие возвращается только для действий с вашей стороны.

Значения actionType:

  • 2 - вы приняли заявку пользователя
  • 3 - вы удалили из друзей или отклонили заявку в друзья пользователя
type Event90 = [
  type: 90,
  actionType: 2 | 3,
  userId: number
];

Событие 114. Изменение настроек пуш-уведомлений в беседе

Для работы необходимо использовать в mode флаг 8 при выполнении запроса.

  • peer_id - id беседы, в которой включили или выключили уведомления
  • sound - нестабильный параметр, не рекомендую его обрабатывать
  • disabled_until может быть трех видов:
    • 0 - Уведомления включены
    • -1 - Уведомления выключены
    • number, > 0, - Уведомления выключены до указанного timestamp
type Event114 = [
  type: 114,
  data: {
    peer_id: number
    sound: 0 | 1
    disabled_until: 0 | -1 | number
  }
];

Событие 115. Звонок

Для работы необходимо использовать в mode флаг 8 при выполнении запроса.

¯\_(ツ)_/¯

Событие 119. Ответ callback-кнопки

Для работы необходимо использовать в mode флаг 8 при выполнении запроса.

Callback-кнопки работают следующим образом:

  1. Бот отправляет клавиатуру (обычную или инлайн), где находится callback-кнопка;
  2. Пользователь нажимает на эту кнопку и клиент вызывает метод messages.sendMessageEvent (параметры см. ниже). Метод возвращает строку - event_id;
  3. Бот получает событие message_event и вызывает метод messages.sendMessageEventAnswer;
  4. Этот метод вызывает 119 событие LongPoll у пользователя, где в action прописано действие, которое необходимо выполнить клиенту.

Параметры метода messages.sendMessageEvent:

interface MessagesSendMessageEventParams {
  peer_id: number
  // Находится в кнопке клавиатуры
  payload: string

  // Нужно передать один из двух параметров,
  // если это инлайн клавиатура в сообщении или карусели
  message_id?: number
  conversation_message_id?: number

  // Находится в объекте клавиатуры беседы
  // Нужно передать, если это клавиатура беседы
  author_id?: number
}

После получения event_id на 2 стадии нужно начать ждать 119 событие LongPoll с нужным event_id. Если за минуту бот так и не пришлет событие, то ожидание ответа следует прекратить.

type Event119 = [
  type: 119,
  data: {
    // Отрицательный ID бота, который ответил на клик по кнопке
    owner_id: number
    // ID беседы, в которой находится сообщение
    peer_id: number
    // Уникальный ID события, действующий 1 минуту.
    // Нужен для идентификации кликнутой кнопки
    event_id: string
    // Не приходит, если не нужно выполнять никакое действие
    // т.е. бот отправил пустой payload или неизвестный тип действия
    action?:
      // Показать снекбар с текстом `text`
      | { type: 'show_snackbar', text: string }
      // Открыть ссылку `link`
      | { type: 'open_link', link: string }
      // Открыть приложение по ссылке
      // https://vk.com/app${app_id}_${owner_id}#${hash}
      // https://vk.com/app${app_id}_${owner_id} (если hash = '')
      // https://vk.com/app${app_id} (если owner_id = undefined и hash = '')
      | { type: 'open_app', app_id: number, owner_id?: number, hash: string }
  }
];

Дополнительная информация

Флаги сообщений

Маской называют сумму некоторых флагов (степеней двойки), которую можно использовать как хорошую замену для объектов или массивов.

// Обычно маску записывают подобным образом:
const mask = 1 | 2 | 8 | 64 | 1024;
// Что эквивалентно сложению чисел:
const mask = 1 + 2 + 8 + 64 + 1024;
// А еще можно не писать магические цифры, а записывать степени двойки в таком формате:
const mask = (1 << 0) | (1 << 1) | (1 << 3) | (1 << 6) | (1 << 10);
Название Описание Бит Значение
unread Непрочитанное сообщение 1 << 0 1
outbox Исходящее сообщение 1 << 1 2
important Важное сообщение 1 << 3 8
chat_vkcom Отправка сообщения в беседу через vk.com 1 << 4 16
friends Исходящее; входящее от друга в лс 1 << 5 32
spam Пометка сообщения как спам 1 << 6 64
deleted Удаление сообщения локально 1 << 7 128
audio_listened Прослушано голосовое сообщение 1 << 12 4096
chat Отправка сообщения в беседу 1 << 13 8192
cancel_spam Отмена пометки как спам 1 << 15 32768
old_minor_id Сообщение не поднимает диалог вверх 1 << 16 65536
deleted_all Удаление сообщения для всех 1 << 17 131072
not_delivered Внутренний флаг 1 << 18 262144
chat_in Входящее сообщение в беседе 1 << 19 524288
silent Сообщение без уведомления 1 << 20 1048576
reply_msg Ответ на сообщение 1 << 21 2097152
auto_read Сообщение пришло сразу прочитанным 1 << 23 8388608
has_ttl Внутренний флаг 1 << 26 67108864

Бесшумное сообщение можно отправить, добавив к параметрам метода messages.send ключ silent: true:

  • Такое сообщение отправится без уведомления пользователю, даже если у него включены уведомления
  • Упоминание или ответ на сообщение тоже не отправит уведомления
  • Сообщение о выходе из беседы автоматически приходит без уведомления

not_delivered и has_ttl приходят для бизнес-уведомлений

Пример определения наличия флага в маске:

const mask = 1 | 2 | 32; // = 35

8 & mask // вернет 0 (false)
2 & mask // вернет 2 (true)

Сервисные сообщения

Сервисное сообщение описывается ключом source_act и ключами с дополнительными данными в объекте additional из структуры сообщения.

У некоторых сервисных сообщений в поле text приходит сообщение вида Сообщение не поддерживается Вашим приложением., поэтому при обработке сервисных сообщений не нужно обрабатывать текст сообщения.

Вместе с сервисными сообщениями chat_title_update и chat_photo_remove в каналах приходит поле source_is_channel: "1". Сервисное сообщение chat_photo_update для каналов не приходит (только 52 событие).

Возможные значения source_act:

Тип Дополнительные ключи
chat_create
Создание беседы
source_text - название беседы
chat_photo_update
Обновление фотографии беседы
Фото можно получить во вложении сообщения
chat_photo_remove
Удаление фотографии беседы
chat_title_update
Обновление названия беседы
source_old_text - старое название беседы (не приходит в API)
source_text - новое название беседы
chat_pin_message
Закрепление сообщения
source_mid - id закрепившего сообщение
source_message - обрезанное закрепленное сообщение
source_chat_local_id - локальный id сообщения
chat_unpin_message
Открепление сообщения
source_mid - id открепившего сообщение
source_chat_local_id - локальный id сообщения
chat_invite_user
Вступление в беседу
source_mid - id вступившего в беседу
chat_invite_user_by_link
Вступление в беседу по ссылке
chat_kick_user
Выход или исключение из беседы
source_mid - id вышедшего или исключенного
chat_kick_don
Исключение дона из беседы
Приходит, начиная с версии API 5.154
chat_screenshot
Создание скриншота с фантомным сообщением
source_mid - id создавшего скриншот
chat_group_call_started
Начало группового звонка в беседе
Больше не приходит в LongPoll
Вместо него создается сообщение с вложением group_call_in_progress
Приходит для старых сообщений через API при получении через токен VK для Android
chat_invite_user_by_call
Приглашение пользователя в звонок
source_mid - id приглашенного юзера
chat_invite_user_by_call_join_link
Присоединение пользователя к звонку по ссылке
chat_invite_user_by_message_request
Запрос на добавление в беседу
source_mid - id пригласившего в беседу
conversation_style_update
Обновление стиля беседы
source_style - название стиля
Поле не приходит в случае сброса стиля
Возможные варианты можно посмотреть здесь

Пример описания сервисного сообщения:

const longpollServiceMessage = {
  source_act: 'chat_pin_message',
  source_mid: '88262293',
  source_message: 'Сообщение, которое будет в закрепе',
  source_chat_local_id: '5517'
}

Клавиатура для ботов

Клавиатура для ботов представляет собой объект с описанием ее типа и кнопок. Основная структура представлена ниже, остальную информацию можно узнать в документации.

// Типы у объекта клавиатуры:
// https://github.com/danyadev/vk-types/blob/master/src/objects/VKKeyboard.ts
interface LongPollKeyboard {
  // Приходит, если это клавиатура сообщения или карусели
  inline?: true
  // Скрывать ли клавиатуру при клике на кнопку (не работает для inline)
  one_time: boolean
  buttons?: VKKeyboardButton[][]
}

Вложения

Список существующих вложений

Список известных на данный момент вложений: geo, doc, link, poll, wall, call, gift, story, photo, audio, video, event, market, artist, widget, sticker, article, podcast, curator, graffiti, mini_app, narrative, wall_reply, audio_message, money_request, audio_playlist, group_call_in_progress.

Однако названия вложений, полученных через LongPoll, могут не совпадать с теми, что приходят через API:

  • event, приходящий в API, в LongPoll обозначается как group
  • graffiti и audio_message из LongPoll обозначаются как doc, но при этом добавляется ключ attach*_kind со значением graffiti или audiomsg
  • artist, article, narrative и audio_playlist, которые приходят в LongPoll, через API отображаются как link
  • mini_app не приходит в LongPoll, вместо него приходит link
  • narrative приходят в API начиная с версии 5.154

Вложения artist, article, mini_app и audio_playlist приходят в API только через токен VK для Android.

Вложение geo (прикрепленное местоположение) приходит в виде ключей geo и geo_provider вместо attach* (см. структуру). Также при получении сообщения через messages.getById ключ geo будет находиться не во вложениях, а в "корне" сообщения.

Сообщение с вложением group_call_in_progress создается, когда пользователь начинает групповой звонок. При окончании группового звонка сообщение с этим вложением удаляется и создается новое сообщение с вложением call.

Работа с вложениями в LongPoll

Пример вложений, состоящих из фотографии, документа и аудиозаписи:

const longpollAttachments = {
  attach1: '88262293_457290160',
  attach1_type: 'photo',
  attach2: '88262293_532324610',
  attach2_type: 'doc',
  attach3: '88262293_535133534',
  attach3_kind: 'audiomsg',
  attach3_type: 'doc'
}

Обычно дополнительная информация о вложении не нужна, поэтому можно ограничиться получением названий вложений для предварительного отображения сообщения и анализа списка вложений, чтобы в случае необходимости получить сообщение через API.

Пример кода для получения массива с названиями вложений
function getAttachments(data) {
  const attachments = [];

  if (data.geo) {
    attachments.push('geo');
  }

  for (const key in data) {
    const match = key.match(/attach(\d+)$/);

    if (match) {
      const id = match[1];
      const kind = data[`attach${id}_kind`];
      let type = data[`attach${id}_type`];

      if (kind === 'audiomsg') type = 'audio_message';
      if (kind === 'graffiti') type = 'graffiti';
      if (type === 'group') type = 'event';

      attachments.push(type);
    }
  }

  return attachments;
}

Ответ на сообщение

Определить наличие ответа на сообщение можно с помощью проверки наличия attachments.reply (структура) или флага reply_msg.

В некоторых случаях получать сообщение через API для получения ответа на сообщение не нужно: если сообщение, на которое пришло ответ, пришло недавно, то оно наверняка уже должно быть в локальном списке сообщений. Найти сообщение можно с помощью conversation_message_id из attachments.reply.

Пересланные сообщения

Определить наличие пересланных сообщений можно с помощью проверки на отсутствие ответа на сообщение и на наличие attachments.fwd. ID пересланных сообщений, как и их количество, пока что не приходит через LongPoll.

Оптимизация получения вложений

Для получения некоторых вложений необязательно получать сообщение через API - в объект attachments (структура) приходят поля attachments_count и attachments, где и содержатся объекты вложений из API. К примеру, в списке вложений можно найти стикер и голосовое сообщение.

При работе с вложениями можно попробовать найти необходимый элемент в документации, однако у некоторых вложений документация не обновлена или вовсе отсутствует.

Права доступа в беседах

В списке представлены все возможные параметры прав доступа с их флагом из 4 действия 52 события.

  • Кто может приглашать участников в беседу
    • Только создатель: 2097152 (1 << 21)
    • Создатель и администраторы: 1 (1 << 0)
    • Все участники: 0
  • Кто может редактировать информацию беседы
    • Только создатель: 4194304 (1 << 22)
    • Создатель и администраторы: 8 (1 << 3)
    • Все участники: 0
  • Кто может менять закреплённое сообщение
    • Только создатель: 8388608 (1 << 23)
    • Создатель и администраторы: 4 (1 << 2)
    • Все участники: 0
  • Кто может отправлять массовые упоминания
    • Только создатель: 1048576 (1 << 20)
    • Создатель и администраторы: 524288 (1 << 19)
    • Все участники: 0
  • Кто может видеть ссылку на беседу
    • Только создатель: 0
    • Создатель и администраторы: 16777216 (1 << 24)
    • Все участники: 33554432 (1 << 25)
  • Кто может начинать групповые звонки
    • Только создатель: 134217728 (1 << 27)
    • Создатель и администраторы: 67108864 (1 << 26)
    • Все участники: 0
  • Кто может назначать администраторов
    • Только создатель: 0
    • Создатель и администраторы: 16 (1 << 4)

Дополнительные флаги:

  • Имеется фантомная копия чата: 65536 (1 << 16)
  • Является фантомным чатом: 32768 (1 << 15)

Зачем нужен random_id

random_id начиная с версии API 5.90 стал обязательным параметром. Но это не означает, что всем нужно генерировать уникальные значения для этого параметра. Если вы не собираетесь его использовать, то можете указать в его значении число 0.

Значение random_id должно быть уникальным в течение одного часа в рамках app_id, id пользователя и peer_id диалога.

Значение random_id может принимать числа от -2147483648 (-(2^31)) до 2147483647 (2^31 - 1). Если число будет больше или меньше данного порога, то из переданного числа отнимется этот лимит.

Основная задача этого параметра заключается в гарантировании идемпотентности API для отправки сообщений. Это означает, что при отправке запросов с одинаковым random_id и, чаще всего, одинаковыми параметрами, сервер не будет создавать новое сообщение и вернет ID уже созданного. Про необходимость данной технологии с убедительными примерами рассказывается в данной статье.

Наверняка вы уже видели, что во всех мессенджерах ВКонтакте при отправке сообщения само сообщение отображается сразу, но около сообщения некоторое время видно иконку часов. Эта иконка означает, что запрос на сервер с новым сообщением отправлен, но сообщение еще не пришло обратно через LongPoll.

Чтобы реализовать подобную фичу, нужно определить, какое именно сообщение, приходящее из LongPoll, было только что отправлено. Для этого нужно:

  1. Создать random_id и сохранить его в списке с отправляемыми сообщениями
  2. Отправить сообщение
  3. Дождаться прихода из LongPoll сообщения с нашим random_id
  4. Удалить random_id из списка, тем самым пометив сообщение как отправленное.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].