Добавить в корзинуПозвонить
Найти в Дзене

MAX + СГО + Yandex Cloud: как мы построили школьного бота посещаемости с отказоустойчивостью

Этот материал для тех, кто: Итоговая связка: Изначально использовался Apps Script-only подход. UX был быстрый, но при первых же боевых сценариях проявился блокер: Ключевой вывод: проблема была не в кнопках MAX, а в транспортном слое и стабильности связки Apps Script -> СГО. Поэтому принято решение: Поток данных: Плюс архитектуры: Дата для заявки берется автоматически как текущая (выбор даты убран, чтобы ускорить поток). Исправлены критичные моменты: Добавлен обязательный best-effort logout после операций: Практическая причина: не оставлять “висящие” сессии в СГО. Если СГО недоступен: Через Yandex Cloud Timer Triggers настроены ежедневные вызовы: Логика: На этапе подключения Google Cloud уперлись в ограничения billing-профиля по стране для целевого аккаунта. Для быстрой и предсказуемой доставки выбрали Yandex Cloud: Для школьного процесса “бот посещаемости” важнее не идеальная красота кода, а надежность и предсказуемость: Именно эта комбинация делает систему реально рабочей в условиях н
Оглавление

Кому и зачем эта архитектура

Этот материал для тех, кто:

  • ведет посещаемость в СГО;
  • хочет работать через привычный мессенджер MAX;
  • не хочет держать критичную логику на домашнем ПК;
  • хочет, чтобы данные не терялись при сбоях СГО.

Итоговая связка:

  • MAX — интерфейс для учителей;
  • Yandex Cloud Serverless Containers — backend (логика и интеграции);
  • СГО — источник классов и целевая система записи посещаемости;
  • очередь/инциденты — страховка на случай недоступности СГО.

Что не сработало в первом приближении (и почему это важно)

Изначально использовался Apps Script-only подход. UX был быстрый, но при первых же боевых сценариях проявился блокер:

  • запрос к https://sgo.rso23.ru/webapi/logindata периодически зависал/падал;
  • MAX-сценарий стартовал, но на шаге получения классов/данных из СГО ломался.

Ключевой вывод: проблема была не в кнопках MAX, а в транспортном слое и стабильности связки Apps Script -> СГО.

Поэтому принято решение:

  • оставить MAX как фронт;
  • вынести интеграцию с СГО в Python backend в облаке.

Целевая архитектура

Поток данных:

  1. Учитель нажимает кнопки в MAX.
  2. MAX шлет webhook в backend (/webhooks/max).
  3. Backend:отдает меню/кнопки;
    получает классы и список учеников из СГО;
    отправляет отметки в СГО;
    при сбое сохраняет заявку в очередь.
  4. Плановые проверки (12:00, 18:00, 23:00) оценивают хвост ошибок.

Плюс архитектуры:

  • минимальная инфраструктура;
  • быстрый запуск;
  • понятный UX;
  • нет привязки к локальному ПК.

Что реализовано в MVP

1) Кнопочный сценарий в MAX

  • Посещаемость;
  • Проставить отсутствующих;
  • выбор класса кнопками;
  • выбор режима УП / Болеет;
  • выбор учеников;
  • Сохранить.

Дата для заявки берется автоматически как текущая (выбор даты убран, чтобы ускорить поток).

2) Устойчивость сценария

Исправлены критичные моменты:

  • нормализация кнопочного текста (NBSP/пробелы);
  • распознавание классов типа 6A и 6А;
  • стабильный ключ состояния пользователя (sender_user_id + chat_id);
  • изоляция состояния между чатами;
  • устранение самопроизвольного возврата в начало после выбора ученика.

3) Сессии СГО закрываются корректно

Добавлен обязательный best-effort logout после операций:

  • загрузка классов;
  • загрузка списка учеников;
  • сохранение посещаемости.

Практическая причина: не оставлять “висящие” сессии в СГО.

4) Failover-логика

Если СГО недоступен:

  • заявка не теряется;
  • уходит в очередь (retry_needed / manual_required);
  • инцидент фиксируется для последующей обработки.

5) Плановые проверки

Через Yandex Cloud Timer Triggers настроены ежедневные вызовы:

  • 12:00;
  • 18:00;
  • 23:00.

Логика:

  • если после 12:00 активных ошибок нет, 18:00 помечается как skipped;
  • если после 18:00 ошибок нет, 23:00 тоже skipped.

Почему выбран Yandex Cloud (а не Google Cloud в этой конфигурации)

На этапе подключения Google Cloud уперлись в ограничения billing-профиля по стране для целевого аккаунта. Для быстрой и предсказуемой доставки выбрали Yandex Cloud:

  • прозрачный путь запуска Serverless Container;
  • простой Container Registry;
  • удобные timer triggers;
  • хороший fit для webhook backend.

Наблюдения по интеграции с MAX

  1. Webhook нужно держать “быстрым” и устойчивым.
  2. Кнопочный UX сильно снижает ошибки ввода по сравнению с free text.
  3. Нужен В начало в каждом ключевом экране.
  4. Нужно логировать каждый шаг сценария, иначе тяжело расследовать “плавающие” кейсы.

Наблюдения по интеграции с СГО

  1. Важна таймаут-стратегия и повторные попытки.
  2. Иногда в roster приходят ученики без корректного ФИО — только ID.
  3. Нельзя полагаться на “идеальный” ответ СГО: очередь и ручной fallback обязательны.
  4. После записи посещаемости желательно закрывать сессию (logout).

Что обязательно сделать перед боевой эксплуатацией

  1. Заменить все тестовые секреты:MAX_BOT_TOKEN;
    MAX_WEBHOOK_SECRET;
    SGO_USERNAME / SGO_PASSWORD.
  2. Добавить длительное хранение очереди/инцидентов (например, Google Sheets или БД).
  3. Добавить алерты на накопление retry_needed.
  4. Зафиксировать регламент ручной обработки инцидентов.

Что можно развить дальше

  1. Роли/права учителей по классам.
  2. История операций в отдельном отчете.
  3. Экран “повторить отправку” по инциденту.
  4. Отдельный режим для Telegram как второго входа в тот же backend.

Вывод

Для школьного процесса “бот посещаемости” важнее не идеальная красота кода, а надежность и предсказуемость:

  • кнопочный UX;
  • облачный backend;
  • failover-очередь;
  • плановые проверки;
  • подробные логи.

Именно эта комбинация делает систему реально рабочей в условиях нестабильного внешнего API.

Репозиторий:

psuren1992-glitch/max-sgo-attendance-bot