суббота, 20 октября 2018 г.

Telegram Bot на Java

После того как Пашка Дуров с помощью Роскомнадзор провел грамотную маркетинговую кампанию Telegram, многие по достоинству оценили API, которое позволяет интегрироваться с этим мессенджером посредством ботов.
Да, как бы мы не относились к личности Павла и его эпатажным выходкам - механизм ботов в Telegram выглядит изящным, красивым и продуманным решением.
Поэтому грех будет не написать своего бота, а то у всех есть, а у нас... Как-то неудобно даже.
Если вы не боитесь своими действиями пополнить армию Скайнет и приблизить закат человечества от железной руки роботов - тогда за мной. Программируй ботов во имя добра!




Telegram Bot Api
Боты - это хорошо. Это очень хорошо. Telegram-бот - это некая программа, которая выглядит как пользователь и умеет взаимодействовать с пользователями и другими ботами в Telegram.

Вот по этой ссылке находится официальная документация API Telegram-ботов. Если вы находитесь в стране запрещенных ботов, то скорее всего, эта ссылка будет у вас недоступна. Но вы же знаете, что делать?=) В крайнем случае - есть документация и на русском языке.

Согласно документации, Telegram Bot API представляет собой основанный на HTTP интерфейс для разработчиков, заинтересованных в создании ботов. Конечно, использовать чистые HTTP-запросы не так удобно, но, к счастью, добрые люди уже написали хорошую библиотеку на Java, ее мы и возьмем.
Задача
Чтобы продемонстрировать возможности ботов, напишем простого echo-бота, который в ответ на текстовое сообщение присылает нам это же текстовое сообщение. 
Создание такого бота сводится к двум шагам:
  1. Регистрация бота;
  2. Написание кода, обрабатывающего сообщения, отправленные этому боту;
Ну что ж, теперь, нужно сделать эти два шага к нашему общему светлому ботному будущему=)
Регистрация бота
Регистрация ботов нужна для того, чтобы получить уникальную строку - токен - без которой вы не сможете вызывать команды API. Токены выдает бот @BotFather. Найдите его поиском в Telegram - или пройдите по ссылке. Бот расскажет вам о себе и перечислит, какие команды поддерживает.
Чтобы создать зарегистрировать нового бота, необходимо послать боту @BotFather команду
/newbot. BotFather спросит у вас имя бота и имя пользователя для бота, а после этого скинет вам токен.
Выглядит это приблизительно так:

Итак мы получили токен: 766686857:AAH1Ap-eYwiAY-8XSaHRju06_IiFkm4Hv4I.
Идем дальше.
Обработка сообщений боту
Создадим Maven-проект для обработчика собщений нашего бота. pom.xml нашего проекта выглядит примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ru.blogspot.toolkas</groupId>
    <artifactId>toolkas-echo-bot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- Java-библиотека для работы с Bot API -->
        <dependency>
            <groupId>org.telegram</groupId>
            <artifactId>telegrambots</artifactId>
            <version>4.1</version>
        </dependency>
    </dependencies>
</project>
Напишем обработчик сообщений бота. В нашем случае он довольно тривиален:
package ru.blogspot.toolkas.telegram.bot.echo;

import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

/**
 * Класс-обработчик поступающих к боту сообщений.
 */
public class EchoBot extends TelegramLongPollingBot {
    /**
     * Метод, который возвращает токен, выданный нам ботом @BotFather.
     * @return токен
     */
    @Override
    public String getBotToken() {
        return "766686857:AAH1Ap-eYwiAY-8XSaHRju06_IiFkm4Hv4I";
    }

    /**
     * Метод-обработчик поступающих сообщений.
     * @param update объект, содержащий информацию о входящем сообщении
     */
    @Override
    public void onUpdateReceived(Update update) {
        try {
            //проверяем есть ли сообщение и текстовое ли оно
            if (update.hasMessage() && update.getMessage().hasText()) {
                //Извлекаем объект входящего сообщения
                Message inMessage = update.getMessage();
                //Создаем исходящее сообщение
                SendMessage outMessage = new SendMessage();
                //Указываем в какой чат будем отправлять сообщение 
                //(в тот же чат, откуда пришло входящее сообщение)
                outMessage.setChatId(inMessage.getChatId());
                //Указываем текст сообщения
                outMessage.setText(inMessage.getText());
                //Отправляем сообщение
                execute(outMessage);
            }
        } catch (TelegramApiException e) {
            e.printStackTrace();
        }
    }

    /**
     * Метод, который возвращает имя пользователя бота.
     * @return имя пользователя
     */
    @Override
    public String getBotUsername() {
        return "ToolkasEcho2Bot";
    }
}
Теперь мы должны зарегистрировать наш обработчик в запускаемом классе:
package ru.blogspot.toolkas.telegram.bot.echo;

import org.telegram.telegrambots.ApiContextInitializer;
import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;

public class App {
    public static void main(String[] args) throws TelegramApiRequestException {
        ApiContextInitializer.init();

        TelegramBotsApi botsApi = new TelegramBotsApi();
        botsApi.registerBot(new EchoBot());
    }
}
Запустив этот код мы подключим к нашему боту обработчик, который будет читать входящие сообщения бота и отправлять текст сообщений обратно.
Проверка
Итак, бот написан, пора его проверить в деле. Нужно запустить класс App и пройти по ссылке. Если мы все сделали правильно, то после отправки боту любого текстового сообщения - мы получим от него ответ с тем же самым текстом. Проверим это:
Если у вас заблокирован доступ до Telegram API, при запуске обработчика бота вы можете увидеть такую ошибку:
INFO: I/O exception (java.net.SocketException) caught when processing request to {s}->https://api.telegram.org:443: Connection reset
окт 20, 2018 8:20:20 PM org.apache.http.impl.execchain.RetryExec execute
INFO: Retrying request to {s}->https://api.telegram.org:443

Если вы это видите, значит сервер API доступа к Telegram упал (маловероятно) или у вас заблокирован доступ к сервисам Telegram (очень вероятно). Чтобы исправить доступ, вам нужно воспользоваться общепринятыми средствами обхода блокировок. И спасибо Роскомнадзору, что повышает компьютерную грамотность в нашей стране)))
Итог
Итак, мы написали простейшего бота. Исходный код - тут. Конечно возможности Telegram ботов не исчерпываются простым обменом текстовыми сообщениями. Мы не рассмотрели механизм веб-хуков и создание кнопочного интерфейса для ботов. Н обо всем этом - в следующий раз. Создавайте своих ботов - красивых и разных. И да пребудет с вами Сила!

3 комментария:

  1. ru.blogspot.toolkas.telegram.bot.echo;←где вы взяли это?эту надпись?

    botsApi.registerBot(new EchoBot());← и где вы взяли надпись"EchoBot"?у меня нет такого в библиотеке

    ОтветитьУдалить
    Ответы
    1. https://github.com/toolkas/echo-bot
      Вот полный код тестового бота.

      Возможно у вас более поздняя версия этой библиотеки

      Удалить
    2. 1) Это имя пакета. Разработчик вправе сам решать, какое имя ему назначить.
      2) Это имя класса, который создает автор. В этом методе нужно просто передать объект этого класса то есть:

      public Class {
      /...
      botsApi.registerBot(new ());

      Удалить