Aiogram @Travel Agent Bot
Бот, облегчающий планирование путешествий с друзьями. Он может помочь: не потерять важные документы, построить маршрут, найти новых друзей, поделить расходы, увидеть достопримечательности и узнать прогноз погоды на протяжении маршрута.
Бот построен на основе асинхронной библиотеки Aiogram для создания Telegram ботов на языке Python. При его создании был сделан упор на хорошую производительность, поэтому все операции с внешними сервисами (PostgreSQL, Redis, различные API) и файловой системой выполняются асинхронно, а все синхронные операции, которые могут быть выполнены только локально, например: отрисовка маршрута на карте и сохранение в формате фото, выполняются в отдельном потоке.
-
Обязательные функциональные возможности
-
👤 Добавление данных пользователя
-
🌍 Управлением путешествием
-
📓 Заметки к путешествию
-
👥 Путешествия с друзьями
-
🚗 Прокладывание маршрута путешествия
-
-
Опциональные функциональные возможности
-
⛅ Прогноз погоды в промежуточных точках
-
🏰 Рекомендация местных достопримечательностей
-
👥 Поиск пользователей для совместного путешествия
-
💸 Общие траты в путешествии
-
💡 Ваши собственные идеи (Конвертер валют; Возврат долга в выбранной валюте; Случайный выбор участника путешествия, который платит за всех)
-
- 🐋 Docker
docker-compose.yml содержит в себе:
- 📁 Тома
volumes:
files: # том с фотографиями маршрутов и файлами пользователей
pg_data: # том PostgreSQL
redis_data: # том Redis
-
📡 Сервисы
-
Бот
bot: # сборка на основе Dockerfile build: . # перезагрузка в случае ошибки restart: always # применение миграций и запуск бота command: bash -c "alembic upgrade head && python bot.py" # открытие портов ports: - 8080:8080 # использование файла для установки переменных окружения env_file: - .env # том с файлами volumes: - files:/files # ожидание запуска необходимых для работы контейнеров depends_on: - postgres - redis # установка имени контейнера container_name: travel_bot
-
PostgreSQL
postgres: # сборка на основе легковесного alpine образа image: postgres:alpine # перезагрузка в случае ошибки restart: always # использование файла для установки переменных окружения env_file: - .env # том с данными volumes: - pg_data:/var/lib/postgresql/data/ # установка имени контейнера container_name: postgres_bot
-
Redis
redis: # сборка на основе легковесного alpine образа image: redis:alpine # перезагрузка в случае ошибки restart: always # запуск Redis command: - redis-server # использование файла для установки переменных окружения env_file: - .env # том с данными volumes: - redis_data:/data # установка имени контейнера container_name: redis_bot
-
-
🛠️ Начало работы
- Создайте Telegram бота с помощью @BotFather и получите токен
- Зарегистрируйтесь в Openrouteservice и получите токен
- Зарегистрируйтесь в Geoapify и получите токен
- Создайте
.env
файл с использованием шаблонаexamples/.env.example
-
🚀 Запуск бота
docker compose up --build -d
-
❌ Остановка
docker compose stop
-
PostgreSQL — надежная SQL СУБД с отличной производительностью и масштабируемостью. Все эти качества делают ее отличным выбором для высоконагруженных проектов. В боте используется в качестве основной БД. Также в проекте используется Alembic — удобный инструмент для проведения операций с миграциями и контроля их версий. В БД содержатся следующие таблицы:
- alembic_version (служебная таблица)
version_num pk, character varying(32), not null - users
id username age sex latitude longitude city country currency bio pk, bigint, not null character varying, not null integer, not null character varying, not null double precision double precision character varying character varying, not null character varying, not null character varying - trips
id username name description locations friends pk, integer, not null fk (users.username), character varying, not null character varying, not null character varying json[] character varying[] - notes
id user_id trip_id name path file_type width height is_private pk, integer, not null fk (users.id), bigint, not null fk (trips.id), integer, not null character varying, not null character varying, not null character varying, not null integer integer boolean - expenses
id username trip_id name cost currency date debtors pk, integer, not null fk (users.username), character varying, not null fk (trips.id), integer, not null character varying, not null double precision character varying, not null timestamp without time zone, default now() character varying[] -
Redis — масштабируемая NoSQL СУБД с потрясающей производительностью, которая хранит данные в виде пар «ключ — значение» прямо в оперативной памяти сервера, что и позволяет их быстро получать. В моем проекте используется для сохранения состояний пользователей и их промежуточных данных, кэширования.
Note
Интересный факт: до настройки кэширования с использованием Redis среднее время ответа бота составляло около 300-350 мс, после настройки оно снизилось до 200-250 мс. Кэширование данных пользователя, а также результатов запросов к внешним сервсиам сделало бота более отзывчивым.
-
OpenStreetMap — открытая карта мира, которую могут редактировать обычные люди. В моем проекте используется для обратного геокодирования (получения города и страны из координат).
-
Openrouteservice — сервис для произведения различных действий с картой OpenStreetMap. В проекте используется для получения маршрута путешествия, он поддерживает построение маршрута на расстояния до 6 тыс. км, что является его огромным плюсом.
-
Geoapify — тоже сервис для произведения различных действий с картой OpenStreetMap. В проекте используется для нахождения достопримечательностей рядом, был выбран за удобство использования.
-
Open-Meteo — сервис для получения прогнозов погоды с учетом множества параметров запроса. Для проекта был выбран именно он, ведь данный сервис позволяет получить погоду на целых 16 дней вперед, чего не могут вам предложить другие сервисы.
-
Calcus.ru — сервис, предоставляющий огромный набор различных калькуляторов и инструментов. В проекте используется для конвертации валют.
Warning
Перед началом необходимо убедиться, что у вас в Telegram профиле указано имя пользователя в формате @example
-
По нажатию на кнопку
/start
начинается процедура регистрации пользователя -
У бота есть боковое меню, которое содержит команды
/menu
,/profile
,/help
, они являются основными для взаимодействия с ботом -
/profile
позволяет просмотреть ваш профиль и, по желанию, отредактировать его -
/menu
бота позволяет просмотреть путешествия как созданные вами, так и те, в которые вас пригласили, они будут со значком 🔗; создать новое путешествие; конвертировать валюту, которую вы указали в профиле -
В процессе создания нового путешествия вы указываете только одну локацию и даты, после создания путешествия вы сможете расширить список локаций
Important
Редактировать/удалять путешествия могут только их организаторы
- В разделе
Друзья
можно пригласить своих друзей, либо найти новых друзей с учетом возраста и интересов
Important
Добавлять/находить друзей для путешествия/удалять могут только организаторы путешествия
Note
Поиск по интересам производится на основе полей О себе
путем их сравнения и определения коэффициента подобия
- В разделе
Заметки
можно создать свою заметку, которая будет прикреплена к данному путешествию. Можно просматривать не только свои заметки, но и открытые чужие, они будут со значком 🔗
Important
Удалять заметки могут только их создатели
- В разделе
Локации
можно создать просмотреть все локации путешествию, построить маршрут или добавить новую локацию
Important
Добавлять/удалять локации может только организатор путешествия
Note
Первоначальная отрисовка карты с маршрутом может занимать некоторое время, после чего она будет сохранена на диск и будет загружаться оттуда. После обновления списка локаций старая карта удаляется
- В разделе
Траты
можно просмотреть, кому ты должен (со значком ❗)/кто тебе; можно записать новые траты и указать всех должников
Important
Редактировать/использовать команду с игрой/удалять траты могут только их создатели
Note
Бот разделит общую сумму траты поровну на всех участников с учетом валют, указанных в их профилях. Также траты сами удаляются, когда последний должник выплачивает свою часть
Caution
Использование далее описанных инструкций может сильно ударить по вашему кошельку! В выбранной трате можно сыграть в мини игру: случайным образом выбирается человек, который связан с этой тратой, это может быть как один из должников, так и тот, кто за всех заплатил, на него будут списаны все долги