| 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-golangimport (
"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.