longpoll-doc
longpoll-doc copied to clipboard
Документация для последней версии User LongPoll API
User LongPoll API
План документации:
- Отказ от ответственности
- Подключение
- Возвращаемые ошибки
- Получение истории событий
- Структура сообщения
-
Описание событий
- Событие 2. Установка флагов сообщения
- Событие 3. Сброс флагов сообщения
- Событие 4. Новое сообщение
- Событие 5. Редактирование сообщения
- Событие 6. Прочтение входящих сообщений
- Событие 7. Прочтение исходящих сообщений
- Событие 8. Друг появился в сети
- Событие 9. Друг вышел из сети
- Событие 10. Сброс флагов беседы
- Событие 12. Установка флагов беседы
- Событие 13. Удаление всех сообщений в диалоге
- Событие 18. Обновление сообщения
- Событие 19. Сброс кеша сообщения
- Событие 20. Закрепление и открепление беседы (изменился majorId)
- Событие 21. Изменился minorId
- Событие 51. Изменение данных чата (устарело)
- Событие 52. Изменение данных чата
- Событие 63. Статус набора сообщения
- Событие 64. Статус записи голосового сообщения
- Событие 65. Статус загрузки фотографии
- Событие 66. Статус загрузки видеозаписи
- Событие 67. Статус загрузки файла
- Событие 80. Изменение количества непрочитанных диалогов
- Событие 81. Изменение состояния невидимки друга
- Событие 90. Добавление или удаление из друзей
- Событие 114. Изменение настроек пуш-уведомлений в беседе
- Событие 115. Звонок
- Событие 119. Ответ callback-кнопки
-
Дополнительная информация
- Флаги сообщений
- Сервисные сообщения
- Клавиатура для ботов
- Вложения
- Права доступа в беседах
- Зачем нужен random_id
Документация написана для 10 версии LongPoll.
Отказ от ответственности
Автор не несет ответственности за точность, полноту или качество предоставленной информации. Используйте последующую информацию на свой страх и риск.
Правила пользования сайтом, пункт 6.7:
6.7. Создаваемые Пользователями приложения API должны использовать только опубликованные на Сайте методы API, а также ID, защищенный ключ и сервисный ключ доступа, указанные в настройках данных приложений. Использование других методов API, а также ID, защищенного ключа и сервисного ключа доступа приложений API третьих лиц, в т.ч. приложения API Администрации Сайта, строго запрещено. Пользователь обязуется регулярно проверять перечень разрешённых методов и незамедлительно вносить корректировки в функциональность своих приложений API в соответствии с изменениями перечня. За нарушение настоящего пункта Пользователь несет предусмотренную применимым законодательством, настоящими Правилами и иными документами Администрации Сайта ответственность. Администрация Сайта при этом оставляет за собой право на защиту собственных прав и законных интересов.
Подключение
Long Polling - это технология, используемая для получения событий в реальном времени, которая работает так:
- Запрос отправляется на сервер
- Сервер ждет нового события или таймаута
- Сервер возвращает список только что пришедших событий (или пустой список, если вернул ответ по таймауту)
Подробнее про данную технологию можно прочитать здесь.
Ссылка для запроса составляется следующим образом:
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
ошибка, но могут прийти и другие:
failed | Описание |
---|---|
1 | Устарела история событий. Решается получением пропущенной истории событий и использованием ts из ответа LongPoll |
2 | Истекло время действия ключа. Решается получением нового key через метод 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, за исключением удаления некоторых лишних событий (т.к. приходит просто измененный объект беседы или сообщения) и сокращения некоторых событий:
-
3
- Сброс флагов сообщения -
4
- Новое сообщение -
5
- Редактирование сообщения -
18
- Обновление сообщения
Структура этих событий выглядит так:
type LongPollHistoryMessageEvent = [
type: 3 | 4 | 5 | 18,
messageId: number,
flags: number,
peerId: number
];
Всю информацию о сообщениях и беседах можно взять из полей messages
и conversations
, где содержатся данные из API.
Если в ответе придет поле more
, то после обработки всех событий нужно будет повторить запрос, указав в поле pts
пришедший new_pts
.
Структура сообщения
Подробнее про некоторые части структуры можно почитать здесь:
- Флаги сообщений
- Шаблоны
- Клавиатура для ботов
- Сервисные сообщения
- Вложения
- random_id
Структура описывает массив, ключи используются только для описания значений
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. Установка флагов сообщения
Возможные значения флагов сообщения:
- Пометка важным (
8 important
) - Пометка как спам (
64 spam
) - Удаление сообщения (
128 deleted
) - Удаление для всех (
128 deleted
и131072 deleted_all
) - Прослушивание голосового сообщения (
4096 audio_listened
)
Событие приходит как при прослушивании собеседником вашего голосового сообщения, так и при прослушивании вами голосового сообщения собеседника.
Вручную прослушать голосовое сообщение собеседника можно с помощью метода messages.markAsListened
с параметром message_id
.
Метод вернет 1
при первом прослушивании голосового сообщения, а 0
при последующих или при попытке прослушать свое сообщение.
type Event2 = [
type: 2,
messageId: number,
flags: number,
peerId: number
];
Событие 3. Сброс флагов сообщения
Возможные значения флагов сообщения:
- Прочитано сообщение (
1 unread
). Устаревший флаг - Отмена пометки важным (
8 important
) - Отмена пометки сообщения как спам (
64 spam
и32768 cancel_spam
) - Восстановление удаленного сообщения (
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. Обновление сообщения
Приходит при следующих событиях:
- Добавился сниппет (ссылка) - к вложениям добавляется
link
. - Сообщение исчезло — удаляется текст и все вложения, добавляется ключ
is_expired: true
. - Пришел перевод голосового сообщения.
Данное событие возвращает сообщение.
type Event18 = LongPollMessage;
Событие 19. Сброс кеша сообщения
Приходит в двух случаях:
- По какой-либо причине изменилось сообщение (без явного редактирования). Необходимо переполучить сообщение через API.
- Сообщение исчезло. В данном случае можно игнорировать это событие, если вы обработали исчезновение сообщения в 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-кнопки работают следующим образом:
- Бот отправляет клавиатуру (обычную или инлайн), где находится callback-кнопка;
- Пользователь нажимает на эту кнопку и клиент вызывает метод
messages.sendMessageEvent
(параметры см. ниже). Метод возвращает строку -event_id
; - Бот получает событие
message_event
и вызывает методmessages.sendMessageEventAnswer
; - Этот метод вызывает
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 - старое название беседы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, было только что отправлено. Для этого нужно:
- Создать
random_id
и сохранить его в списке с отправляемыми сообщениями - Отправить сообщение
- Дождаться прихода из LongPoll сообщения с нашим
random_id
- Удалить
random_id
из списка, тем самым пометив сообщение как отправленное.