Шлюз

Шлюз: подключение

Шлюз — WebSocket-соединение, по которому сервер присылает события в реальном времени: новые сообщения, участники, команды. Бот подключается один раз и держит соединение открытым.

Подключение

text
wss://voice-chat.ru/gateway?bot_token=vbt_…

Токен передаётся параметром адреса (bot_token; также принимается token=Bot%20vbt_…). Сразу после подключения сервер присылает READY, затем — события. Подписываться ни на что не нужно: бот получает события всех своих серверов, каналов, которые может видеть, и личных бесед. Когда бота добавляют на новый сервер, подписка расширяется сама.

function connect(retry = 0) {
  const ws = new WebSocket(`wss://voice-chat.ru/gateway?bot_token=${encodeURIComponent(TOKEN)}`);
  let hb;
  ws.onopen = () => (hb = setInterval(() => ws.send(JSON.stringify({ op: "HEARTBEAT", d: {} })), 25_000));
  ws.onmessage = (e) => {
    const msg = JSON.parse(e.data);
    if (msg.op === "READY") retry = 0;
    if (msg.op === "DISPATCH") handle(msg.t, msg.d);
    if (msg.op === "ERROR") console.error(msg.d.message);
  };
  ws.onclose = (e) => {
    clearInterval(hb);
    if (e.code === 4001) return console.error("Неверный токен — не переподключаемся");
    setTimeout(() => connect(retry + 1), Math.min(30_000, 1000 * 2 ** retry));
  };
}
connect();

Формат сообщений

Каждое сообщение — JSON-объект. Клиент отправляет команды, сервер — ответы и события:

JSON
{ "op": "HEARTBEAT", "d": {} }                                  // клиент → сервер
{ "op": "READY", "d": { … } }                                   // сервер → клиент
{ "op": "DISPATCH", "t": "MESSAGE_CREATE", "d": { "message": { … } } }
{ "op": "ERROR", "d": { "message": "Слишком часто — подождите секунду" } }

READY

ПолеТипОписание
userUserСам бот.
servers{ id, name, icon, banner }[]Серверы бота.
serverChannels{ serverId, channels: { id, categoryId }[] }[]Каналы каждого сервера.
dmsDmChannel[]Личные беседы (members — id участников).
presence{ userId, status, activity }[]Кто сейчас в сети на серверах бота.
voiceRoomsobject[]Кто в голосовых каналах.

Подробности о сервере — GET /api/servers/:id. В READY есть и служебные поля приложения Voice (settings, appConfig и т. п.) — боту они не нужны.

Команды клиента

opdЧто делает
HEARTBEAT{}Пульс раз в 25 секунд. Ответ — HEARTBEAT_ACK { at }.
PRESENCE{ status: "online" | "idle" | "dnd" | "invisible" }Статус бота.
ACTIVITY_UPDATE{ activity: {…} | null }Активность — «Играет в …».
TYPING_START{ channelId }«Бот печатает…» на несколько секунд (не чаще раза в 4 секунды).
TIME_SYNC{ t0 }Сверка часов: ответ { t0, server }.

Живучесть соединения

  • Сервер раз в 30 секунд проверяет соединение (ping на уровне WebSocket) и закрывает зависшие. Отправляйте HEARTBEAT раз в 25 секунд.
  • Возобновления сессии нет: после переподключения придёт новый READY. Пропущенные сообщения можно дочитать через историю канала.
  • Переподключайтесь с растущей паузой (1, 2, 4… до 30 секунд).
  • Сброс токена в консоли закрывает все подключения бота.

Коды закрытия

КодПричинаЧто делать
4001Неверный или сброшенный токен, аккаунт заблокированНе переподключаться, проверить токен
4003Почта не подтверждена (только для людей)—
4008Слишком много подключений (60 в минуту с адреса, 12 одновременно на аккаунт) или флуд командамиПодождать и переподключиться реже
1000/1001/1006Обычное закрытие, перезапуск сервера, обрыв сетиПереподключиться
Не больше 800 сообщений клиента за 10 секунд на соединение — иначе оно закрывается с кодом 4008.

Все события и их данные — в разделе События.