Документація tg_client

Цей документ описує всі модулі пакету tg_client, окрім директорії graphQL/. У центрі уваги — робота з TDLib, керування сесіями userbot-ів, авторизація, взаємодія з Redis/WebSocket та сервіси для діалогів і медіа.

Примітка: документація не охоплює GraphQL-шару. Якщо потрібна інтеграція з API, використовуйте наведені нижче сервіси як джерело даних та подій. Інформацію по GraphQL-шару можна знайти ТУТ.

1. Огляд архітектури

Пакет складається з кількох горизонтальних шарів:

Основні залежності

  • TDLib (через python-telegram)
  • Redis для шини подій/команд
  • Django ORM + Channels
  • S3/MinIO для медіафайлів

Ключові сервіси

  • TDLibHelper — фасад для API
  • SessionManager — контроль сесій
  • TDLibDialogService — парсер історії
  • WS-консюмери для auth та списку чатів

2. Структура директорій

Каталог Призначення
tg_client/models.py Моделі UserBot та CustomEmoji.
tg_client/_tg_utils/ Конфіг TDLib (config.py) і SessionManager для блокувань та життєвого циклу клієнтів.
tg_client/auth/ Channels-консюмер TDLibAuthConsumer для проходження login/code/password.
tg_client/dialogs/services/ Бізнес-логіка: TDLibHelper, парсер повідомлень, збереження медіа, хелпер UTF-16.
tg_client/dialogs/handlers/ Обробка updateNewMessage з TDLib та пуш у Redis.
tg_client/dialogs/listeners/ Головний лістенер, що стартує userbot-клієнти, слухає Redis-команди й шле відповіді.
tg_client/dialogs/ws/ WebSocket API для фронтенду (наприклад, list_chats/consumers.py).

3. Моделі Django

UserBot

CustomEmoji

4. _tg_utils

config.py

session_manager.py

5. WebSocket-авторизація (tg_client/auth)

TDLibAuthConsumer керує повним циклом логіну userbot-а:

  1. start — ініціалізує SessionManager, створює TDLib-клієнт, запускає login(blocking=False).
  2. send_code — передає код підтвердження (AuthorizationState.WAIT_CODE).
  3. send_password — вводить 2FA (AuthorizationState.WAIT_PASSWORD).
  4. Після READY витягує профіль через get_me(), оновлює UserBot, закриває сесію.

Комунікація завжди ведеться через JSON-повідомлення Channels, Redis тут не залучений.

Ендпойнт WebSocket: wss://<host>/ws/tg-auth/ (див. tg_client/routing.py).

Приклади клієнтських запитів

1. Старт авторизації:

{
  "action": "start",
  "userbot_id": 12,
  "phone": "+380955870336"
}

2. Передача одноразового коду (стає доступною після події code_required):

{
  "action": "send_code",
  "code": "12345"
}

3. Введення 2FA-пароля (коли бекенд надіслав password_required):

{
  "action": "send_password",
  "password": "my-secret"
}

Приклади відповідей сервера

{"type": "connected", "message": "WebSocket connected"}
{"type": "status", "message": "Connecting to Telegram..."}
{"type": "code_required", "message": "Confirmation code sent"}
{"type": "authorized", "message": "Authorization completed", "username": "akva_bot", ...}

Після закриття з'єднання сесія примусово завершується, тому повторні спроби починаються з нового start.

6. Сервіси діалогів

TDLibHelper (dialogs/services/tg_requests.py)

TDLibDialogService

save_to_cloud.py

utf_index_to_py_index.py

Конвертує UTF-16 індекси (які повертає TDLib) у Python-індекси, щоб коректно працювати з емодзі/сурогатами.

7. Лістенери та обробники

main_listener.py

handle_new_update.py

8. WebSocket API для діалогів

TDLibListChatsConsumer

Action (WS) Очікувані поля Результат із Redis
get_chats userbot_id, опц. limit, offset_order, offset_chat_id Послідовність {type: "get_chats", payload: chat_item}
open_dialog chat_id, from_message_id, опц. topic_id Потік повідомлень (message) + dialog_end + media_ready; для форумів без topic_id повертає топіки
send_message chat_id, text send_message або send_message_error
get_prem_path emoji_id Посилання на лотті/відео кастомного емодзі
forward_message to_chat_id, from_chat_id, message_id forward_message або forward_message_error
reply_message chat_id, reply_to_message_id, text reply_message або reply_message_error
import_contacts userbot_id, phone import_contacts або import_contacts_error

Події з Redis

Приклади payload-ів

/ws/chats/
{"action": "open_client", "userbot_ids": [1, 2], "user_id": 1}
{"action": "get_chats", "userbot_id": 1, "user_id": 1}
{"action": "open_dialog", "userbot_id": 1, "from_message_id": "0", "chat_id": "123"}
{"action": "open_dialog", "userbot_id": 1, "from_message_id": "0", "chat_id": "123", "topic_id": "456"}

// Відправити повідомлення
{"action": "send_message", "userbot_id": 1, "chat_id": "123", "text": "Привіт"}

// Переслати повідомлення
{"action": "forward_message", "userbot_id": 1, "to_chat_id": "488386685", "from_chat_id": "2123445553", "message_id": "984071798784"}

// Reply на конкретне повідомлення
{"action": "reply_message", "userbot_id": 1, "chat_id": "2123445553", "reply_to_message_id": "984121081856", "text": "Відповідаю"}

9. Потік даних

Команди від фронтенду

  1. React/SPA шле action у WebSocket (dialogs/ws).
  2. WS-консюмер публікує JSON у Redis-канал tg_commands.
  3. listen_for_commands() читає повідомлення, викликає TDLibHelper.
  4. Результат (або помилка) повертається через send_ws() у канал chat_list_updates.
  5. WS-консюмер відправляє payload назад клієнту.

Push-оновлення

  1. TDLib кидає updateNewMessage.
  2. handle_new_update парсить повідомлення через TDLibDialogService та формує payload із тими ж полями, що повертає open_dialog.
  3. Подія з userbot_id, unread_count та деталями месиджу публікується у chat_list_updates й летить на фронт.
  4. Якщо у повідомленні є файл/кастомне емодзі/іконка топіка, окремо приходить media_ready з метаданими (поступова доставка медіа).

10. Типові сценарії

Пагінація чатів

Беріть order і chat_id з останнього елемента відповіді. Передавайте їх як offset_order/offset_chat_id у наступному get_chats, аби TDLib видав наступний блок.

Завантаження медіа

TDLibHelper.download_file() викликає downloadFile+getFile, чекає завершення, зберігає у S3/MinIO та повертає presigned URL. Встановіть return_meta=True, якщо потрібно локальний шлях.

Парсинг історії

TDLibDialogService.get_dialog() приймає chat_id та from_message_id. Якщо історія порожня, поверне is_empty=True + дані чату.

Робота з кастомними емодзі

При першому використанні емодзі helper завантажує asset, зберігає у CustomEmoji, повертає JSON/WebM. Повторні звернення беруться з БД.

11. Рекомендації з розширення