Support links | Guides & News |
---|---|
max-chatbot-golang - библиотека для интеграции с мессенджером Max через API сервиса green-api.com. Чтобы воспользоваться библиотекой, нужно получить регистрационный токен и ID аккаунта в личном кабинете. Есть бесплатный тариф аккаунта разработчика.
Документация к REST API находится по ссылке. Библиотека является обёрткой к REST API, поэтому документация по ссылке выше применима и к самой библиотеке.
Чтобы отправить сообщение или выполнить другие методы GREEN API, аккаунт Max в приложении телефона должен быть в авторизованном состоянии. Для авторизации аккаунта перейдите в личный кабинет и авторизуйте инстанс с использованием номера телефона.
Не забудьте создать модуль:
go mod init example
Установка:
go get github.com/green-api/max-chatbot-golang
import (
"github.com/green-api/max-chatbot-golang/chatbot"
)
Перед запуском бота необходимо включить входящие уведомления в настройках экземпляра с помощью метода SetSettings.
"incomingWebhook": "yes",
"outgoingMessageWebhook": "yes",
"outgoingAPIMessageWebhook": "yes",
Создать инстанс можно в личном кабинете по ссылке. Нажмите создать и выберите тариф. Чтобы начать получать входящие уведомления, нужно настроить инстанс. Открываем страницу личного кабинета по ссылке. Выбираем инстанс из списка и кликаем на него. Нажимаем * Изменить*. В категории Уведомления включаем все вебхуки которые необходимо получать.
Для инициации бота нужно воспользоваться методом NewBot
из библиотеки и указать номер инстанса и токен из личного
кабинета.
bot := chatbot.NewBot("INSTANCE_ID", "TOKEN")
Обратите внимание, что ключи можно получать из переменных среды:
IDInstance := os.Getenv("ID_INSTANCE")
APITokenInstance := os.Getenv("API_TOKEN_INSTANCE")
Чтобы начать получать уведомления, необходимо вызвать у бота метод bot.StartReceivingNotifications()
.
Но перед этим необходимо добавить обработчик, это можно сделать двумя способами. Вы можете сделать это сразу в функции
main
как в примере base
.
Ссылка на пример: base.go.
package main
import (
"github.com/green-api/max-chatbot-golang/chatbot"
)
func main() {
bot := chatbot.NewBot("INSTANCE_ID", "TOKEN")
bot.IncomingMessageHandler(func(message *chatbot.Notification) {
if message.Filter(map[string][]string{"text": {"test"}}) {
message.AnswerWithText("Well done! You have write \"test\".")
} else {
message.AnswerWithText("Write \"test\"!")
}
})
bot.StartReceivingNotifications()
}
Если у вас сложные вложенные сценарии, лучше использовать сцены как в примере baseScene
.
Пользоваться сценами просто - достаточно вынести логику бота в отдельную структуру, которая реализовывает интерфейс
Scene
, и добавить ее в бот методом bot.SetStartScene(StartScene{})
.
Стартовая сцена может вызвать следующую с помощью метода message.ActivateNextScene(NextScene{})
, тогда следующий
вебхук попадет уже в новую сцену, это позволит разделить бота на отдельные части и сделает код более читаемым и
редактируемым:
package main
import (
"github.com/green-api/max-chatbot-golang/chatbot"
)
func main() {
bot := chatbot.NewBot("INSTANCE_ID", "TOKEN")
bot.SetStartScene(StartScene{})
bot.StartReceivingNotifications()
}
type StartScene struct {
}
func (s StartScene) Start(bot *chatbot.Bot) {
bot.IncomingMessageHandler(func(message *chatbot.Notification) {
if message.Filter(map[string][]string{"text": {"test"}}) {
message.AnswerWithText("Well done! You have write \"test\".")
message.AnswerWithText("Now write \"second scene\"")
message.ActivateNextScene(SecondScene{})
} else {
message.AnswerWithText("Write \"test\"!")
}
})
}
type SecondScene struct {
}
func (s SecondScene) Start(bot *chatbot.Bot) {
bot.IncomingMessageHandler(func(message *chatbot.Notification) {
if message.Filter(map[string][]string{"text": {"second scene"}}) {
message.AnswerWithText("Well done! You have write \"second scene\".")
message.ActivateNextScene(StartScene{})
} else {
message.AnswerWithText("This is second scene write \"second scene\"!")
}
})
}
Если вам нужно чтобы при создании нового состояния, оно уже имело некоторые дефолтные значения, необходимо изменить поле
InitData
у структуры StateManager
.
В стандартной имплементации MapStateManager
это делается так:
package main
import (
greenapi "github.com/green-api/max-api-client-golang"
"github.com/green-api/max-chatbot-golang/chatbot"
"github.com/green-api/max-chatbot-golang/examples/full"
)
func main() {
bot := chatbot.NewBot("INSTANCE_ID", "TOKEN")
bot.StateManager = chatbot.NewMapStateManager(
map[string]interface{}{
"defaultField1": "defaultValue1",
"defaultField2": "defaultValue2",
"defaultField3": "defaultValue3",
})
bot.SetStartScene(full.StartScene{})
bot.StartReceivingNotifications()
}
Обратите внимание, что во время выполнения запросов могут возникать ошибки, чтобы ваша программа не прерывалась из-за
них,
вам необходимо обрабатывать ошибки. Все ошибки библиотеки отправляются в канал ErrorChannel
, вы можете обработать их
например таким способом:
package main
import (
"fmt"
"github.com/green-api/max-chatbot-golang/chatbot"
"github.com/green-api/max-chatbot-golang/examples/full"
)
func main() {
bot := chatbot.NewBot("INSTANCE_ID", "TOKEN")
bot.SetStartScene(full.StartScene{})
//Все ошибки будут просто выводиться в консоль
go func() {
select {
case err := <-bot.ErrorChannel:
if err != nil {
fmt.Println(err)
}
}
}()
bot.StartReceivingNotifications()
}
Получать можно не только входящие сообщения, но и исходящие, а так же их статусы и любые другие типы веб хуков. Для этого просто добавьте в сцену или в функцию main новый обработчик. В каждой сцене может быть несколько обработчиков.
Ссылка на пример: event.go.
package main
import (
cb "github.com/green-api/max-chatbot-golang/chatbot"
)
type StartScene struct {
}
func (s StartScene) Start(bot *cb.Bot) {
bot.IncomingMessageHandler(func(notification *cb.Notification) {
//Логика обработки входящих сообщений
})
bot.OutgoingMessageHandler(func(notification *cb.Notification) {
//Логика обработки исходящих сообщений
})
bot.OutgoingMessageStatusHandler(func(notification *cb.Notification) {
//Логика обработки статусов исходящих сообщений
})
bot.StateInstanceChangedHandler(func(notification *cb.Notification) {
//Логика обработки вебхуков о смене статуса инстанса
})
}
Получать входящие уведомления (сообщения, статусы) можно через HTTP API запросы по аналогии, как реализованы остальные методы Green API. При этом гарантируется хронологический порядок следования уведомлений в той последовательности, в которой они были получены FIFO. Все входящие уведомления сохраняются в очереди и ожидают своего получения в течение 24 часов.
Для получения входящих уведомлений требуется выполнить последовательно вызов двух методов ReceiveNotification и DeleteNotification. Метод ReceiveNotification выполняет получение входящего уведомления. Метод DeleteNotification подтверждает успешное получение и обработку уведомления. Подробнее о методах смотрите в соответствующих разделах ReceiveNotification и DeleteNotification.
Фильтрация по типу вебхука происходит автоматически на уровне создания обработчика,
пример - event.go.
Другие типы фильтров реализованы с помощью метода Filter
который принимает в качестве параметра
map[string][]string{}
.
Ключом данной карты служит строка с именем параметра по которому будет происходить фильтрация, значение карты - срез с
набором ожидаемых значений.
Если в фильтре по параметру несколько ожидаемых значений, то метод возвращает true
если хотя бы одно ожидаемое
значение совпадает с полем вебхука.
Если метод фильтрует одновременно несколько параметров, то метод возвращает true
только если все параметры прошли
проверку.
Имена параметров для фильтрации | Описание |
---|---|
text |
Фильтр по тексту сообщения, если хоть один из ожидаемых значений совпадает, возвращает true |
text_regex |
Фильтр по тексту сообщения, но по regex паттерну, если хотябы один паттерн в срезе подходит, возвращает true |
sender |
Возвращает true , если хотя бы одно ожидаемое значение равно идентификатору отправителя сообщения |
chatId |
Возвращает true , если хотя бы одно ожидаемое значение равно идентификатору чата сообщения |
messageType |
Возвращает true , хотя бы одно ожидаемое значение равно значению поля messageType в вебхуке |
Ссылка на пример: filter.go.
package main
import (
cb "github.com/green-api/max-chatbot-golang/chatbot"
)
type StartScene struct {
}
func (s StartScene) Start(bot *cb.Bot) {
bot.IncomingMessageHandler(func(message *cb.Notification) {
if message.Filter(map[string][]string{"text": {"1"}}) {
message.AnswerWithText("This message text equals \"1\"")
}
if message.Filter(map[string][]string{"text_regex": {"\\d+"}}) {
message.AnswerWithText("This message has only digits!")
}
if message.Filter(map[string][]string{"text_regex": {"6"}}) {
message.AnswerWithText("This message contains \"6\" in the text")
}
if message.Filter(map[string][]string{"text": {"hi"}, "messageType": {"textMessage", "extendedTextMessage"}}) {
message.AnswerWithText("This message is a \"textMessage\" or \"extendedTextMessage\", and text equals \"hi\"")
}
})
}
По умолчанию в данной библиотеке состояние хранится в карте типа map[string]interface{}{}
.
В качестве ключа может быть любая строка в качестве значения, любой объект.
Идентификатором состояния является идентификатор чата, то есть у каждого чата будет отдельное состояние.
Чтобы управлять состоянием, нужно использовать методы структуры Notification
:
Метод менеджера | Описание |
---|---|
ActivateNextScene() |
Активирует выбранную сцену. |
GetCurrentScene() |
Возвращает текущую сцену. |
GetStateData() |
Возвращает данные состояния выбранного чата. |
SetStateData() |
Заменяет данные состояния выбранного чата. |
UpdateStateData() |
Обновляет данные состояния выбранного чата. |
Вебхуки типа stateInstanceChanged не привязаны к чату, поэтому не имеют собственного состояния. Если вы хотите взаимодействовать с состояниями других чатов, отличных от чата обрабатываемого вебхука, вы можете использовать методы структуры
StateManager
напрямую. МетодыStateManager
делают тоже что и методы структурыNotification
, но они ожидают дополнительный параметрstateId
.
В качестве примера был создан простой бот для имитации регистрации пользователя.
Ссылка на пример: state.go.
package main
import (
"github.com/green-api/max-chatbot-golang/chatbot"
)
type StartScene struct {
}
func (s StartScene) Start(bot *chatbot.Bot) {
bot.IncomingMessageHandler(func(notification *chatbot.Notification) {
if notification.Filter(map[string][]string{"text": {"/start"}}) {
notification.AnswerWithText("Привет! Этот бот - пример использования состояния.\nПожалуйста введите логин:")
notification.ActivateNextScene(LoginScene{})
} else {
notification.AnswerWithText("Пожалуйста введите команду /start.")
}
})
}
type LoginScene struct {
}
func (s LoginScene) Start(bot *chatbot.Bot) {
bot.IncomingMessageHandler(func(notification *chatbot.Notification) {
login, err := notification.Text()
if err != nil || len(login) > 12 || len(login) < 6 {
notification.AnswerWithText("Выберите логин от 6 до 12 символов!")
} else {
notification.UpdateStateData(map[string]interface{}{"login": login})
notification.ActivateNextScene(PasswordScene{})
notification.AnswerWithText("Ваш логин " + notification.GetStateData()["login"].(string) + " - успешно сохранен.\nПридумайте пароль:")
}
})
}
type PasswordScene struct {
}
func (s PasswordScene) Start(bot *chatbot.Bot) {
bot.IncomingMessageHandler(func(notification *chatbot.Notification) {
password, err := notification.Text()
if err != nil || len(password) > 16 || len(password) < 8 {
notification.AnswerWithText("Выберите пароль от 8 до 16 символов!")
} else {
notification.UpdateStateData(map[string]interface{}{"password": password})
notification.ActivateNextScene(StartScene{})
notification.AnswerWithText("Успех! Ваш логин: " + notification.GetStateData()["login"].(string) + "\nВаш пароль: " + notification.GetStateData()["password"].(string))
}
})
}
Если вам нужно чтобы при создании нового состояния, оно уже имело некоторые дефолтные значения, необходимо изменить поле
InitData
у структуры StateManager
.
В стандартной имплементации MapStateManager
это делается так:
package main
import (
"github.com/green-api/max-chatbot-golang/chatbot"
"github.com/green-api/max-chatbot-golang/examples/full"
)
func main() {
bot := chatbot.NewBot("INSTANCE_ID", "TOKEN")
bot.StateManager = chatbot.NewMapStateManager(
map[string]interface{}{
"defaultField1": "defaultValue1",
"defaultField2": "defaultValue2",
"defaultField3": "defaultValue3",
})
bot.SetStartScene(full.StartScene{})
bot.StartReceivingNotifications()
}
В качестве примера был создан бот демонстрирующий отправку методов структуры Notification
.
Запуск бота происходит командой - /start После запуска необходимо выбрать метод из меню, и бот выполнит его.
Ссылка на пример: full.go.
Стартовая сцена ждет команду /start
, после чего отправляет меню и активирует следующую сцену PickMethodScene
.
PickMethodScene
ждет ответа пользователя и выполняет выбранный метод.
Если пользователь выбрал SendFileByUrl()
, то бот запустит сцену InputLinkScene
, в которой попросит ссылку на файл и
отправит файл, если ссылка валидна.
package full
import (
greenapi "github.com/green-api/max-api-client-golang"
"github.com/green-api/max-chatbot-golang/chatbot"
)
type StartScene struct {
}
func (s StartScene) Start(bot *chatbot.Bot) {
bot.IncomingMessageHandler(func(notification *chatbot.Notification) {
if notification.Filter(map[string][]string{"text": {"/start"}}) {
notification.AnswerWithText(`Привет! Этот бот использует различные методы API.
Пожалуйста выберите метод:
1. SendMessage()
2. SendFileByUrl()
Пришлите номер пункта одной цифрой.`)
notification.ActivateNextScene(PickMethodScene{})
} else {
notification.AnswerWithText("Пожалуйста введите команду /start.")
}
})
}
type PickMethodScene struct {
}
func (s PickMethodScene) Start(bot *chatbot.Bot) {
bot.IncomingMessageHandler(func(message *chatbot.Notification) {
if message.Filter(map[string][]string{"text": {"1"}}) {
message.AnswerWithText("Hello world!")
}
if message.Filter(map[string][]string{"text": {"2"}}) {
message.AnswerWithText("Give me a link for a file, for example: https://th.bing.com/th/id/OIG.gq_uOPPdJc81e_v0XAei")
message.ActivateNextScene(InputLinkScene{})
}
if !message.Filter(map[string][]string{"text_regex": {"\\d+"}}) {
message.AnswerWithText("Ответ должен содержать только цифры!")
}
})
}
type InputLinkScene struct {
}
func (s InputLinkScene) Start(bot *chatbot.Bot) {
bot.IncomingMessageHandler(func(message *chatbot.Notification) {
if message.Filter(map[string][]string{"text_regex": {"^https://[^\\s]+$"}}) {
text, _ := message.Text()
message.AnswerWithUrlFile(text, "testFile", "This is your file!")
message.ActivateNextScene(PickMethodScene{})
} else {
message.AnswerWithText("Ссылка не должна содержать пробелы и должна начинаться на https://")
}
})
}
Документация по методам сервиса
Лицензировано на условиях Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) . LICENSE.