Начинается установка так же, как и все остальные: клонированием git-репозитория:
git clone https://github.com/Zverik/bot_na_rayone.git
Следующий шаг тоже традиционен: сделайте окружение virtualenv привычным вам способом. Например:
python3 -m venv venv
pipenv install -r requirements.txt
hatch env na_rayone
И иногда нужно будет запустить pip
из этого окружения:
pip install -r requirements.txt
В конце проверьте, что бот запускается, командой (из-под окружения):
python -m raybot help
На сервер автора бот установлен и управляется через Ansible. Это такая чудесная система программирования состояний сервера на файлах yaml. Вот здесь опубликована роль для бота. Роль легко читается и может служить пошаговой инструкцией для ручной установки.
Обратите внимание на часть про установку свежего Python: в коде использованы датаклассы, введённые в Python 3.7, поэтому версии старее этой не поддерживаются. Это может быть проблемой на Ubuntu 18.04, Debian Stretch и CentOS 8.
Как всегда, новый бот делается через @BotFather.
Пишете там /newbot
и проходите все этапы. В конце получите длинную
строку токена, которую нужно прописать в config/config.yml
в поле
telegram_token
.
Помимо прочего, BotFather командой /setcommands
предлагает подсказать
пользователям, какие команды бот поддерживает. Скопируйте туда вот это:
start - Приветствие и кнопки поиска
help - Справка и статистика
popular - Популярные заведения
random - Несколько случайных заведений
my - Мои отмеченные заведения
msg - Написать модераторам
В первой части мы готовили фоточки. Если вы её пропустили, то сделайте
каталог photo
внутри каталога с ботом. Или где-нибудь в другом месте, но
тогда убедитесь, что бот может туда писать, и пропишите путь в config.yml
в поле photos
.
Если вы хотите, чтобы кроме фоточек, у заведений была мини-карта, и списки заведений тоже приходили с картой, на которой расставлены цифры результатов, то нужны тайлы. Тайлы — это растровые квадратики 256×256 точек, из которых собраны интерактивные карты на многих сайтах, включая OpenStreetMap. Они поделены на уровни масштаба, где квадратик на масштабе N состоит из четырёх квадратиков (2×2) масштаба N+1. Вам нужны тайлы масштабов 15-17, а то и 14, если город слишком большой.
Есть два способа тайлы получить: скачать и сгенерировать. Учитывая небольшой объём данных (около 200 файлов или 3 МБ), оба варианта хороши. Второй требует чуть больше работы, но даёт результат красивее. Важно, чтобы на тайлах не было заведений (POI), но были дороги с их названиями, здания с номерами и побольше местного контекста.
Вот несколько ссылок:
- Скачать выгрузку OpenStreetMap для своего города: BBBike, Interline или OSMaxx из этого списка.
- Стиль OSM Carto включает в себя образ Docker для загрузки файла pbf в базу PostgreSQL.
- Добавив к тому образу Docker для TileMill,
получите редактор стилей на CartoCSS с выгрузкой в тайлы (параметры соединения:
host=db dbname=gis
). - Установив
python3-mapnik
и пару других модулей, можно сделать тайлы из базы PostgreSQL и стиля Mapnik скриптом polytiles. - Можно нарисовать карту в QGIS (или купить основу у NextGIS) и установить модуль Processing. В нём найдите команду "Generate XYZ tiles (Directory)".
Если тайлы в формате MBTiles, то распакуйте
их в набор файлов *.png
. Должны получиться каталоги с числовыми названиями:
15
, 16
и 17
. Создайте каталог tiles
внутри каталога с ботом (или
в другом месте, прописав путь к нему в config.yml
в поле tiles
) и
переместите эти числовые каталоги туда.
Бот ожидает найти несколько файлов в формате yaml в каталоге config
.
config.yml
— мы его делали на протяжении инструкций. Важные ключи для него —telegram_token
иadmin_id
, которые мы заполнили выше. Остальные ключи, кроме путей, задокументированы вconfig.sample.yml
. Пропишите путь к логам вlogs
(должны быть права на запись!) и прямоугольник вокруг вашего района вbbox
. Последний нарисуйте на этом сайте, выберите внизу формат "CSV" и скопируйте числа.responses.yml
— второй по важности файл послеconfig.yml
. Скопируйте его изresponses.sample.yml
и поправьте поля в нём:start
иhelp
: сообщения по командам/start
и/help
соответственно.buttons
: список списков для кнопок под полем ввода. То есть, список строк, каждая строка — список кнопок. Строки на кнопках отправляются в поиск напрямую.synonims
: список синонимов для ключевых слов. Помогает делать кнопки из эмодзи, а не из обычных слов.responses
: здесь можно добавить ответов роботу. Полеname
выводится как заголовок,message
содержит полное длинное сообщение,photo
содержит имя картинки для ответа (должна быть в каталоге с фотографиями),keywords
(единственное обязательное поле) — список ключевых слов, по которым вернётся этот ответ. Важно, что эти ключевые слова затмевают все заведения с такими же словами. Все слова обязательно должны быть в нижнем регистре.skip
: ключевые слова, которые не учитываются в поиске.
addr.yml
— дома, подъезды и номера квартир в них. Этот файл описан в прошлом разделе.tags.yml
— теги OpenStreetMap и дополнительные с описаниями и синонимами. Используется для поиска и для панели тегов в редакторе. Описан в следующем разделе.strings.yml
— строки, которые видит пользователь. Редактировать не нужно, разве что вы заходите перевести на другой язык. Мультиязычность пока не поддерживается.
Обычно бот оперирует поисковой строкой: человек вводит слово или несколько, бот ищет эти слова в своих базах. Поэтому кнопки под полем ввода размещены больше для подсказки: всё, что они вводят, человек может ввести самостоятельно.
Альтернативный подход для районного бота — курируемый каталог заведений. Он работает, когда заведений меньше сотни, или когда мы хотим не только поиск, но и продвижение. Каталог также облегчает обнаружение новых заведений: когда ничего не ищешь, всё равно можно занять время нажиманием на кнопочки.
Механизм предопределённых ответов позволяет сделать подобную систему вложенных
списков. Помимо ключей для построения ответа (name
, message
, photo
),
в элемент списка responses
можно добавить ключ buttons
, формат содержимого
которого ровно тот же, что у общего buttons
: список списков строк для вывода
на кнопках. Некоторые из этих строк могут входить в списки keywords
других
предопределённых ответов. Если поля buttons
нет, то выводятся общие кнопки.
Помните, что ключевые слова для responses
приоритетнее ключевых слов для
тегов и заведений. То есть, не используйте стандартные слова вроде «еда»
или «школа». Лучше всего воспользоваться особенностью ключевых слов в responses
:
они могут содержать пробелы, которые сохраняются при проверке. То есть,
«🛒 Магазины» будет проверено целиком, а не разобьётся на два слова, эмодзи
и «магазины».
Небольшой пример вложенных кнопок:
responses:
- name: Что ищете?
keywords: [⬅️ начало]
- name: Какие магазины?
keywords: [🛒 магазины]
buttons:
- [⬅️ начало, продукты, веганам, алкоголь]
- [одежда, обувь, сумки, цветы]
- name: Какие заведения?
keywords: [🍽️ еда]
buttons:
- [⬅️ начало, кафе, фастфуд, кофейни]
buttons:
- [🛒 Магазины, 🍽️ Еда, ✉️ Почта]
Запустить бота просто: из-под виртуального окружения выполните такое:
python -m raybot
Появится строчка про start polling, и можно открыть телеграм и нажать «Start». В самом начале база будет пустая и никакие запросы не сработают — смотрите ниже, как её заполнить.
У библиотеки aiogram есть странный баг: на некоторых операционных системах второй ответ может занять до двух минут. В проде этого у меня не случалось.
Сначала база пустая, но она не должна быть такой. На прошлом этапе вы нарисовали на карте, как минимум, все дома в районе, и получили файл GeoJSON. Теперь давайте зальём его в базу.
Отправьте боту команду /admin
. Затем нажмите «База заведений», и там «Прислать файл».
Теперь пришлите боту файл GeoJSON. Если всё будет хорошо, заведения появятся
в базе. После этого можно отправить боту команды или ключевые слова.
Если обходили дома и подъезды, то попробуйте ввести улицы и числа.
При загрузке вы можете получить одну из двух ошибок: "Duplicate id" требует проверить
идентификаторы на дубликаты, а "POI references missing key" обратит внимание
на теги house
, которые должны ссылаться на существующие id
.
На сервер бота лучше ставить не для запуска из командной строки
(это довольно странно для сервера), а как сервис systemd. Это несложно:
сделайте файл /etc/systemd/system/nav_bot.service
с
таким содержимым.
Поправьте в нём User
, Ground
, WorkingDirectory
и ExecStart
.
Дальше — как обычно:
sudo systemd start nav_bot
sudo systemd enable nav_bot
Чтобы посмотреть логи, сделайте sudo journalctl -u nav_bot
. Остальные
три лога будут либо в каталоге бота, либо в каталоге, который вы
прописали в ключе logs
в config.yml
.
Теперь у вас запущен бот и настроены его ответы. Но база заведений пуста. Как её заполнить, читайте в третьей части.