Программирование

Пишем Telegram бота на Go

Telegram постоянно увеличивается в размерах, умники уже сколотили себе аудиторию в Telegram и монетизируют ее разными способами. Если вы один из них, вам может пригодиться бот, который будет общаться с пользователями, принимать оплату за товары и\или услуги, а также автоматизировать какую-то рутину.

Мне нравится Golang как практичный язык, который позволяет быстро создавать те или иные решения, не изучая основы программирования 5-7 лет, не читая 10 томов как надо правильно использовать ту или иную теоретическую базу. Просто садись и пиши бизнес-логику. Ведь в конечном счете программирование — это инструмент, а не самоцель. По крайней мере, для меня.

Давайте используем готовую либу для работы с Telegram Bot API: https://github.com/tucnak/telebot

Готовый пример можно посмотреть тут: https://github.com/Sagleft/telegram-bot-gosample — я разделил по версиям релиза, чтобы можно было посмотреть простой пример, затем более сложный.

Начнем с простого примера, который указан в Readme либы:

package main

import (
	"log"
	"time"

	tb "gopkg.in/tucnak/telebot.v2"
)

func main() {
	b, err := tb.NewBot(tb.Settings{
		Token:  "TOKEN_HERE",
		Poller: &tb.LongPoller{Timeout: 10 * time.Second},
	})

	if err != nil {
		log.Fatal(err)
		return
	}

	b.Handle("/start", func(m *tb.Message) {
		b.Send(m.Sender, "Hello World!")
	})

	b.Start()
}

Тут всё просто. Указываем токен бота, который получаем от @BotFather затем ожидаем когда пользователь начнет диалог с ботом и получит сообщение «Hello World!»

Теперь улучшим. Сделаем загрузку токена бота из JSON. Создадим файл helpers.go со следующим содержанием:

package main

import (
	"encoding/json"
	"io/ioutil"
)

func readFile(filepath string) ([]byte, error) {
	filebytes, err := ioutil.ReadFile(filepath)
	if err != nil {
		return nil, err
	}
	return filebytes, err
}

func getBotSettings() (*botSettings, error) {
	settingsBytes, err := readFile(settingsFilePath)
	if err != nil {
		return nil, err
	}
	settings := botSettings{}
	err = json.Unmarshal(settingsBytes, &settings)
	if err != nil {
		return nil, err
	}
	return &settings, nil
}

А также добавляем в основной файл (у меня это bot.go) следующее:

const (
	settingsFilePath = "settings.json"
)

type botSettings struct {
	Token string `json:"token"`
}

и делаем загрузку этих параметров в func main:

	settings, err := getBotSettings()
	if err != nil {
		log.Fatal(err)
		return
	}

	b, err := tb.NewBot(tb.Settings{
		Token:  settings.Token,
		Poller: &tb.LongPoller{Timeout: 10 * time.Second},
	})

Поясню новичкам в Go:

  • в Go можно возвращать несколько результатов функции, а не только один. По началу это кажется дико, но затем становится ясно, что так удобно обрабатывать возникшие ошибки. Обычно сначала идет результат, затем ошибка.
  • В Go используются структуры, в данном случае для хранения настроек бота, которые мы загружаем из JSON, десериализуем в структуру. А дальше просто берем необходимые данные из этой структуры по ее полям. Для структур также можно добавлять методы, об этом расскажу в других уроках.
  • *botSettings означает ссылку на элемент типа botSettings. В Go бывает удобно использовать в качестве результата ссылку, чтобы в случае возврата ошибки также вернуть результат как nil. Мнения на счет целесообразности такого подхода у разработчиков расходятся, но он существует и распространен.
  • в блоке const мы объявили константу.
теперь наш бот отвечает на старт беседы

Позже расскажу как сделать Inline-кнопки с этой либой. Ибо это не очевидный трюк

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *