Архитектура
Техническая документация
Открыть Shalter

Архитектура Shalter

Shalter — это однопроцессный мессенджер на Node.js с Express, SQLite (WAL) и WebSocket-сервером. Клиент построен на чистом ES module JavaScript без фреймворков.

Технологический стек

СлойТехнология
СерверNode.js, Express 5
База данныхSQLite 3 (better-sqlite3, WAL-режим)
Веб-сокетыws (Node.js Web Server API)
ВидеосвязьWebRTC PeerConnection
Клиент (web)Чистый HTML, CSS, ES module JavaScript
ДесктопTauri (Linux, Windows)
МобильныйAndroid (Kotlin)
Сборка клиентаesbuild (минификация, бандл)
Шифрование текстаserver/lib/textCrypto.js (AES-GCM)

Сервер

server/index.js

Точка входа — server/index.js. Express-приложение монтирует маршруты по группам:

ПрефиксМодульОписание
/api/bot-apiserver/routes/botApi.jsBot API
/api/oauthserver/routes/oauth.jsOAuth 2.0 (SSO в сторонние сервисы)
/api/chatsserver/routes/chats.jsЧаты, группы, каналы
/api/messagesserver/routes/messages.jsСообщения
/api/callsserver/routes/calls.jsЗвонки
/api/usersserver/routes/users.jsПользователи
/api/storiesserver/routes/stories.jsStories
/api/botsserver/routes/bots.jsУправление ботами
/api/giftsserver/routes/gifts.jsПодарки
/api/premiumserver/routes/premium.jsPremium и звёзды
/api/exportserver/routes/export.jsЭкспорт данных
/api/shalter-aiserver/routes/shalterAi.jsИИ-ассистент
/api/gamesserver/routes/games.jsМини-игры
/api/adsserver/routes/ads.jsРекламные кампании
/api/liveserver/routes/live.jsПрямые трансляции
/api/partnersserver/routes/partners.jsПартнёрская программа

Статические файлы из public/ обслуживаются через express.static(). SPA-режим: любой не-API путь, не начинающийся с /api/, отображает index.html (клиентский роутинг).

База данных

SQLite 3 через better-sqlite3. Журнал WAL (Write-Ahead Logging) для одновременного чтения и записи. Схема в server/db.js.

Основные таблицы

ТаблицаОписание
usersАккаунты: id, name, username, phone, email, isBot, isPremium, stars, тотп
chatsЧаты: id, type (dm|group|channel), title, username, ownerId, pinned, muted, archived
chat_membersСвязь чат ↔ пользователь (many-to-many), isAdmin, isOwner, isModerator
messagesСообщения: id, chatId, senderId, type, text (зашифр.), attachments, reactions, readByIds
chat_readsГраница прочитанного по чату (оптимизация)
botsБоты: userId, ownerId, token, description, commands, appUrl, appCode
chat_members → restrictionsОграничения (молчание) — JSON на чате
sessionsАктивные сессии с токенами доступа
storiesStories: userId, kind, url, expiresAt, viewedByIds
sticker_packsПаки стикеров (JSON колонка)
custom_emojiКастомные эмодзи
gamesМини-игры (HTML5, iframe)
gift_issuesВыпущенные эксклюзивные подарки с серийными номерами
scheduled_messagesОтложенные сообщения
data_exportsАудит экспорта данных для правовых запросов
Хранилище данных. Переписка шифруется на сервере (textCrypto.js). Поиск по сообщениям работает через FTS5-индекс по токенам (строятся из зашифрованного текста — токены поисковые, текст не раскрывается). Файлы вложений хранятся на диске и отдаются через serveUpload.

WebSocket

server/ws.js + public/js/lib/wsClient.js. WebSocket используется для:

  • Мгновенной доставки сообщений (message:new, message:updated, message:deleted)
  • Статуса печати (typing:update)
  • Сигнализации звонков (WebRTC offer/answer/candidate)
  • Обновлений статуса онлайна
  • Подачи постов и обновлений каналов в реальном времени

HTTP polling сохраняется как fallback для переподключения и догрузки истории.

WebRTC (звонки)

Голос и видео на WebRTC PeerConnection. Сигналинг через WebSocket (server/routes/calls.js, server/ws.js). Групповые звонки до 50 участников, PiP-режим, приглашение по ссылке с токеном доступа (calls.joinToken).

Клиент

Клиент — чистый ES module JavaScript без фреймворков (public/js/). Сервис-воркер (public/sw.js) кэширует оболочку для офлайн-работы. Роутинг — клиентский (public/js/router.js), view-компоненты в public/js/views/.

В продакшене клиент собирается через npm run build (esbuild) в public/dist/. В режиме разработки (npm run dev) обслуживаются сырые исходники из public/.

HTTP API

REST API на /api/. Авторизация через HTTP-only cookie с device token (см. server/middleware/auth.js). API возвращает JSON. Основные группы:

  • /api/bootstrap — загрузка данных пользователя и списка чатов при старте
  • /api/chats — CRUD чатов, участники, права
  • /api/messages — список, поиск, редактирование, удаление, реакции
  • /api/calls — история звонков, создание звонков
  • /api/users — профиль, статус, поиск
  • /api/stories — истории и отзывы
  • /api/gifts — каталог подарков, покупка за звёзды
  • /api/ads — рекламные кампании
  • /api/live — прямые трансляции
  • /api/games — мини-игры
  • /api/shalter-ai — ИИ-ассистент
  • /api/export — экспорт данных пользователя

Bot API

Bot API доступен на /api/bot-api/. Все методы требуют заголовка Authorization: Bearer <token>. Обновления приходят через long-polling (/updates?after=ISO&timeout=50). Подробная документация: справочник методов и полная документация.

Авторизация

  • По номеру телефона — SMS или звонок с кодом
  • Двухфакторная аутентификация (TOTP)
  • OAuth 2.0 — «Войти через Shalter» для сторонних сервисов
  • Recovery-коды при потере доступа к TOTP
Ограничения. Реализация рассчитана на один серверный процесс. Typing presence и WebSocket-соединения хранятся в памяти. Не рекомендуется масштабирование горизонтально без вынесения presence и сессий в отдельный сервис.
© Shalter. Архитектурная документация открыта для индексации поисковиками и ИИ-моделей.