Как я Telegram бота на Go писал. Часть первая. Начало.

В этой серии заметок хотел бы немного коснуться данной темы. Серия будет включаться в себя три раздела:

  1. Разработка бота на Go для поиска заклинаний для Dungeon And Dragons
  2. Публикация бота на платформе heroku
  3. Добавление аналитики использования бота

Во-первых, нам потребуется сам список заклинаний DnD. Найти его можете в моём bitbucket-репозитории этого бота.

Во-вторых, создать новую папку. Например, dndspellsbot.

В-третьих, получить ключ для вашего нового бота у служебного аккаунта @BotFatherBot, отправив ему команду /newbot и сохранить полученный в ответ токен в безопасное место.

В-четвертых, чтобы не изобретать велосипед, добавить библиотеку telegram-bot-api:

go get gopkg.in/telegram-bot-api.v4

И, наконец-то, в-пятых, написать код самого бота.

Создадим пустой Go-файл dndspellsbot.go в папке dndspellsbot. Туда же добавим конфигурационный файл config.json со следующим содержимым:

{  "TelegramBotToken": "токен-полученный-от-BotFather" }

Конечно же, можно обойтись без этих усложнений и зашить токен прямо в коде бота, но в случае, если вы случайно зальетё код вашего бота в какой-то публичный репозиторий на github/bitbucket/whatever, то утечёт и токен, а это, согласитесь, неприятно. И это только сейчас у нас такой простой конфиг — в дальнейшем будут добавляться новые свойства и всё будет храниться в одном месте. Удобно, согласитесь?

Получить этот токен из конфигурационного файла довольно просто стандартными средствами Go:

package main  import (     "fmt"     "gopkg.in/telegram-bot-api.v4"     "log"     "os"     "encoding/json" )  type Config struct {     TelegramBotToken string }  func main() {     file, _ := os.Open("config.json")     decoder := json.NewDecoder(file)     configuration := Config{}     err := decoder.Decode(&configuration)     if err != nil {        log.Panic(err)     }     fmt.Println(configuration.TelegramBotToken) }

Теперь при добавлении в config.json новых свойств и модификации структуры Config можно получать необходимые параметры конфигурации.

В репозитории telegram-bot-api есть пример echo-бота — бота, который отвечает вам те же сообщением. Возьмём его за основу:

bot, err := tgbotapi.NewBotAPI(configuration.TelegramBotToken)  if err != nil {     log.Panic(err) }  bot.Debug = false  log.Printf("Authorized on account %s", bot.Self.UserName)  u := tgbotapi.NewUpdate(0) u.Timeout = 60  updates, err := bot.GetUpdatesChan(u)  if err != nil {     log.Panic(err) } // В канал updates будут приходить все новые сообщения. for update := range updates {      // Создав структуру - можно её отправить обратно боту     msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)     msg.ReplyToMessageID = update.Message.MessageID     bot.Send(msg) }

Вы уже добавила вашего бота в свой список контактов? Если нет — сейчас самое время.

Теперь самое интересное — запускаем наше приложение командой go run dndspellsbot.go и пишем что-нибудь нашему боту. Если всё сделано правильно, то бот ответит вам вашим же сообщением:

2016-10-03_21-46-08.png

Однако, мы хотели не этого.

Опустим подробности парсинга XML — пост не об этом (полный код можно будет найти по ссылке в конце статьи).

Будем считать, что у нас есть слайс всех заклинаний и любой запрос пользователя к боту — это запрос на поиск подходящего заклинания по его имени (усложнять можно бесконечно, но на данный момент этого достаточно):

... query := update.Message.Text // Получим те заклинания, в имени которых есть искомое слово или фраза filteredSpells := Filter(spells.Spells, func(spell Spell) bool {      return strings.Index(strings.ToLower(spell.Name), strings.ToLower(query)) >= 0 })  // Если не нашлось ни одного заклинания - скажем об этом пользователю if len(filteredSpells) == 0 {     msg := tgbotapi.NewMessage(update.Message.Chat.ID, "No one spells matches")     bot.Send(msg)  }  // Каждое заклинание отправляем отдельным сообщением for _, spell := range(filteredSpells) {     text := ""     for _, t := range(spell.Texts) {         text = text + t + "n"     }          msg := tgbotapi.NewMessage(update.Message.Chat.ID, fmt.Sprintf("%sn%s", spell.Name, text))     bot.Send(msg) } ... // Функция фильтрации слайсов func Filter(spells []Spell, fn func(spell Spell) bool) []Spell {     var filtered []Spell     for _, spell := range(spells) {         if fn(spell) {             filtered = append(filtered, spell)         }     }     return filtered }

Теперь, при любом запросе от пользователя, бот будет возвращать все подходящие заклинания из phb.xml.

В следующей статье немного улучшим нашего бота: добавим форматирование сообщений, inline-режим и добавим пару команд.

Код бота можно найти на bitbucket.

zaz600</span>Aug 30, 2015 · 5 min read</span></span>

В этой заметке я покажу, как можно написать бота для мессенджера Telegram при помощи языка Go.

Прежде чем начать работать с ботом, его необходимо создать. Для этого заходим в Telegram и находим там пользователя @BotFather и отсылаем ему команду /start, после чего он выдаст список доступных команд.

