Files
TG_autoposter/docs/ARCHITECTURE.md
2025-12-18 05:55:32 +09:00

15 KiB
Raw Blame History

Архитектура TG Autoposter

Общая структура

┌─────────────────────────────────────────────────────┐
│         Telegram User (в личных сообщениях)         │
└──────────────────────┬──────────────────────────────┘
                       │
                       ↓
┌─────────────────────────────────────────────────────┐
│              Telegram Bot (python-telegram-bot)      │
│                   main.py → app/__init__.py          │
└──────────────────┬──────────────────┬──────────────┘
                   │                  │
        ┌──────────┘                  └────────────┐
        ↓                                          ↓
   ┌─────────────┐                        ┌──────────────┐
   │  Handlers   │                        │  Callbacks   │
   │  (команды)  │                        │  (кнопки)    │
   └──────┬──────┘                        └──────┬───────┘
          │                                      │
          └──────────────┬───────────────────────┘
                         ↓
         ┌───────────────────────────────┐
         │    Database Repository        │
         │  (repository.py)              │
         │  - GroupRepository            │
         │  - MessageRepository          │
         │  - MessageGroupRepository     │
         └──────────────┬────────────────┘
                        ↓
         ┌───────────────────────────────┐
         │      SQLAlchemy ORM           │
         │  (database/__init__.py)       │
         │  - AsyncSessionLocal          │
         │  - engine                     │
         └──────────────┬────────────────┘
                        ↓
         ┌───────────────────────────────┐
         │    Database (SQLite/PgSQL)    │
         │  - groups                     │
         │  - messages                   │
         │  - message_groups             │
         └───────────────────────────────┘

Слои приложения

1. Presentation Layer (Telegram Bot)

  • Файлы: handlers/, utils/keyboards.py
  • Отвечает за взаимодействие с пользователем
  • Обработка команд и callback'ов
  • Формирование инлайн кнопок

2. Application Logic Layer (Handlers)

  • Файлы: handlers/commands.py, handlers/callbacks.py, handlers/sender.py, handlers/message_manager.py, handlers/group_manager.py
  • Бизнес-логика отправки сообщений
  • Учет slow mode
  • Управление сообщениями и группами

3. Repository Layer (Data Access)

  • Файл: database/repository.py
  • CRUD операции для каждой сущности
  • Абстракция работы с БД
  • Защита от прямых SQL запросов

4. ORM Layer (Object-Relational Mapping)

  • Файл: database/__init__.py
  • SQLAlchemy для работы с БД
  • Асинхронные сессии
  • Управление подключением

5. Data Layer (Models & Database)

  • Файлы: models/, база данных
  • Определение структуры данных
  • Связи между таблицами
  • Физическое хранилище

Модели данных

Group (Группа)

┌──────────────────┐
│     Group        │
├──────────────────┤
│ id (PK)          │
│ chat_id (UNQ)    │
│ title            │
│ slow_mode_delay  │
│ last_message_time│
│ is_active        │
│ created_at       │
│ updated_at       │
└──────────────────┘
         │
         │ 1..N
         │
         └───────────────────┐
                             │
                    ┌────────────────┐
                    │ MessageGroup   │
                    │ (pivot table)  │
                    └────────────────┘
                             │
                             │ 1..N
                             │
                    ┌────────────────┐
                    │    Message     │
                    │ (Сообщение)    │
                    └────────────────┘

Поток данных при отправке сообщения

1. Пользователь нажимает "📤 Отправить"
   │
   ↓
2. send_message() получает callback
   │
   ├─→ Получить сообщение из БД
   │   (MessageRepository.get_message)
   │
   ├─→ Получить все связи для отправки
   │   (MessageGroupRepository.get_message_groups_to_send)
   │
   ↓
3. Для каждой группы:
   │
   ├─→ Проверить slow mode
   │   (can_send_message() из utils)
   │
   ├─→ Если нужно, ждать
   │   (asyncio.sleep)
   │
   ├─→ Отправить сообщение через Bot API
   │   (context.bot.send_message)
   │
   ├─→ Обновить время последнего сообщения
   │   (GroupRepository.update_last_message_time)
   │
   ├─→ Отметить как отправленное
   │   (MessageGroupRepository.mark_as_sent)
   │
   └─→ Обновить статус в UI
       (query.edit_message_text)

4. Показать итоговое сообщение пользователю

Поток данных при добавлении бота в группу

1. Бот добавлен в группу
   │
   ↓
2. Telegram отправляет my_chat_member update
   │
   ↓
3. my_chat_member() обработчик получает событие
   │
   ├─→ Проверить статус: member или left
   │
   ├─→ Если member:
   │   │
   │   ├─→ Получить информацию о группе
   │   │   (context.bot.get_chat)
   │   │
   │   ├─→ Получить slow mode
   │   │
   │   ├─→ Проверить есть ли уже в БД
   │   │   (GroupRepository.get_group_by_chat_id)
   │   │
   │   └─→ Добавить или обновить
   │       (GroupRepository.add_group)
   │
   └─→ Если left:
       │
       └─→ Деактивировать в БД
           (GroupRepository.deactivate_group)

Асинхронность

Весь код использует async/await:

async def main():
    # Инициализация
    await init_db()
    
    # Создание приложения
    application = Application.builder().token(TOKEN).build()
    
    # Добавление обработчиков
    application.add_handler(...)
    
    # Polling (слушаем обновления)
    await application.run_polling()

Обработка ошибок

┌─────────────────────────────────────┐
│  Попытка отправки сообщения         │
└────────────┬────────────────────────┘
             │
      ┌──────┴──────┐
      │             │
      ↓             ↓
   SUCCESS      EXCEPTION
      │             │
      ├─→ mark_as_sent()  ├─→ Сохранить ошибку
      │   (is_sent=True)      mark_as_sent(error=str(e))
      │                       (is_sent=False)
      └─────────┬──────────┬──────────┘
                 │         │
                 └─────────┘
                   │
                   ↓
            Показать статус
            пользователю

Состояния ConversationHandler

При создании сообщения:

START
  │
  └─→ CREATE_MSG_TITLE
      (ввод названия)
  │
  └─→ CREATE_MSG_TEXT
      (ввод текста, создание в БД)
  │
  └─→ SELECT_GROUPS
      (выбор групп с кнопками)
  │
  └─→ DONE или CANCEL
      (завершение)

Безопасность данных

Уровни защиты:

  1. Переменные окружения (.env)

    • Токен бота не в коде
    • DATABASE_URL скрыт
  2. Асинхронные сессии

    • Каждая операция в собственной транзакции
    • Автоматический rollback при ошибке
  3. SQL Injection

    • SQLAlchemy использует parameterized queries
    • Защита встроена в ORM
  4. Логирование

    • Чувствительные данные не логируются
    • Ошибки записываются в файл с ротацией

Масштабируемость

Текущие возможности:

  • Линейная масштабируемость с количеством групп
  • Асинхронная обработка не блокирует бота
  • БД может быть PostgreSQL для производства
  • Логирование с ротацией

Возможные улучшения:

  • Queue (Celery) для больших рассылок
  • Cache (Redis) для часто используемых данных
  • Webhook вместо polling для масштабирования
  • Connection pooling для БД

Производительность

Оптимизации:

  1. Асинхронность

    • Не блокирует при I/O операциях
    • Может обрабатывать много групп параллельно
  2. Batch операции

    • Отправка в несколько групп одновременно
    • Кэширование результатов
  3. Индексы в БД

    • chat_id в таблице Groups (UNIQUE)
    • Foreign keys оптимизированы

Тестирование

Структура для тестирования:

tests/
├── test_models.py        # Модели
├── test_repository.py    # Репозитории
├── test_handlers.py      # Обработчики
└── test_integration.py   # Интеграция

Развертывание

Production deployment:

1. Клонировать репо
2. pip install -r requirements.txt
3. Настроить .env с реальным токеном
4. Использовать PostgreSQL вместо SQLite
5. Запустить с systemd/supervisor
6. Настроить ротацию логов
7. Мониторинг и алерты

Взаимодействие компонентов

┌────────────────────────────────────────────────────────────┐
│                    Telegram Bot (main.py)                   │
├────────────────────────────────────────────────────────────┤
│ Application (python-telegram-bot)                          │
│  ├─ CommandHandler (/start, /help)                        │
│  ├─ CallbackQueryHandler (callback buttons)               │
│  ├─ ChatMemberHandler (my_chat_member events)             │
│  └─ ConversationHandler (multi-step flows)                │
└────────────────────────────────────────────────────────────┘
        ↓               ↓              ↓             ↓
   ┌─────────┐  ┌────────────┐  ┌──────────┐  ┌─────────────┐
   │ commands │  │ callbacks  │  │  sender  │  │group_manager│
   │   .py    │  │    .py     │  │   .py    │  │    .py      │
   └────┬─────┘  └──────┬─────┘  └────┬─────┘  └──────┬──────┘
        │                │             │               │
        └────────────────┼─────────────┼───────────────┘
                         │
                    ┌────▼────┐
                    │ message_ │
                    │manager.py│
                    └────┬─────┘
                         │
              ┌──────────┴──────────┐
              │                     │
         ┌────▼────────┐      ┌────▼────────┐
         │ Repository  │      │ Utils       │
         │   Layer     │      │  - keyboards│
         │             │      │  - slow_mode│
         └────┬────────┘      └─────────────┘
              │
         ┌────▼─────────┐
         │  SQLAlchemy  │
         │     ORM      │
         └────┬─────────┘
              │
         ┌────▼──────────┐
         │  SQLite/PgSQL │
         │   Database    │
         └───────────────┘

Это архитектура позволяет:

  • Легко тестировать каждый слой
  • Менять БД без изменения логики
  • Расширять функциональность
  • Масштабировать приложение