Как писать бота

Материал из wiki-MyMakerBot

Что такое бот, как его понять изнутри

Если описать внутреннее представление бота в двух словах, то бот (в рамках этого конструктора) это совокупность именованных страниц с текстом и кнопками. Текст и кнопки на экране вашего клиента - это результат выполнения какой либо команды. Имя блока текста совпадает с менем команды для простоты восприятия.

Если оглядываться на разные библиотеки, которые используют программисты, то подходы к написанию бота будут разными. Наиболее часто используется функциональный подход, когда мы пишем функцию команды и к ней функцию обработчика. Но этот подход надо попытаться понять и в двух словах мне будет сложно объяснить что это. Мы не будем использовать это представление бота.

Так давайте попытаемся понять - что такое бот. Посмотрим ссылку на любой сайт. После имени сайта вы видите несколько, зачастую английских слов, разделенных символом / (слеш), например, https://www.reg.ru/support в данном случае запись /support - это ничто иное, как страница которую сайт вам должен показать. Не кажется ли вам, что это и есть команды ботам, которые мы используем в телеграме? Так вот бота можно представить как сайт. И когда вы пишете бота, то представьте, что вы пишете сайт. А что такое сайт - это совокупность отдельных страничек с ссылками-переходами. Адрес ссылки вы также прописываете на сайте как /help /support и т.д. Так вот в боте мы то же будем придерживаться этой системы - страницы с именем. Именем страницы и будет наша команда. Например, первая же страница любого бота это /start - совпадает с именем команды?


Пишем бота

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

Второй момент. По умолчанию интерфейс с такими инлайн кнопками рассчитан на то, что у нас каждый раз меняется сообщение, меняется текст и новый состав кнопок. А значит нам надо в каждом экране (сообщении, блоке - можно по разному называть) надо ВСЕГДА предусматривать кнопки для возврата назад или перехода куда-нить дальше.

В ботах у которых есть и инлайн кнопки и кнопки внизу сообщения, я очень часто видел сатуацию, когда серия диалогов заканчивалась и дальше мы нажимаем инлайн кнопку, а ничего не происходит. Нам нужно после этого нажать кнопку под сообщением для запуска новой цепочки диалога. А по сути получается, что программисты просто бросили ветку и не написали обработчик на законченном диалоге. С одной стороны правильно - пользователю больше нечего ответить, а с другой стороны выглядит как откровенный баг в боте. Ибо кнопка если есть, значит она должна что-то делать и точка.

Интерфейс данного конструктора лишен такого недостатка. Каждая кнопка у вас будет запускать команду (вида /команда), т.е. являтся ссылкой на какой-то существующий (вами написанный) блок. А из него дальше и дальше. Как вы построите карту переходов зависит только от вашей фантазии.


Подготовка ТЗ

Чтоб не путаться во время написания своего бота, настоятельно рекомендую взять листок бумаги и написать ТЗ

ТЗ - это некое волшебное слово, которое вам поможет значительно быстрее сделать своего бота.

ТЗ - это техническое задание. Нарисуйте диаграмму бота со стрелками. В каждом блоке вы пишете, какой текст будет выводиться. Стрелками вы соединяете свои блоки и вверху каждого блока вы пишете имя самого блока. Все имена блоков на английском языке без пробелов. Например, имена могут быть help support menu backlog и т.д.

После вы соединяете стрелками блоки - это будут ваши переходы. Предположим стрелка идет в блок help, значит на самой стрелке подпишите help. оно вам поможет при формировании кнопок. Позже вы будете просто смотреть в какой блок приходит стрелка - так она и будет именоваться и, забегая вперед, скажу, что именно это имя и будет вписано в команду на кнопке. Как только вы построили диаграмму - вы сделали 50% работы. Вам остается только перенабрать тексты в бота.

Что такое контроллеры и экшены

В предыдущей главе мы рисовали ТЗ. Но тз может быть на столько большим, что вам не хватило листика и вы потянулись за другим. А теперь внимание! Возьмите и напишите в уголке предыдущего листика английское имя - какие блоки на этом листике, например это catalog,

далее вы берете второй листик и сразу подписывайте в углу, например, это будут экраны с вашими реквизитами, формой оплаты и отправки сообщения вам о том, что клиент оплатил. Вы подписали этот листик pay.

Таким образом вы разбили ваше тз на некое количество законченных блоков. Но Не забывайте о том, что вы можете рисовать стрелки, как угодно и куда угодно и не обязательно стрелки будут внутри одного листика. Они могут и будут вести и на другие листики. Так вот на выручку как раз и приходят подписи на самих стрелках.

А теперь плано переходим от наших листиков в конструктор. Те имена которые вы подписали над самим блоком - это экшены. А те имена которыми озаглавили сам лист - это контроллер. К примеру у вас лист озаглавлен support, а на листе есть блоки show, about и т.д Нам надо как-то именовать функции. Мы смело можем написать так support__show (разделено двумя знаками подчеркивания). Так вот это и будет ваше полное имя функции.

Чтоб легче понять представьте, что у вас семья - и в семье Вася, Петя. И фамилия у все семьи Ивановы. Полное имя у каждого будет иванов__вася и иванов__петя. И есть другая семья - там тоже есть петя и слава и фамилия у них петровы. Их полные именя будут петров__петя и петров__слава

