Привет! Хочу поделиться историей, как я писал telegram-бот на Python. Хоть это и супер банально, но решил сделать бот-витрину с возможностью просмотра товаров, добавления в корзину и подтверждением заказа.
Предисловие
Я не являюсь профессиональным разработчиком, и никогда не писал большие продакшн проекты хоть уже 6 лет работаю в IT. Я - тестировщик. Тестирую руками, пишу автотесты на C#, но при этом делаю домашние проекты.
Я три раза начинал реализовывать бот на C# но каждый раз погрязал в рутине, где нужно было создать 20 моделей, написать конвертеры, адаптеры, запись в базу и на самое веселое - написание логики, уже не хватало сил.
Первая версия
Все поменялось, когда я решил выучить Python. Бегло прочитал документацию, написал десяток строк кода в REPL и понял, что пора делать реальный проект.
Нашел в google несколько библиотек по работе с telegram bot api и остановился на python-telegram-bot. Она оказалась простой и понятной. Делаешь фильтр по сообщениям и передаешь callback метод, который будет вызван в случае совпадения фильтра. Внутри метода пишешь обработку сообщения, запись в базу, отвечаешь в чат.
Так как я не знал как принято писать на Python, создавать модели или использовать dict, писать отдельные функции или методы в классах, то просто начал делать. Быстро и просто. Через неделю первая версия бота была готова.
Что получилось? Для хранения данных использовал mongodb. Ну потому, что стильно, модно, молодежно. Клиент к базе определил как будут храниться данные. Так как в mongo было легко писать dict, то я передавал данные в словаре. Отдельно писал функции для обработки этих данных. Никаких классов и объектов.
Запаковал проект в докер контейнер и запустил на digital ocean.
Вторая версия
Первая версия получилась рабочая, но у нее было много минусов. Добавление данных в базу осуществлялось через Robo 3T клиент, что не очень то удобно. Агрегация данных с разных коллекций в no sql базе тоже доставляла хлопот. Ну и в конечном итоге сложновато оказалось работать со словарями, каждое переименования поля или изменение типа вываливалось ошибкой в рантайме.
Я понимал, что хочу чтобы была админка для бота. Подумал, что можно написать ее на django. На GitHub лежит такой проект RealWorld example app, где можно посмотреть как пишут реальное проекты на популярных технологиях. Посмотрел код там, почитал try a tutorial по django и понял, что админку не нужно писать. В django есть возможность подключать уже существующие модули к проекту, которые называются APP. Один из таких app называется django.contrib.admin
как раз и есть админ панель, которую можно подправить под свои нужды.
Плюсы использования django заключались в том, что я мог использовать один и тот же код для бота и для админки. В этом случае я решил поменять базу на реляционную и начал с самого простого - sqlite. Django models поддерживает ее из коробки и мне почти не пришлось писать дополнительного кода. Просто создал модели с нужными полями и задал отношения между ними.
Читайте также: Как создать бота в Telegram: большая инструкция
И на этом этапе все было здорово, кроме одной вещи: Django - это веб фреймворк и рассчитан на то, что пользователь делает http запрос, и синхронно получает сгенерированный ответ. А часть проекта с ботом работает не так. В ней должен запуститься python процесс и постоянно слушать обновления от telegram.
Ответ на вопрос как это сделать, я получил в чате Hexlet в #python. Как подсказал Aleksei Pirogov в django есть понятие management commands. Это такие же команды как makemigrations python manage.py makemigrations
или python manage.py createsuperuser
только ваши собственные. Они могут работать вечно, запускаются командой python manage.py
и не стартуют веб сервер, хотя при этом могут использовать те же модели и конфигурации что и основное веб приложение. Главное - разместить команду в правильной директории и добавить app в INSTALLED_APPS.
Развертывание
В конечном итоге получился один django проект с несколькими apps внутри. App с ботом запускается с помощью команды python manage.py startbot
, а админ панель с помощью python manage.py runserver 0.0.0.0:8000
. Все это пакуется в один docker контейнер, но а в docker-compose запускаю их как два отдельных сервиса с разными командами. Сервисы делят одну базу на двоих так как это sqlite файл, который добавляется как volumes к сервису.
Надеюсь вам было полезно и познавательно. Для себя же я открыл python и django как инструмент для быстрой реализации идей, без заморочек и лишнего кода.
Если вам интересно следить за дальнейшим развитием этого проекта, то в telegram канале я публикую маленькие заметки по этой теме.