Доброго времени суток, Habr'овчане.

В поисках различной информации по разработке бота для чата Telegram в сети Интернет обнаружил, что все tutorial'ы хоть и достаточно полны различными механиками взаимодействия с библиотекой «telegram-bot-api», никто не пришёл к умозаключению, что жизнь товарищей всегда нужно улучшать в сторону облегчения труда (программисты — люди по натуре своей ленивые), потому решил написать собственный tutorial с применением собственной библиотеки-обёртки, которая умеет на данный момент только читать сообщения и отправлять на них ответ, но обо всём по порядку.

Почему чатботы нужны?



Тема разработки чатботов в наше время для различных социальных сетей вопрос достаточно чувствительный, поскольку внедрение чатбота:

  1. Уменьшает время ответа пользователю на интересующий его вопрос (и в ваших же интересах скорейший контакт с ним)
  2. Уменьшает нагрузку на кошелёк компании N для содержания работника, обрабатывающего заявки вручную

Внедрение чатбота отнюдь не означает, что человек не нужен вовсе, поскольку всегда существуют определённые ситуации, требующие участия ответственного за решение того или иного вопроса человека, но упрощает и автоматизирует вопрос решения бытовых вопросов, обработки заявок, а также доставки информации до ответственных лиц, ведение статистики и прочего, чего душе захочется.

Поскольку внедрение виртуальных помощников происходит не столь активно, а мы уже понемногу входим во 2 десятилетие 21 века, считаю необходимым снизить порог вхождения в данную тему.

Приступим.

Attention

Проект с применением реализованной библиотеки-обёртки использует не webhook, но long pooling, поскольку не имеет цели развёртывание на таких специфичных сервисах, как heroku (однако, имеет базовый функционал для того, чтобы проект жил более-менее долго и не засыпал по первому звонку распределяющего время работы различных сервисов других пользователей heroku). Основной идеей проекта было максимальное упрощение разработки и сокращение количества «телодвижений» при разработке чатбота с базовым функционалом — обработкой входящих пользовательских запросов.

Как это работает в данной библиотеке?




Основным источником данных является словарь, на котором чатбот и основывается (содержится в файле JSON формата), но также подразумевается и обработка пользовательских сообщений путём написания собственной программной логики.

Для начала необходимо создать бота у BotFather (будем считать далее, что бота вы создали и получили токен). Теперь необходимо «забрать» библиотеку к себе путём исполнения команды
go get "github.com/liquiddeath13/reactivetgbot".

Далее необходимо создать файл формата .go и поместить туда следующий код:

package main

import (
	reactivetgbot "github.com/liquiddeath13/reactivetgbot"
)

func main() {
    BotInstance := reactivetgbot.Init("YOUR_BOT_TOKEN", "PATH_TO_JSON_DICTIONARY")
    if BotInstance != nil {
        go BotInstance.Logic()
        //if we need host our application on Heroku and shouldn't think about uptime
        reactivetgbot.HerokuServiceUP("Telegram ChatBot by liquiddeath13")
    }
}

Переменная BotInstance содержит в себе ссылку на экземпляр чатбота с указанными токеном и путём до словаря, хранящего в себе вопросы и ответы.

Пример словаря:

[
    {
        "Question" : "/about",
        "Answer" : "ChatBot created by liquiddeath13 in 2019 year"
    },
    {
        "Question" : "Hello, how can i contact with your company?",
        "Answer" : "Hello, you can contact us by provided mail address. Email: coolnickname@hostname.domain"
    }
]

Далее чатбот начинает работу с API Telegram'а и забирает оттуда информацию о событиях, происходящих в чатах, где он состоит. Если сообщение, описанное в словаре в поле Question, поступает в адрес бота, то он ответит на сообщение тем ответов, который сопоставлен в пару в поле Answer, (т.е. на сообщение «Hello, how can i contact with your company?» в данном примере бот ответит «Hello, you can contact us by provided mail address. Email: coolnickname@hostname.domain»).

Также, как уже было сказано ранее, продвинутые товарищи могут определить поведение бота при получении какого-либо сообщения путём добавления обработчика, пример:

package main

import (
	"fmt"
	reactivetgbot "github.com/liquiddeath13/reactivetgbot"
)

func main() {
	BotInstance := reactivetgbot.Init("YOUR_BOT_TOKEN", "PATH_TO_JSON_DICTIONARY")
	AskCounter := 0
	if BotInstance != nil {
		BotInstance.AppendHandler("how much time people asked you?", func(Msg reactivetgbot.TGMessage) string {
			AskCounter++
			return fmt.Sprintf("Hello.\n%d - so many time people asked me", AskCounter)
		})
		go BotInstance.Logic()
		reactivetgbot.HerokuServiceUP("Telegram ChatBot by liquiddeath13")
	}
}