Вот мы и подошли к тому, что контроллер - это просто визуальное представление, которое помогает разделить большой проект на законченные логические группы. Основной контроллер в боте у нас всегда есть - я его сразу обозвал main И в данном контроллере присутствует наша команда старт (start) Полное имя команды будет выглядеть как /main__start Так же для команд контроллера main можно не писать main, а просто писать /start (Но это только для контроллера main и только!) если у вас в контроллере main будет еще одна команда help - то ее имя будет /help и /main__help Бот будет одинаково выполнять и то и то. Для других контроллеров всегда надо писать имя /контроллер__экшн

Вот именно так выглядят ВСЕ команды нашего бота - сколько бы их ни было.

Давайте на практике попробуем бота с самой простейшей навигацией

1. Созадаеде бота в @BotFather, регистрируйте токен в боте. После добавления токена ваш бот стартует в системе. Если вы не хотите, чтоб пользователи тыкали кнопки в боте - остановите. Тогда бот будет работать только для вас. Остальным будет выдавать информацию о техническом обслуживании

2. Перейдите в конструктор ботов и в экшене напишите какое-нибудь приветствие. Напишите сообщение своему боту /start - по сути выполните команду. Вы увидите свое сообщение. Поздравляю - ваш первый простой бот, который может приветствовать с порога и выдавать пользователю на команду start любой текст.

3. Создайте второй экшн и назовите его help. Впишите туда так же любой текст и сохраните. В боте выполните команду /help Вы получите текст помощи, который только что написали. Вы получили вторую команду. Таких команд вы можете делать сколько угодно.

Так сделано большинство старых ботов без особой навигации. Вы стартуете бота и получаете список команд, выполнив которые вы получите тот или иной текст в ответ. И как правило всегда делают команду /help, которая возвращает справку по командам бота. Таким образом вы уже можете создать бота визитку со своими текстами и командами /start /help /contacts ...


Теперь наш бот растет. У нас очень много текстов. Делаем бота каталог чего-нибудь.

Итак, у нас растет количество текстов. Для каждой товарной позиции мы будем делать новый экшн и туда заполнять карточку товара. И у нас слева в редакторе выделено main и количество экшенов катастрофически растет. При том у нас еще и товары разделены на группы - например, часы, конфеты, футболки, куртки. А в каждой группе десятка два-три товаров. Вот для такой ситуации и придуман контроллер - для логического деления на группы.

Создаем новый контроллер watch и внем создаем экшн например brand1 и в этот экшн вписываем описание товара. Как вызвать эту карточку в боте? Пишем /watch__brand1 - у нас карточка. Теперь карточки разделены по группам и мы быстро можем найти нужный нам товар и поправить.

Примерный текст в команде start Наш каталог товаров: /watch - часы /candies - конфеты


вопрос - почему /watch а не /watch__show? Можно и так и так. Бот поймет обе записи. В других контроллерах, кроме main, автоматом вам создается волшебный метод show. Он служит для того, чтоб к нему обращались по краткой команде - /ИмяКонтроллера (просто так эстетически удобно).

Примерный текст в команде /watch (контроллер watch экшн show)

Наш каталог часов: /watch__brabd1 - часы от марсиан /watch__brabd2 - часы от плутонианцев /watch__brabd3 - часы от землян /start - вернуться в общий каталог


Остальные имена экшенов мы пишем полными. Так же по образу и подобию мы можем заполнить контроллер candies.

В итоге мы создали каталог товаров с навигацией просто на слеш-командах. Это наш первый бот. И до введения инлайн кнопок именно такие каталоги и делались. Да и сейчас зачастую встречаются, т.к. это очень просто и быстро реализуется. В итоге в конструкторе ботов мы еще не написали ни одной строчки кода. По сути редактор кода, но мы работаем со стандартным человеческим текстом.


Мы наводим красоту

Казалось бы бот готов, все есть, переходы есть, все показывает. Но можно сделать красивее У нас команды перехода заданы как /watch /candies /watch__brabd1 - просто командами в тексте. Но можно перевести данные команды в кнопки и расположить их снизу под сообщением. Такие кнопки называют инлайн-кнопками

Давайте в тексте заменим запись Наш каталог товаров: /watch - часы /candies - конфеты на Наш каталог товаров: {key l=1 t='часы' c='/watch'} {key l=2 t='конфеты' c='/candies'}

И мы получаем внизу кнопки.

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

Интересный параметр l - это по сути условный номер строки на которой будет распологаться кнопка. Если мы запишем текст так. Наш каталог товаров: {key l=1 t='часы' c='/watch'} {key l=1 t='конфеты' c='/candies'} То две кнопки будут располагаться на одной строке. Ставя разные параметры можно располагать несколько кнопок в одной строке, потом сколько-то кнопок в другой строке. Максимально в строке можно разместить только 8 кнопок. Но учитывайте, что они буду сжаты по горизонтали. Поэтому оптимально располагать по 1-2-3 текстовых кнопки или 4-5 с очень коротким текстом.

Вот мы и подошли к первой функции которую можно вызвать в тексте бота. key - имя функции, l - номер строки, t - текст на кнопке c - текст команды. В основном весь ваш бот будет состоять из вызова подобных команд, которые что-то делают и что-то возвращают. А бот это некоторое количество страниц, каждая вызванная по команде что-то делает и в финале выдает как результат текст с кнопками. Результат любой страницы - это текст с кнопками. А кнопки - это выход какой-нибудь следующей команды.