JavaRush /Java блог /Random /Telegram Ability Bot: бот, умеющий вести диалог: Часть 2
Chundrik
35 уровень
Санкт-Петербург

Telegram Ability Bot: бот, умеющий вести диалог: Часть 2

Статья из группы Random
ЧАСТЬ 1 Чтобы позже не запутаться в частях программы, я стараюсь всю логику разделять на отдельные классы. Собственно фразы, которыми будет отвечать бот, будут хранится в интерфейсе Constants. Создадим там строку:

String START_DESCRIPTION = "Hello";
Затем перейдем в класс TelegramBot и вставим следующий код:

public Ability replyToStart() {
    return Ability
        .builder()
        .name("start")
        .info(Constants.START_DESCRIPTION)
        .locality(ALL)
        .privacy(PUBLIC)
        .action(ctx ->  silent.send("Hello!", ctx.chatId()))
        .build();
}
Telegram Ability Bot: бот, умеющий вести диалог: Часть 2 - 1Теперь бот может приветствовать его клиентов в ответ на стандартную команду /start. Попробуйте запустить его: бот уже немного живой! Но, как и любому монстру Франкештейна, ему не хватает парочки конечностей.Telegram Ability Bot: бот, умеющий вести диалог: Часть 2 - 2

Использование встроенной клавиатуры

Чтобы бот смог построить с нами диалог, нам понадобятся еще два класса: MessageFactory и KeyboardFactory. Первый будет считывать ответы людей и генерировать сообщения, а второй — создавать кнопки с ответами.

public class KeyboardFactory {
    public static ReplyKeyboard startButtons() {
        InlineKeyboardMarkup inlineKeyboard = new InlineKeyboardMarkup();
        List<list<inlinekeyboardbutton>> rowsInline = new ArrayList<>();
        List<inlinekeyboardbutton> rowInline = new ArrayList<>();

       rowInline.add(new InlineKeyboardButton().setText("DISCUSSION").setCallbackData(Constants.DISCUSSION));
        rowInline.add(new InlineKeyboardButton().setText("SMALL TALK").setCallbackData(Constants.SMALL_TALK));

        rowsInline.add(rowInline);
        inlineKeyboard.setKeyboard(rowsInline);
        return inlineKeyboard;
    }
}
</inlinekeyboardbutton></list<inlinekeyboardbutton>
По пути добавим в Constants:

String START_REPLY = "Start using the telegram bot if you are lonely or bored";
String CHOOSE_OPTION = "Make a choice";
String DISCUSSION = "Let's discuss!";
String SMALL_TALK = "Let's talk!";
Теперь мы можем просто вызвать статический метод нашей фабрики, чтобы использовать встроенную клавиатуру. Самая важная часть кода — это setCallbackData(). Она распознает, какая кнопка была нажата пользователем. Переходим в MessageFactory:

public class MessageFactory {
    private final MessageSender sender; //используется для отправки сообщений обратно пользователю

    public MessageFactory(MessageSender sender) {
        this.sender = sender;
    }

    public void start (long chatId) {
        try {
            sender.execute(new SendMessage()
                    .setText(Constants.START_REPLY)
                    .setChatId(chatId));

            sender.execute(new SendMessage()
                    .setText(Constants.CHOOSE_OPTION)
                    .setChatId(chatId)
                    .setReplyMarkup(KeyboardFactory.startButtons()));


        } catch (TelegramApiException e) {
            e.printStackTrace();
        }
    }
}
Заменим код в методе Telegrambot.replyToStart():

public Ability replyToStart() {
        return Ability
                .builder()
                .name("start")
                .info(Constants.START_DESCRIPTION)
                .locality(ALL)
                .privacy(PUBLIC)
                .action(ctx ->  messageFactory.start(ctx.chatId()))
                .build();
    }
И еще одна поправка в том же классе — замена конструктора:

private TelegramBot(String botToken, String botUsername) {
        super(botToken, botUsername);
        messageFactory = new MessageFactory(sender);
    }