Нас интересует команда /newbot. Запускаем её и отвечаем на несколько вопросов имя (name) бота, ник (username) бота и т. п. Username должен быть уникальным и в конце обязательно должен содержать слово bot.

Если не совсем понятно, чем name отличается от username, смотрите картинку ниже.

Когда регистрация бота завершится успешно, вы увидите сообщение со ссылкой на вашего бота и токен для доступа к нему через API.

При необходимости можно ещё раз настроить бота, задав приветственное сообщение — то сообщение, которое увидит пользователь, когда зайдёт в приват к вашему боту.

Итак. Мы создали бота и у нас есть токен для доступа к нему. Приступим.

Для работы с API будем использовать библиотеку telegram-bot-api. Установим её, выполнив команду:

go get github.com/Syfaro/telegram-bot-api

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

Скачать исходный текст можно тут.

Не забудьте в код подставить токен, который вы получили от @BotFather

Компилируем, запускаем. Потом идём в приват к вашему боту и пишем ему какое-нибудь сообщение.

Бот готов. Дальше открывается простор для творчества. Всё, что нам надо сделать — это получить сообщение от пользователя, интерпретировать его и выдать ответ.

В приватной беседе (не в общем канале) бот получает от пользователя все сообщения, в общем же канале, он видит сообщения, которыми пользователи ответили на любое сообщение бота либо сообщения, начинающиеся с символа “слэш”, то есть “/”. Например, /help, /top, /last и т. п. Список таких команд можно задать через @BotFather командой /setcommands.

Сделаем так, чтобы бот приветствовал пользователей, входящих в канал.

   var reply string   if update.Message.NewChatParticipant.UserName != "" {     // В чат вошел новый пользователь     // Поприветствуем его     reply = fmt.Sprintf(`Привет @%s! Я тут слежу за порядком. Веди себя хорошо.`,     update.Message.NewChatParticipant.UserName)   }   if reply != "" {     // Созадаем сообщение     msg := tgbotapi.NewMessage(ChatID, reply)     // и отправляем его     bot.SendMessage(msg)   }

Полный текст тут.

Пусть наш бот, получив команду /instarandom, кидает ссылку на популярное фото в instagram.

Для доступа к API Instagram необходимо получить ClientID.

Идем в раздел для разработчиков https://instagram.com/developer/, регистрируемся там сами и регистрируем своё приложение, а затем копируем Client ID.

Если нет желания регистрировать своё приложение, то можно воспользоваться ClientID, который указан в библиотеке go-instagram. Однако вы можете получать ошибки при доступе к API по этому ключу, так как им наверняка многие пользуются, а у каждого ClientID есть ограничение на количество запросов в час.

Через @BotFather добавляем команду /instarandom, как описано выше.

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

Приступим.

Устанавливаем библиотеку g0-instagram.

go get github.com/carbocation/go-instagram/instagram

Создаём два канала. В первый будем помещать сообщения для функции get_ig_popular, которая будет обращаться к инстаграму и получать ссылку на популярное фото. Во второй — ответы от этой функции.

Так как обращаться к инстаграму мы будем в отдельной горутине, то ей необходимо передать (через канал) сообщение Telegram, в котором пользователь отправил команду /instarandom, чтобы она его вернула вместе со ссылкой на фото. А затем мы из основной программы ответим на сообщение переданной ссылкой.

// Читает канал с запросами к инстаграму// Получает популярное фото и отправляет в канал ответов ссылкуfunc get_ig_popular() {  // создаем и настраиваем клиента  instagram_client := instagram.NewClient(nil)  instagram_client.ClientID = "ClientID"   for {    for msg := range instagram_req {      // запрашиваем популярные фото      media, _, err := instagram_client.Media.Popular()       if err != nil {        log.Println(err)        continue      }      // возвращаем ссылку на первое фото из списка      if len(media) > 0 {instagram_res 

И изменения в main.

   case resp := <-instagram_res:     // отправляем инстаграм-ссылку пользователю     msg := tgbotapi.NewMessage(resp.m.Chat.ID, resp.url)     msg.ReplyToMessageID = resp.m.MessageID     bot.SendMessage(msg)  }

Импорт.

import ( “fmt” “github.com/Syfaro/telegram-bot-api”“github.com/carbocation/go-instagram/instagram” “log”)

Все вместе.

Полный текст можно скачать тут. Только не забудьте вставить в текст свой ClientID инстаграма.

Компилируем, запускаем, проверяем.

Итого.

Используя библиотеку telegram-bot-api, довольно несложно разрабатывать бота для Telegram, так как нет необходимости погружаться в особенности работы с API, хотя при желании это можно сделать. Также нет необходимости получать картинку напрямую, чтобы затем её пересылать пользователю, потому что Telegram-клиенты сами выкачивают содержимое ссылок и показывают его пользователю.

Используемые источники:

  • https://ashirobokov.wordpress.com/2016/10/04/dnd-spells-telegram-bot-1/
  • https://medium.com/golang-notes/пишем-бота-для-telegram-на-go-71c9acd102d1

Оцените статью
Рейтинг автора
5
Материал подготовил
Илья Коршунов
Наш эксперт
Написано статей
134
Добавить комментарий