После реализации бота на Ruby , мне захотелось сделать ещё одного, но уже на моём любимом языке — Golang.
Когда я только начинал работу, информации о библиотеке go-telegram-bot-api у меня не было. Так что пришлось писать бота практически с нуля. В проекте на Ruby все самое сложное делал гем telegram-bot-ruby . Но в этот раз я захотел сам реализовать бота.
После потраченного вечера на поиск информации об архитектуре телеграм ботов, я занялся написанием самого проекта.
Main():
err := initConfig() if err != nil
Сначала бот инициализирует конфиг (ключи и токены) вызывая функцию initConfig(), которая выглядит следующим образом:
func initConfig() error
Тут я использую библиотеку viper для считывания ключей и токенов из файла config.json
После инициализации конфига бот выполняет проверку переменной err, в которую в случае ошибки будет записан код ошибки (точнее не код, а сама ошибка). Если переменная err равна nil, бот продолжит работу, в противном случае в консоль выведется ошибка и main() закроется.
Мастер-класс «Создание telegram бота на Go»
в языке Golang значение nil означает буквально «ничего»
botUrl := «https://api.telegram.org/bot» + viper.GetString(«token») offSet := 0 for < updates, err := getUpdates(botUrl, offSet) if err != nil < fmt.Println(«Something went wrong: «, err) return >for _, update := range updates < respond(botUrl, update) offSet = update.UpdateId + 1 >fmt.Println(updates) >
После работы с инициализацией конфига, бот записывает в переменную botUrl ссылку, по которой он будет получать сообщения, или же слайс объектов Update. botUrl состоит из токена, полученного ранее из файла config.json и ссылки на api.telegram.org . Идентификатор offset нужен для обработки нескольких сообщений.
Далее идёт главный цикл бота, в котором происходит вообще всё. Для работы с пользователем боту необходимо получить от него сообщение, это реализовано с помощью функции getUpdates():
getUpdates()
func getUpdates(botUrl string, offset int) ([]mods.Update, error) < resp, err := http.Get(botUrl + «/getUpdates?offset=» + strconv.Itoa(offset)) if err != nil < return nil, err >defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil < return nil, err >var restResponse mods.TelegramResponse err = json.Unmarshal(body, return nil, err >return restResponse.Result, nil >
Построчно расписывать не буду, весь процесс в этой функции можно расписать так:
Бот отправляет запрос GET телеграму, на что получает json файл, который переводит в слайс byte’ов. Слайс байтов записывается в структуру restResponse, которая имеет только одно поле — «Result». Result является слайсом объектов Update. В конце функция вернёт поле «Result», т.е слайс обновлений.
type TelegramResponse struct
type Update struct
Структура Update имеет всего два поля: идентификатор обновления и объект Message:
Пишем TELEGRAM бота на GO
type Message struct
У структуры Message есть поле Chat, которое бот использует только для работы с идентификатором чата. Поле Text отвечает за текст сообщения, а поле Sticker нужно для обработки сообщений, состоящих из стикера.
После получения слайса обновлений, бот проходится по каждому объекту Update функцией respond().
respond()
func respond(botUrl string, update mods.Update) error < msg := strings.ToLower(update.Message.Text) if msg != «» < switch msg < . >>
В этой функции я описал весь функционал бота, сначала записывает в переменную msg сообщение, которое берет из объекта Update и переводит в нижний регистр, после чего идёт проверка на то, что отправил пользователь.
Если на вход пришло сообщение, функция пройдется по нему с помощью оператора switch:
switch msg < case «/check»: mods.Check(botUrl, update) return nil case «/git»: mods.CheckGit(botUrl, update) return nil case «/weather7»: mods.SendDailyWeather(botUrl, update, 7) return nil . >
При каждой команде, вызывается определённая функция, после чего respond() возвращает nil, что означает, что всё прошло без ошибок.
> else < if update.Message.Sticker.File_id != «» < mods.SendRandomSticker(botUrl, update) return nil >mods.SendMsg(botUrl, update, «Пока я воспринимаю только текст и стикеры ♂️») return nil >
Если же пользователь отправил не текст, а что-то иное, бот сделает проверку на стикер. Если пользователь отправил стикер, бот тоже отправляет в ответ случайный стикер. В остальных случаях бот уведомит пользователя, что воспринимает только текст и стикеры.
Осталось рассказать о командах, но это я сделаю в следующей статье. В целом, это оказался очень интересный проект, над которым я работаю до сих пор. Мало того, что во время реализации бота я накапливаю опыт работы с API, так ещё и получаю очень полезного помощника, который подскажет погоду, курс криптовалюты, отправит смешную картинку с попугаем или котом, найдёт страну по IP адресу, и даже я не знаю, как его функционал изменится через неделю.
Источник: teletype.in
Пишем простого бота для Telegram на Go. Часть 1
Написание бота для Telegram отличный способ попрактиковаться в изучении Go.
Преимущества создания программ под Telegram-бота состоят в том, что для получения результата не нужно отдельно создавать frontend-часть, достаточно реализовать необходимую логику на backend-части и добавить взаимодействие с ботом.
Итак, начинаем процесс создания нового бота и через несколько часов можно будет насладиться результатом
Шаг 1. Регистрация Telegram бота
После этого будет предложено выбрать имя бота и уникальное имя пользователя для бота. Имя пользователя при этом должно заканчиваться на bot.
В результате, будет создан новый пользователь по указанному имени username и token, который понадобится для работы с API Telegram
Процесс создания бота
Шаг 2. Постановка задачи для бота
Существуют 2 основных сценария использования бота — взаимодействие с ботом с помощью приватных сообщений и добавление бота в чат группы.
Какие сообщения при этом будет получать бот для анализа?
Все боты вне зависимости от настроек будут получать следующие сообщения:
- все сервисные сообщения
- все сообщения из личных каналов сообщений с пользователем
- все сообщения из каналов, в которых состоит бот
Боты с отключенным режимом конфиденциальности будут получать все сообщения, кроме сообщений, отправленных другими ботами.
Боты с включенным режимом конфиденциальности получат:
Поставим задачу создать бота, который анализируя сообщения пользователя в группе, высылает автоответы на наиболее популярные запросы.
Шаг 3. Пишем код на Go
Сначала установим библиотеку для работы с API Telegram
go get github.com/go-telegram-bot-api/telegram-bot-api/v5
Далее перейдем к реализации процесса программирования бота.
Простейший бот представляет собой сервис, в данном случае написанный на языке Go, который использует long-polling запросы для получения информации об обновлении данных.
Для подключения к API Telegram необходимо воспользоваться методом NewBotApi . В качестве параметра необходимо указать ключ API полученный на этапе регистрации бота.
Итак, наш бот почти готов. Осталось вставить ключ API и реализовать логику по формированию ответа пользователю
Учим бот анализировать сообщение и формировать ответ
Возвращаемся к постановки первоначальной задачи. Итак нам нужно анализировать текст сообщения от пользователя и формировать ответ.
При этом возможны сценарии, когда бот формирует ответ в виде публичного ответа пользователю в группе или же отправляет сообщение пользователю в личном сообщении
В случае публичного ответа (см. пример выше) мы должны в качестве в методе NewMessage указать идентификатор канала, из которого мы получили сообщение (берем из поля message.Chat.ID ) и заполнить поле ReplyToMessageID сообщения, указав ID сообщения, на которое нужно ответить (берем из поля Message.MessageID )
Пример ответов бота Anfiska в чате группы
В случае приватного ответа, в качестве идентификатора чата мы должны указать ID пользователя, которому мы собираемся отправить сообщение (берем из поля Message.From.ID ). В этом случае поле ReplyToMessageID сообщения проставлять не нужно.
Код отправки сообщения будет выглядеть так:
Источник: dzen.ru
Пишем телеграм бота на Go и AWS Lambda
Будем писать простой телеграм бот, отвечающий тем же сообщением, что и отправили.
Почему AWS Lambda ?
- Удобство деплоя, просто пишешь sls deploy , и lambda уже выгружена
- Платишь только за время, когда lambda работает
- Не надо настраивать никаких серверов, и беспокоиться о масштабировании
Что понадобится?
- Установленный go
- Nodejs и npm для установки serverless
- AWS аккаунт для деплоя
TLDR
- Клонируем репозиторий https://github.com/R11baka/echotgbot
- Устанавливаем в .env файле BOT_TOKEN переменную
- Компилируем бинарник env GOOS=linux go build -o bin/webhook main.go
- Выгружаем лямбду с помощью sls deploy
- Устанавливаем webhook с помощью BOT_TOKEN
Регистрация в AWS
- Регистирируем пользователя в AWS aws console и получаем aws_access_key_id, и aws_secret_access_key и прописываем их в .aws/credentials файле
Вот как выглядит мой .aws/credentials
cat ~/.aws/credentials [default] aws_access_key_id = ADEFEFEFFEBDXK3 aws_secret_access_key = Zy6ewfir/zGaT1B2/o9JDWDSssdrla region = us-west-1
Регистрация бота
Для начала, нам надо зарегистировать бота в BotFather. Идем по ссылке, отправляем команду BotFather /newbot , придумываем имя боту, описание. В конце, BotFather вернет нам токен бота.Этот токен понадобится,нам для дальнейшей разработки.
Установка Serverless
Serverless-это framework, облегчающий настройку, деплой AWS Lambda функций. Написан на node, поэтому для его установки понадобится nodejs и npm. Устанавливаем serverless через npm
npm install -g serverless
После установки serverless проверяем, все ли установилось
sls -v Framework Core: 2.35.0 (standalone) Plugin: 4.5.3 SDK: 4.2.2 Components: 3.8.2
Теперь можно приступить к конфигурации serverless. Все настройки для serverless лежат в serverless.yml файле,который мы и создадим со следующим контентом
service: echoBot useDotenv: true configValidationMode: error # если в конфиге,чтото неправильно ,то ошибка frameworkVersion: ‘>=1.28.0 events: — http: path: /webhook method: ANY cors: false
Имлементация логики бота на Go
- Устанавливаем библиотеки telebot.v2 и aws-lambda-go
➜ go mod init testBot go: creating new go.mod: module testBot ➜ go get -u gopkg.in/tucnak/telebot.v2 go: gopkg.in/tucnak/telebot.v2 upgrade => v2.3.5 go: github.com/pkg/errors upgrade => v0.9.1 ➜ go get github.com/aws/aws-lambda-go go: github.com/aws/aws-lambda-go upgrade => v1.23.0
2. Создаем файл main.go с контентом
package main import ( «encoding/json» «fmt» «github.com/aws/aws-lambda-go/events» «github.com/aws/aws-lambda-go/lambda» tb «gopkg.in/tucnak/telebot.v2» «os» ) func main() < settings := tb.Settings< Token: os.Getenv(«BOT_TOKEN»), Synchronous: true, Verbose: true, >tgBot, err := tb.NewBot(settings) if err != nil < fmt.Println(err) panic(«can’t create bot») >tgBot.Handle(tb.OnText, func(m *tb.Message) < message := m.Text tgBot.Send(m.Sender, message) >) lambda.Start(func(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) < var u tb.Update if err = json.Unmarshal([]byte(req.Body), err == nil < tgBot.ProcessUpdate(u) >return events.APIGatewayProxyResponse, nil >) >
Текущая документация в tucnak/telebot.v2 немного устарела, и если просто написать return вместо return events.APIGatewayProxyResponse, nil , то телеграм будет повторно отправлять сообщения к боту.
Deploy бота
- Создаем файл .env и вставляем API_TOKEN полученный от BotFather
echo API_TOKEN= > .env
sls print
env GOOS=linux go build -o bin/webhook main.go
serverless deploy -v
При успешной выгрузке, мы получим в конце
Service Information service: echoBot stage: dev region: us-west-1 stack: echoBot-dev resources: 11 api keys: None endpoints: ANY — https://y7p31bwnu1.execute-api.us-west-1.amazonaws.com/dev/webhook functions: webhook: echoBot-dev-webhook layers: None
Интеграция с telegram
Осталось сообщить телеграму, какой эндпоинт дергать при получении сообщения. Делается это командой setWebhook
curl https://api.telegram.org/bot/setWebhook?url=
Проверка что webhook установлен, происходит с помощью getWebhookInfo
➜ ~ curl https://api.telegram.org/bot1324913549:AAE1zYMH6K3hF2TOgUQoIP-E1g4rMIamck/setWebhook?url= https://y7p31bwnu1.execute-api.us-west-1.amazonaws.com/dev/webhook ➜ ~ curl https://api.telegram.org/bot1324913549:AAE1zYMH6K3hF2TOgUQoIP-E1g4rMIamck/getWebhookInfo >
Ошибки
Если что-то пошло не так,идем в CloudWatch и смотрим логи,или же из консоли также можно посмотреть логи
sls logs -f webhook
Источник: temofeev.ru