Попробуйте перезапустить ваш бот. Теперь он предложит встроенную клавиатуру в ответ на ваши действия.Telegram Ability Bot: бот, умеющий вести диалог: Часть 2 - 3Полезные лайфхаки для новичков: Если вы пользуетесь Идеей и хотите посмотреть документацию по классу, то выделите класс или метод и нажмите Ctrl+J на Mac или Ctrl+Q на Windows. Также можно сделать правой кнопкой мыши-> Go to-> Declaration of usages. Таким образом, к примеру, можно узнать, что наш AbilityBot на самом деле наследуется от стандартного TelegramLongPollingBot. Только в нем используются лямбды, что существенно сокращает код. В следующей (финальной) части будет развитие диалога и деплой на Heroku.
Комментарии (17)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Vitaliy_JV Уровень 16
12 февраля 2023
Очень классно и конструктивно! Я уже запустил "полуживой" бот по этому руководству. Круто! Очень хочется следующую часть!
JavaCodeR Уровень 1
29 августа 2022
Блин, где продолжение? Самой важной части нету, я уже столько гуглю как построить систему диалогов в боте, ничего не нахожу
Alexey Finik Уровень 14
17 мая 2022
MessageFactory.java import org.telegram.abilitybots.api.sender.MessageSender; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Message; import org.telegram.telegrambots.meta.api.objects.MessageEntity; import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import java.util.List; public class MessageFactory { private final MessageSender sender; //используется для отправки сообщений обратно пользователю SendMessage message; SendMessage message2; public MessageFactory(MessageSender sender) { this.sender = sender; } public void start (long chatId) { try { message = new SendMessage(String.valueOf(chatId), Constants.START_REPLY); sender.execute(message); message2 = new SendMessage(String.valueOf(chatId), Constants.CHOOSE_OPTION); message2.setReplyMarkup(KeyboardFactory.startButtons()); sender.execute(message2); } catch (TelegramApiException e) { e.printStackTrace(); } } }
Alexey Finik Уровень 14
17 мая 2022
KeyBoardFactory.java import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup; import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard; import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton; import java.util.ArrayList; import java.util.List; public class KeyboardFactory { public static ReplyKeyboard startButtons() { InlineKeyboardMarkup inlineKeyboard = new InlineKeyboardMarkup(); List<List<InlineKeyboardButton>> rowsInline = new ArrayList<>(); List<InlineKeyboardButton> rowInline = new ArrayList<>(); InlineKeyboardButton inlineKeyboardButton = new InlineKeyboardButton("DISCUSSION"); inlineKeyboardButton.setCallbackData(Constants.DISCUSSION); InlineKeyboardButton inlineKeyboardButton2 = new InlineKeyboardButton("SMALL TALK"); inlineKeyboardButton2.setCallbackData(Constants.SMALL_TALK); rowInline.add(inlineKeyboardButton); rowInline.add(inlineKeyboardButton2); rowsInline.add(rowInline); inlineKeyboard.setKeyboard(rowsInline); return inlineKeyboard; } }
Alexey Finik Уровень 14
17 мая 2022
Присоединяюсь к предыдущему комментатору частично. Вот пока довел бота до следующего состояния: TelegramBot.java import org.telegram.abilitybots.api.bot.AbilityBot; import org.telegram.abilitybots.api.objects.Ability; import org.telegram.abilitybots.api.objects.Locality; import org.telegram.abilitybots.api.objects.Privacy; import org.telegram.telegrambots.meta.api.objects.Update; import java.util.List; public class TelegramBot extends AbilityBot { public TelegramBot(){ this(Constants.BOT_TOKEN, Constants.BOT_USERNAME); } private TelegramBot(String botToken, String botUsername) { super(botToken, botUsername); //MessageFactory messageFactory = new MessageFactory(sender); } @Override public long creatorId() { return Constants.CREATOR_ID; } @Override public void onUpdatesReceived(List<Update> updates) { super.onUpdatesReceived(updates); } @Override public void onClosing() { super.onClosing(); } public Ability replyToStart() { return Ability .builder() .name("start") .info(Constants.START_DESCRIPTION) .locality(Locality.ALL) .privacy(Privacy.PUBLIC) .action(ctx -> new MessageFactory(sender).start(ctx.chatId())) .build(); } }
Oleg Viktorovich Уровень 41
22 февраля 2021
Очень ужасно все рассказано, нечего не получилось по этим 2м статьям, просто огрызки кода, переменные не инициализированны, типо догадывайтесь сами, нету финального кода по каждому классу как должно быть. Я не доволен.
Алексей К. Уровень 41
18 ноября 2020
Когда будет продолжение? Очень жду.
Александер Уровень 20
11 сентября 2020
Очень понравились статьи. Жду с нетерпением продолжения, особенно интересует деплой. Я до сих пор пишу небольшие вещи наподобие ботов для телеграмма, но запускаю их всегда под IDE. Вот как избавиться от этой зависимости и запускать готового бота под виндовсом или маком...? Не представляю...
Azazil47 Уровень 22
30 августа 2020
Здравствуйте! Прочел обе Ваши статьи, я пока на 20 уровне и знаний наверное у меня еще мало.(Ранее программированием не увлекался) Мне бы очень хотелось написать бота, но боюсь, что наверное у меня не хватит навыков? P.S. Очень жду продолжение Вашей работы
Alukard Уровень 37 Expert
25 августа 2020
Не знаю зачем я это прочел но выглядит круто!