В данном примере описан механизм обработки вопроса «how much time people asked you?». В качестве ответа бот выдаст пользователю значение которое показывает, сколько раз пользователи задали указанный вопрос, предварительно увеличив счётчик.

Deployment на Heroku (не реклама)


Чатботы по некоторым причинам плохо чувствуют себя на сервисах, подобных heroku, потому был написан небольшой функционал для предотвращения раннего «засыпания» сервиса, а именно эмулирование сетевой активности (обращение к веб-ресурсу раз в пять минут)
Для размещения проекта на Heroku нам понадобится утилита godep, которая «упакует» зависимости в проект. «Забрать» её можно командой go get github.com/tools/godep, упаковать зависимости можно путём выполнения команды godep save в папке проекта.

Далее нам необходимо создать аккаунт на Heroku и ознакомиться с официальным гайдом по развёртыванию. Если времени на почитать особо нет или хочется «всего и сразу в одном месте», то всё сводится к следующему ряду команд:

  1. Авторизация на ресурсе Heroku с помощью их CLI путём выполнения команды heroku login
  2. Выполнение команды git init в папке проекта
  3. Выполнение команды git remote add heroku **ваш путь до git'а проекта, который указан на странице проекта на Heroku**
  4. Выполнение команды git add . для добавления всех файлов в локальный репозиторий
  5. Выполнение команды git commit -m "ваше осмысленное и короткое сообщение, описывающее некоторые ключевые детали изменений проекта по сравнению с предыдущим commit'ом"
  6. Помещение локального репозитория в репозиторий heroku с помощью команды git push heroku master

После проделанных действий более делать ничего не нужно — Heroku соберёт проект в автоматическом режиме, а бот сделает всю рутинную работу за вас или ваших подчинённых.
Для наблюдения за жизненным циклом веб-сервиса у Heroku существует команда heroku logs --tail, которая позволяет наблюдать за log'ом последних действий.

Соображения по поводу дальнейшего развития


Планируется как минимум введение поддержки обработчиков, возвращающих не просто строку, а сформированное сообщение (improvement с целью поддержки различных attachment'ов в виде файлов).

upd: пришёл к выводу, что применённый механизм эмуляции не работает так, как ожидалось и сервис пребывает в бодрствующем состоянии лишь 30 минут, а далее «засыпает» пока к нему не постучатся напрямую (ссылка на проект всегда есть в кабинете проекта на Heroku-подобных хостерах), хотя вероятно просто стоит переписать на webhook. Собственные пожелания, а также ненависть и соображения по улучшению оставлять любыми удобными способами — буду рад услышать вас.

(Вероятно) полезные ссылки


Страница проекта библиотеки-обёртки
Страница проекта библиотеки взаимодействия с API Telegram'а

Комментарии (5)


  1. oWart
    14.12.2019 23:00

    В Go нынче вендорить можно через go mod vendor и сторонние библиотеки не нужны


  1. Griboks
    15.12.2019 12:36

    Честно говоря, не представляю, что может быть проще простых http запросов-ответов. Возможно, вы просто не разбирались с API телеги, а сразу перешли к каким-то сторонним библиотекам/обёрткам.


  1. backmeupplz
    15.12.2019 17:23
    +1

    Хоспаде, комментаторы от бога выше, которые *обожают*, похоже, придумывать велосипеды.

    telegraf.js.org наше все — там и плагинов туча, и разработчики приветливые и отзывчивые, и апи донельзя простое, и стейты есть, загляденье.

    Все остальное, пока не появится что-то лучше, трешак и стыд-позор.


    1. Dreadd
      16.12.2019 13:35

      Так-то для задачи которую поставил и решает автор эти "плагины, стейты, загляденья" мягко говоря не нужны. Давайте спокойнее относиться к людям, мнений много, в том числе и то что node.js для бота модели "привет-пока" позор, стыд и трешак...


  1. Dreadd
    16.12.2019 14:00

    На текущий момент обертка выглядит неплохо для задачи "вопрос-ответ", но если смотреть на возможное расширение то все становится уже не так забавно. Когда нужно реализовать что-то более интересное (многоэтапные диалоги настроек, хитрая разметка, индивидуальные кнопки, множественная обработка одного и того-же события etc) то все эти дополнительные абстракции над апи телеги начинают скорее мешать. Наглядным примером может служить telebot где вроде как все под рукой, шмяк шмяк и в продакшн, sendFile(), onSticker() и так далее, почти полное скрытие апи под своими "легкими в понимании" обертками. Но чем дальше в лес тем больше становится понятно что "а повесить новый хендлер на ходу уже нельзя", "conncurrent unfriendly", "давайте смотреть json теги в бибилиотеке чтобы понять что вообще она тут делает" и так далее… В этом отношении telegram-bot-api реально выглядит достаточно чистой и разумной штукой для которой нет смысла городить что-то дополнительное.