Skip to content

MishaVoyager/cashbox-zoo

Repository files navigation

В Контур.Маркете огромное количество кассовой техники. Когда ее забирают домой, то нигде не отмечаются. Поэтоу порой непонятно, где находится нужный тебе терминал эквайринга или ККТ. Приходится писать в чатики и объявлять технику в розыск. Бот создан для того, чтобы записывать технику на себя было легко и удобно - и чтобы у всех была актуальная инфа о том, где техника.

Основные команды

Доступные команды выводятся при первом запуске бота (/start) и при вызове команды /help.

  • /all - выводит весь список устройств с пагинацией
  • /categories - список устройств в конкретной категории
  • /mine - устройства, которые пользователь записал на себя
  • /wishlist - устройства, за которыми пользователь стоит в очереди (когда очередь придет, в чате появится сообщение об этом)

Возможности админа

В переменной среды прописаны администраторы бота. Администраторам доступны те же команды + ряд специальных возможностей.

  • /add - команда для добавления устройств (по одному или файлом csv)
  • /users - для поиска по пользователям (также можно изменить почту пользователя, если он ввел неправильную; оставить про пользователя комментарий; удалить пользователя)
  • При поиске устройств доступна команда /edit, которая позволяет отредактировать информацию об устройстве, записать его на пользователя и списать с пользователя, а также удалить устройство

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

На самом деле, есть еще скрытая роль разработчика - есть особые команды для получения логов из файлов, массового удаления устройств, дропа БД, скачивания устройств в виде файла, скачивания всех важных объектов со всеми полями. Для подтверждения подобных действий требуется код, который прописан в переменных среды и доступен только обладателям определенных прав в проекте на гитлабе.

Напоминания о сдаче устройств

При записи устройства на пользователя есть возможность указать дату возврата. В этом случае бот напомнит за день, что скоро пора возвращать технику обратно. А также будет напоминать в последующие дни.

Как бот задеплоен

Для пользователей бот запущен в контуровском кубернетес, куда деплоится при помощи гитлаба (.gitlab-ci.yml в корне репозитория) и хельма (values.yaml в папке deploy).

Для простоты бот использует polling. Потому что для вебкуха нужно открывать доступ вовне, а значит, проходить безопасности и подкручивать кубернетес - в нашем случае особого смысла в этом нет.

Как тестировать

Локально бота удобно запускать через docker compose (чтобы поднимать сразу самого бота, Postgres, Redis и воркера). В корне проекта есть конфиг compose.yaml.

Для этого вам нужно:

  • Сходить в телеграме в бота BotFather, создать своего тестового бота и сохранить токен.
  • Создать в src папку secrets и засунуть в нее файлы со всеми секретными переменными, которые нужны для запуска контейнеров (посмотрите в compose.yaml). Например, файл token.txt, в котором содержимое - только токен.
  • Поставить докер, если его нет (в т.ч. доступен на Windows и Mac)
  • Запустить командой docker compose up --build

Технологии

Для взаимодействия с Postgres:

  • Asyncpg - драйвер для асинхронного подключения к Postgres.
  • SQLAlchemy - в качестве ORM (тоже, естественно, в асинхронном режиме). Эта штука соединяет мир наших классов и мир таблиц в базе данных. Т.е. мы описываем модели понятным нам спообом, с подсветкой синтаксиса - и эти модели используются для создания таблиц, просмотра, изменения и удаления данных. В нашем случае основные модели - Resource, Visitor, Record, Category, Action. У них есть primary и foreign keys, они связаны между собой при помощи relations, связанные поля автоматически обновляются, некоторые поля автоматически заполняются (created_at, updated_at) - все это делать с алхимией очень удобно.
  • Alembic - для миграций. Алембик создан теми же людьми, что и SQLAlchemy, и работает как надстройка над первой библиотекой. Когда наше состояние моделей уходит вперед от состояния БД - мы можем одной командой сгенерировать миграцию. В большинстве случаев это будет корректная миграция, которая позволяет делать апгрейд и даунгрейд. В нашем случае апгрейд происходит прямо при запуске контейнера (хотя бывают разные подходы, и это дискуссионная тема). При желании или для тестирования локальной базы - можно откатывать и накатывать миграции вручную.

Для взаимодействия с телеграмом используется aiogram. В частности такие фичи:

  • Хэндлеры. Для старта с aiogram достаточно навесить на функцию с параметром message: Message декоратор, например @router.message(Command("wishlist")). Создать сам этот router, засунуть его в dispatcher, указать параметры запуска бота - и запустить. И за счет асинхронности сразу будет возможность за небольшое количество ресурсов обработать много запросов.
  • FSM. Когда пользователь заходит в сценарий - мы сохраняем его состояние. Поэтому можем провести его по нужному маршруту - например, по добавлению нового устройства (ввод 9 полей с валидацией и соответствующими подсказками). А если он будет вводить какую-то неожиданную фигню - не перейдем в следующий стейт, а переспросим его. По дефолту стейты хранятся в памяти, а в нашем проекте - в редисе (чтобы состояние не терялось при перезапуске бота). В проекте переиспользуются типичные переходы между стейтами - в модуле fsmhelper.
  • Клавиатуры. ReplyKeyboard - используется для выбора нужного варианта и заменяет сообщение от пользователя. InlineKeyboard - для просмотра результатов, например, для выбора страницы в выводе. Кстати, пагинации из коробки нет, она реализована самостоятельно + написано большое количество тестов.

Подробности смотрите в документации aiogram. А еще есть прикольный гайд.

Для запуска бота на сервере в режиме вебхука - используется aiohttp (ну точнее использовался - сейчас, как упомянуто выше, бот запускается в режиме поллинга). Как вы понимаете, все эти библиотеки неплохо между собой дружат: asyncio, aiohttp, aiogram - поэтому многие вещи работают из коробки легко и гладко.

Также в проекте есть:

  • pydantic-settings - чтобы собирать разрозненные переменные среды в удобные конфиги. Нужные значения подтягиваются в конфиг из переменных среды и файлов с секретами - и сразу валидируются привычными средствами pydantic. Если переменных не хватает или они указаны неправильно, приложение сразу выбросит ошибку - а не тогда, когда мы попытаемся эти переменные использовать. В этом проекте переменных среды реально много, поэтому если бы этой библиотеки не было, ее надо бы было придумать.
  • charset_normalizer - майкрософт очень коварный, поэтому мы заранее не знаем, в какой кодировке придет файл .csv с устройствами. Пришлось заюзать эту библиотеку и вставить костыль, потому что она плохо определяет cp1251 (считает маковской кодировкой).
  • arq - для запуска воркера, который отправляет напоминания о необходимости сдать устройство. Сейчас используется не на всю мощь: есть возможность в зависимости от событий класть вызов функций в редис - и чтоб воркер доставал их из редиса и исполнял.
  • redis - для хранения стейтов и результатов работы воркера.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages