Webhooks – Події в реальному часі
Вебхуки BigBlueButton дозволяють вашому застосунку отримувати HTTP POST-сповіщення в реальному часі щоразу, коли відбуваються події зустрічі. Замість того щоб постійно опитувати getMeetings або getMeetingInfo, ви реєструєте URL-адресу зворотного виклику, і BigBlueButton автоматично надсилає вам події. У цьому розділі розглядаються три кінцеві точки API вебхуків, формат зворотного виклику, типи подій, поведінка повторних спроб і конфігурація сервера.
Для вебхуків потрібно, щоб на сервері було встановлено пакет bbb-webhooks. Кілька деталей, описаних у цьому розділі, не охоплені офіційною документацією BigBlueButton і були визначені шляхом аналізу вихідного коду. undocumented
Передумови
Пакет bbb-webhooks має бути встановлено на сервері BigBlueButton, перш ніж стануть доступними кінцеві точки вебхуків:
sudo apt-get install bbb-webhooks Якщо застосунок webhook не працює в момент створення зустрічі, внутрішнє зіставлення зустрічі не буде встановлено. У результаті для цієї зустрічі не буде викликано жодних callback.
hooks/create — зареєструвати вебхук
GET https://api-guide.bbbserver.com/bigbluebutton/api/hooks/create?<parameters>&checksum=replace-with-checksum Офіційна документація не визначає HTTP-метод. Маршрутизатор Express реєструє лише маршрути GET — запити POST не приймаються. undocumented
| Параметр | Тип | Обов’язково | За замовчуванням | Опис |
|---|---|---|---|---|
callbackURL | String | Так | — | URL-адреса, яка отримуватиме зворотні виклики POST. Виявлення дублікатів базується виключно на цій URL-адресі — ту саму URL-адресу не можна зареєструвати двічі, навіть з іншим meetingID або eventID. |
meetingID | String | Ні | — | Обмежує webhook конкретною зустріччю (зовнішній ідентифікатор зустрічі). Якщо параметр пропущено, webhook стає глобальним і спрацьовує для всіх зустрічей. |
eventID | String | Ні | — | Список типів подій, розділених комами, які слід відстежувати (наприклад, user-joined,meeting-ended). Якщо параметр пропущено, доставляються всі події. Фільтр нечутливий до регістру. Доступно з BBB 2.5. |
getRaw | Boolean | Ні | false | Якщо встановлено в true, зворотні виклики містять сире повідомлення Redis замість оброблених даних події. |
Успішна відповідь
<response>
<returncode>SUCCESS</returncode>
<hookID>replace-with-hook-id</hookID>
<permanentHook>false</permanentHook>
<rawData>false</rawData>
</response> Дубльована реєстрація
Якщо той самий callbackURL реєструється знову, відповідь однаково повертає SUCCESS, але містить duplicateWarning. Існуючий webhook залишається без змін — meetingID, eventID і getRaw не оновлюються.
<response>
<returncode>SUCCESS</returncode>
<hookID>replace-with-hook-id</hookID>
<messageKey>duplicateWarning</messageKey>
<message>There is already a hook for this callback URL.</message>
</response> Відповіді з помилками
messageKey | Опис |
|---|---|
checksumError | Контрольна сума недійсна або відсутня. |
missingParamCallbackURL | Параметр callbackURL не було надано. undocumented |
createHookError | Сталася внутрішня помилка (наприклад, Redis недоступний). Перевірте журнали сервера. |
hooks/list — перелік зареєстрованих вебхуків
GET https://api-guide.bbbserver.com/bigbluebutton/api/hooks/list?<parameters>&checksum=replace-with-checksum | Параметр | Тип | Обов’язково | Опис |
|---|---|---|---|
meetingID | String | Ні | Фільтрує за ID зустрічі. Результат містить як хуки для вказаної зустрічі, так і всі глобальні хуки. Якщо параметр не вказано, повертаються всі зареєстровані хуки. |
Успішна відповідь
<response>
<returncode>SUCCESS</returncode>
<hooks>
<hook>
<hookID>replace-with-hook-id</hookID>
<callbackURL><![CDATA[https://api-guide.bbbserver.com/callbacks/webhook]]></callbackURL>
<meetingID><![CDATA[replace-with-meeting-id]]></meetingID>
<eventID>user-joined,meeting-ended</eventID>
<permanentHook>false</permanentHook>
<rawData>false</rawData>
</hook>
</hooks>
</response> Елемент <meetingID> з’являється лише для хуків, прив’язаних до конкретної зустрічі. Глобальні хуки не мають елемента <meetingID>. Так само, <eventID> з’являється лише тоді, коли під час створення було встановлено фільтр подій.
Відповіді з помилками
messageKey | Опис |
|---|---|
checksumError | Контрольна сума недійсна або відсутня. |
listHookError | Під час отримання списку хуків сталася внутрішня помилка. Перевірте журнали сервера. undocumented |
hooks/destroy — видалити вебхук
GET https://api-guide.bbbserver.com/bigbluebutton/api/hooks/destroy?<parameters>&checksum=replace-with-checksum | Параметр | Тип | Обов’язково | Опис |
|---|---|---|---|
hookID | String | Так | ID хука, який потрібно видалити (отриманий із hooks/create або hooks/list). |
Успішна відповідь
<response>
<returncode>SUCCESS</returncode>
<removed>true</removed>
</response> Постійні хуки (налаштовані на боці сервера через permanentURLs) не можна видалити через API. Спроба зробити це повертає помилку destroyMissingHook, ніби такого хука не існує.
Відповіді з помилками
messageKey | Опис |
|---|---|
checksumError | Контрольна сума недійсна або відсутня. |
missingParamHookID | Параметр hookID не було надано. |
destroyMissingHook | ID хука не існує або належить постійному хуку. |
destroyHookError | Під час видалення хука сталася внутрішня помилка. Перевірте журнали сервера. |
hooks/ping — перевірка працездатності
GET https://api-guide.bbbserver.com/bigbluebutton/api/hooks/ping Ця діагностична кінцева точка не потребує контрольної суми. Якщо застосунок вебхука доступний, вона повертає рядок звичайного тексту bbb-webhooks API up! (не XML, тип вмісту text/plain). undocumented
Формат зворотного виклику
Зворотні виклики вебхука надсилаються як запити HTTP POST з типом вмісту application/x-www-form-urlencoded. Тіло запиту містить три поля:
| Поле | Опис |
|---|---|
domain | Домен сервера (із конфігурації вебхука). undocumented |
event | Масив JSON, що містить дані події. Завжди масив, навіть для однієї події. |
timestamp | Мітка часу Unix у мілісекундах на момент відправлення. |
Тіло обробленого зворотного виклику (getRaw=false)
domain=myserver.com&event=[{"data":{"type":"event","id":"user-joined","attributes":{...},"event":{"ts":1532718316938}}}]×tamp=1532718316953 Тіло сирого зворотного виклику (getRaw=true)
domain=myserver.com&event=[{"envelope":{"name":"UserJoinedMeetingEvtMsg","routing":{"sender":"bbb-apps-akka"}},"core":{"header":{...},"body":{...}}}]×tamp=1532718316953 Коли сервер налаштовано зі значенням multiEvent більшим за 1, кілька подій можуть бути об’єднані в масиві event в межах одного зворотного виклику.
Перевірка контрольної суми зворотного виклику
У типовому режимі кожна URL-адреса зворотного виклику отримує параметр запиту checksum, який ваш застосунок повинен перевірити:
https://api-guide.bbbserver.com/callbacks/webhook?checksum=replace-with-checksum Формула перевірки така:
sha<algo>(<callback-URL-without-checksum> + <URL-encoded-body> + <shared-secret>) Візьміть зареєстрований URL зворотного виклику без параметра checksum.
Додайте повністю URL-кодоване тіло запиту (domain=...&event=[...]×tamp=...).
Додайте спільний секрет BBB.
Обчисліть хеш отриманого рядка за допомогою налаштованого алгоритму (типово: sha1, можна налаштувати через hookChecksumAlgorithm).
Режим Auth 2.0 / Bearer
Альтернативно сервер можна налаштувати за допомогою auth2_0: true. У цьому режимі параметр контрольної суми не додається до URL-адреси зворотного виклику. Натомість спільний секрет надсилається як токен Bearer у заголовку Authorization: undocumented
Authorization: Bearer <shared-secret> Поведінка зворотного виклику
- Прийняті коди стану HTTP: HTTP
2xxі HTTP401вважаються успішною доставкою. Усі інші коди стану спричиняють повторну спробу. undocumented - Перенаправлення: відповіді HTTP
3xxобробляються (до 10 переходів). Лише якщо після 10 перенаправлень не буде досягнуто2xx/401, зворотний виклик вважається невдалим. - Тайм-аут: Кожен запит зворотного виклику має тайм-аут 5 секунд (можна налаштувати через
requestTimeout). - Інтервали повторних спроб: У разі помилки повторні спроби використовують експоненційне збільшення інтервалів:
100ms, 500ms, 1s, 2s, 4s, 8s, 10s, 30s, 60s, 60s, 60s, 60s(12 спроб протягом приблизно 5 хвилин, можна налаштувати черезretryIntervals). - Після вичерпання всіх повторних спроб: Непостійні хуки автоматично видаляються. Постійні хуки продовжують повторні спроби безстроково з інтервалом 60 секунд (можна налаштувати через
permanentIntervalReset).
Типи подій
Події зустрічі
| ID події | Опис |
|---|---|
meeting-created | Зустріч була створена. |
meeting-ended | Зустріч завершилася. Це також спричиняє синтетичні події user-left для всіх підключених користувачів. |
meeting-recording-started | Запис розпочато. |
meeting-recording-stopped | Запис зупинено. |
meeting-recording-unhandled | Необроблена подія запису (резервний варіант, коли статус запису не є ні true, ні false). |
meeting-screenshare-started | Почато демонстрацію екрана (включає дані користувача-доповідача). |
meeting-screenshare-stopped | Демонстрацію екрана зупинено (включає дані користувача-власника). |
meeting-presentation-changed | Активну презентацію змінено (включає presentation-id). |
Події користувача
| ID події | Опис |
|---|---|
user-joined | Користувач приєднався до зустрічі (включає ознаку гостя, дані користувача, IP-адресу, User-Agent). |
user-left | Користувач залишив зустріч (включає прапорець гостя). Також генерується синтетично під час meeting-ended. |
user-audio-voice-enabled | Аудіо увімкнено (включає прапорці listening-only, sharing-mic, muted). |
user-audio-voice-disabled | Аудіо вимкнено. |
user-audio-muted | Користувача було вимкнено звук. |
user-audio-unmuted | Користувачу було ввімкнено звук. |
user-audio-unhandled | Необроблена аудіоподія (резервний варіант). |
user-cam-broadcast-start | Вебкамера запущена (включає stream-id). |
user-cam-broadcast-end | Вебкамеру зупинено. |
user-presenter-assigned | Користувачу було призначено роль ведучого. |
user-presenter-unassigned | Користувача було позбавлено ролі ведучого. |
user-emoji-changed | Змінено емодзі або реакцію користувача (включає значення емодзі). |
user-raise-hand-changed | Користувач підняв або опустив руку (включає булеве значення raise-hand). У версіях BBB до 2.7 це генерується синтетично з user-emoji-changed. |
Події чату та нотаток
| ID події | Опис |
|---|---|
chat-group-message-sent | Повідомлення було надіслано в публічний чат. Повідомлення приватного чату не генерують webhook-подій. |
transcript-updated | Транскрипцію оновлено (включає transcript, locale, прапорець final). |
pad-content | Вміст спільних нотаток змінено (включає pad-id, rev, text). |
Події опитувань
| ID події | Опис |
|---|---|
poll-started | Опитування було розпочато (включає запитання та варіанти відповідей). |
poll-responded | Учасник відповів на опитування (включає ID відповідей). |
Події запису та відтворення (RAP)
| ID події | Опис |
|---|---|
rap-archive-started | Архівування розпочато. |
rap-archive-ended | Архівування завершено (включає прапорець recorded і тривалість). |
rap-sanity-started | Перевірку цілісності розпочато. |
rap-sanity-ended | Перевірку цілісності завершено. |
rap-post-archive-started | Післяархівну обробку розпочато. |
rap-post-archive-ended | Післяархівну обробку завершено. |
rap-process-started | Обробку розпочато. |
rap-process-ended | Обробку завершено. |
rap-post-process-started | Післяобробку розпочато. |
rap-post-process-ended | Післяобробку завершено. |
rap-publish-started | Публікацію розпочато. |
rap-publish-ended | Публікацію завершено (включає повний об’єкт запису з метаданими, інформацією про відтворення та завантаження). |
rap-post-publish-started | Післяпублікаційну обробку розпочато. |
rap-post-publish-ended | Післяпублікаційну обробку завершено. |
rap-published | Запис опубліковано. |
rap-unpublished | Публікацію запису скасовано. |
rap-deleted | Запис видалено. |
Більшість подій RAP включають record-id, success (булеве значення) і step-time. Події з полем workflow додатково містять назву робочого процесу обробки.
Конфігурація сервера
Наведені нижче параметри можна налаштувати в /etc/bigbluebutton/bbb-webhooks.yml або config/default.yml. Більшість із них не описано в офіційній документації. undocumented
| Варіант | За замовчуванням | Опис |
|---|---|---|
hookChecksumAlgorithm | sha1 | Алгоритм хешування для контрольних сум зворотних викликів (sha1, sha256, sha384, sha512). |
api.supportedChecksumAlgorithms | [sha1, sha256, sha384, sha512] | Прийнятні алгоритми для вхідних контрольних сум API. |
api.port | 3005 | Порт сервера API webhook. |
api.bind | 127.0.0.1 | Адреса прив’язки сервера API. |
includeEvents | [] | Глобальний фільтр подій сервера: лише ці події надсилаються до всіх hook-ів. Порожнє значення означає всі події. |
excludeEvents | [] | Глобальний фільтр подій сервера: ці події пригнічуються для всіх hook-ів. Порожнє значення означає відсутність виключень. |
permanentURLs | [] | Список постійних URL hook-ів, які реєструються під час запуску і не можуть бути видалені через API. |
retryIntervals | [100,500,1000,...,60000] | Інтервали повторних спроб у мілісекундах для callback-запитів, що завершилися невдачею. |
permanentIntervalReset | 60000 | Інтервал повторної спроби в мілісекундах для постійних hook-ів після вичерпання всіх звичайних повторних спроб. |
requestTimeout | 5000 | Тайм-аут HTTP у мілісекундах для callback-запитів. |
multiEvent | 1 | Якщо встановлено значення більше 1, кілька подій об’єднуються в масиві подій для одного callback-виклику. |
queueSize | 10000 | Максимальний розмір внутрішньої черги подій. |
bbb.auth2_0 | false | Увімкнює автентифікацію токеном Bearer замість контрольної суми URL для зворотних викликів. |
includeEvents і excludeEvents — це загальносерверні фільтри, які застосовуються додатково до фільтра eventID для кожного hook. Щоб подію було доставлено, вона має пройти обидва фільтри.
Операційні примітки
- Збереження: Хуки зберігаються в Redis і переживають перезапуск сервера (повторно синхронізуються під час запуску).
- Порядок: Зворотні виклики надсилаються послідовно для кожного hook, по одному за раз, із збереженням порядку подій.
- Унікальність URL: Виявлення дублікатів базується виключно на URL-адресі зворотного виклику. Ту саму URL-адресу не можна зареєструвати з іншими фільтрами
meetingIDабоeventID— перша реєстрація має пріоритет. - Очищення даних: Внутрішні зіставлення meeting видаляються після одного тижня неактивності (налаштовується через
mappings.timeout, типово: 604800000 мс). - Синтетичні події: Коли зустріч завершується, події
user-leftавтоматично генеруються для всіх користувачів, які все ще підключені, тому що сам BigBlueButton не генеруєUserLeftMeetingEvtMsgпід час завершення зустрічі. - Приватні чати: Лише повідомлення публічного чату генерують події
chat-group-message-sent. Приватні повідомлення тихо ігноруються.
meetingID — глобальні хуки без meetingID не підтримуються; (2) персональні дані в подіях автоматично обфускуються з міркувань приватності (наприклад, IP-адреси учасників не видно).Поширені запитання
bbb-webhooks має бути встановлений через apt-get install bbb-webhooks. Без нього кінцеві точки hooks/create, hooks/list і hooks/destroy недоступні.duplicateWarning, а наявний хук залишиться без змін. Щоб окремо відстежувати конкретні зустрічі, використовуйте різні URL-адреси зворотного виклику.MAIN-PUBLIC-GROUP-CHAT), запускають подію chat-group-message-sent. Приватні повідомлення між учасниками не генерують жодних подій вебхуків.getRaw=false (типовий режим) ви отримуєте оброблені дані подій зі стандартизованою структурою, що містить поля type, id і attributes. З getRaw=true ви отримуєте сире повідомлення Redis, опубліковане внутрішньо BigBlueButton, яке містить поля envelope і core. Сирий формат корисний для налагодження або коли вам потрібні дані, яких немає в обробленому форматі.permanentURLs і не можуть бути видалені через API. Виклик hooks/destroy для постійного хука повертає помилку destroyMissingHook так, ніби такого хука не існує.2xx і HTTP 401 обидва вважаються успішною доставкою. Усі інші коди стану, включно з 3xx (після виконання до 10 перенаправлень), 4xx (крім 401) і 5xx, спричиняють повторну спробу. Ця поведінка не задокументована в офіційній документації BigBlueButton.