JavaRush /Blog Jawa /Random-JV /Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot...
Whiskels
tingkat
Москва

Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot

Diterbitake ing grup
PART 1 Aloha! Ing artikel sadurunge, kita nggawe bot prasaja sing nampani acara apa wae. Kita wis nulis ewonan baris kode, lan wektune kanggo nambah fungsi sing luwih rumit ing bot kita. Dina iki kita bakal nyoba nulis bot sing prasaja supaya ing wektu luang kita bisa ngasah kawruh babagan Java Core sadurunge wawancara (nggumunake, aku ora nemokake bot sing bisa digunakake kaya iki). Kanggo nindakake iki, kita bakal nindakake ing ngisor iki:
  • nyambungake database Postgres eksternal menyang Heroku;
  • Ayo kita nulis skrip pisanan kita kanggo initialize lan populate database;
  • ayo nyambungake Spring Boot Data JPA kanggo nggarap database;
  • Kita ngetrapake macem-macem skenario prilaku bot.
Yen iki menarik kanggo sampeyan, lan sawise maca artikel sampeyan ora pengin mbuwang tomat bosok, banjur sijine lintang ing repositori sandi , Aku bakal pleased! Yen sampeyan duwe pitakonan, kita bakal ngrembug ing komentar. Iki sing bakal kita entuk ing pungkasan: Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 1Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 2Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 3<h2>Dadi, ayo!</h2><h3>Nggawe database ing Heroku</h3>Ayo miwiti nggawe database eksternal pisanan. Kanggo karya lokal, aku nyaranake mriksa metu pgAdmin . Nanging aku pengin sampeyan bakal dipandu dening kasunyatan sing ing mangsa ngarep sampeyan bakal masang bot kanggo Heroku supaya ora gumantung ing mesin lokal, lan kanggo iki, ayo kenalan karo layanan iki. tata cara:
  • ndhaftar ing Heroku ;
  • Bukak dashboard kita -> Anyar -> Gawe aplikasi anyar lan gawe aplikasi anyar;
  • Kita pindhah menyang aplikasi sing mentas digawe, kita wedi karo akeh tombol, nanging kita konsentrasi ing panel "Add-ons" - ing jejere ana tombol Konfigurasi Add-ons, kita klik;
  • Ketik "Heroku Postgres" menyang telusuran, pilih rencana "Hobby Dev - Gratis" -> Kirim Formulir Pesenan;
  • Bukak database sing mentas dipikolehi -> Setelan -> Deleng Kredensial. Tab iki bakal ngemot kunci kita kanggo ngakses database. Kita ngelingi lokasi - kita kudu nyambungake database, kaya DataSource ing IDEA.
<h3>Tambahake dependensi menyang pom.xml</h3> Minangka bagéan saka nggarap bot kita, kita bakal nambah dependensi ing ngisor iki menyang pom kita: Lombok, Spring Boot Data JPA, PostgreSQL. mandeg! Apa kabeh iki lan kenapa kita nambahake?
  • Lombok minangka perpustakaan thanks kanggo sing bakal nyuda jumlah kode sing beda-beda. Kanthi iku kita bisa kanthi otomatis nggawe konstruktor, setter, getter lan akeh liyane.
  • Spring Data JPA minangka kerangka kerja kanggo nggarap database (sanajan muni banget prasaja). Katrangan babagan kapabilitas Spring Data JPA bakal dadi pirang-pirang artikel, lan ketergantungan sing ditemtokake uga kalebu Hibernate lan liya-liyane, mula ayo ngliwati rincian kasebut lan coba nulis apa wae nggunakake Spring JPA saiki.
  • PostgreSQL - kita narik perpustakaan kanggo njaluk driver sing bakal bisa digunakake karo database kita.
Pom.xml kita wiwit katon kaya iki: Properties: Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 1Dependensi: Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 2Yen sampeyan ora maca artikel sadurunge, elinga yen kita nambah dependensi anyar kene, dadi iki dudu struktur pom.xml lengkap. Aja lali kanggo mbukak dependensi iki menyang proyek kita (contone, kanthi pindhah menyang Maven -> Reimport kabeh jendhela proyek Maven).<h3>Nyambungake database ing IDEA</h3>Yen sampeyan nggunakake IDEA Community Edition, sampeyan bisa aktifake tab DataSource kaya ing ngisor iki . Sawise nambahake plugin, kita kudu ngatur DataSource. Kanggo nindakake iki, pisanan ngaktifake tampilan plugin: View -> Tool Windows -> DB Browser. Ing jendhela sing mbukak, klik ing plus ijo (sambungan anyar) -> PostgreSQL. Ing kene kita butuh kredensial, sing wis kita deleng ing Heroku. Isi metu jendhela: Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 3Lan klik "Test Connection". Yen kabeh wis rampung kanthi bener, jendhela pop-up bakal katon sing nuduhake yen sambungan menyang database sukses. Simpen Sumber Data kita.<h3>Gawe tabel ing basis data</h3>Saiki ayo nggawe tabel sing bakal digunakake. Pisanan, ayo nginstal PostgreSQL . Sawise instalasi, gawe file initDB.sql ing folder src/main/resources:

DROP TABLE IF EXISTS java_quiz;
DROP TABLE IF EXISTS users;
CREATE SEQUENCE global_seq START WITH 100000;

CREATE TABLE users
(
    id         INTEGER PRIMARY KEY DEFAULT nextval('global_seq'),
    chat_id    INTEGER UNIQUE                NOT NULL,
    name       VARCHAR                       NOT NULL,
    score      INTEGER             DEFAULT 0 NOT NULL,
    high_score INTEGER             DEFAULT 0 NOT NULL,
    bot_state  VARCHAR                       NOT NULL
);

CREATE TABLE java_quiz
(
    id             INTEGER PRIMARY KEY DEFAULT nextval('global_seq'),
    question       VARCHAR NOT NULL,
    answer_correct VARCHAR NOT NULL,
    option1        VARCHAR NOT NULL,
    option2        VARCHAR NOT NULL,
    option3        VARCHAR NOT NULL
);
Apa sing ditindakake skrip kita? Rong baris pisanan mbusak tabel, yen ana, kanggo nggawe maneh. Baris katelu nggawe urutan sing bakal digunakake kanggo nggawe entri id unik ing database kita. Sabanjure kita nggawe rong tabel: kanggo pangguna lan kanggo pitakonan. Pangguna bakal duwe id unik, id obrolan telegram, jeneng, jumlah poin (saiki lan maksimal), uga status bot saiki. Pitakonan uga bakal duwe id unik, uga kolom sing tanggung jawab kanggo pilihan pitakonan lan jawaban kasebut. Kita bisa nglakokake skrip sing diasilake kanthi ngeklik-tengen lan milih "Execute SQL Script". Perhatian khusus kudu dibayar menyang item "antarmuka Cmd-Line" - ing kene kita butuh PostgreSQL sing anyar diinstal. Nalika ngatur lapangan iki, pilih "Antarmuka Cmd-Line Anyar" lan nemtokake path kanggo psql.exe. Akibaté, setelan kudu katon kaya iki: Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 4Kita nglakokaké script lan yen kita ora nggawe kesalahan ing ngendi wae, asil karya bakal kaya ing ngisor iki: Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 8<h3>Gawe model</h3>Saiki wektune kanggo bali nulis kode Jawa. Kanggo nyepetake artikel, aku bakal ngilangi katrangan babagan anotasi sing digunakake kanggo nulis kelas supaya sampeyan bisa akrab karo dheweke. Ayo nggawe paket model sing bakal duwe telung kelas:
  • AbstractBaseEntity minangka kelas sing nggambarake obyek apa wae sing bisa duwe id (kelas iki minangka penyederhanaan sing kuat babagan apa sing bisa sampeyan deleng ing magang):
    
    package com.whiskels.telegram.model;
    
    import lombok.Getter;
    import lombok.Setter;
    
    import javax.persistence.*;
    // Аннотация, которая говорит нам, что это суперкласс для всех Entity
    // https://vladmihalcea.com/how-to-inherit-properties-from-a-base-class-entity-using-mappedsuperclass-with-jpa-and-hibernate/
    @MappedSuperclass
    // http://stackoverflow.com/questions/594597/hibernate-annotations-which-is-better-field-or-property-access
    @Access(AccessType.FIELD)
    
    // Аннотации Lombok для автогенерации сеттеров и геттеров на все поля
    @Getter
    @Setter
    public abstract class AbstractBaseEntity {
    
    // Аннотации, описывающие механизм генерации id - разберитесь в documentации каждой!
        @Id
        @SequenceGenerator(name = "global_seq", sequenceName = "global_seq", allocationSize = 1, initialValue = START_SEQ)
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "global_seq")
    //  See https://hibernate.atlassian.net/browse/HHH-3718 and https://hibernate.atlassian.net/browse/HHH-12034
    //  Proxy initialization when accessing its identifier managed now by JPA_PROXY_COMPLIANCE setting
        protected Integer id;
    
        protected AbstractBaseEntity() {
        }
    }
  • Panganggo :
    
    package com.whiskels.telegram.model;
    
    import com.whiskels.telegram.bot.State;
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    import org.hibernate.annotations.BatchSize;
    
    import javax.persistence.*;
    import javax.validation.constraints.NotBlank;
    import javax.validation.constraints.NotNull;
    import java.util.Set;
    
    import static javax.persistence.FetchType.EAGER;
    
    @Entity
    @Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = "chat_id", name = "users_unique_chatid_idx")})
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public class User extends AbstractBaseEntity {
        @Column(name = "chat_id", unique = true, nullable = false)
        @NotNull
        private Integer chatId;
    
        @Column(name = "name", unique = true, nullable = false)
        @NotBlank
        private String name;
    
        @Column(name = "score", nullable = false)
        @NotNull
        private Integer score;
    
        @Column(name = "high_score", nullable = false)
        @NotNull
        private Integer highScore;
    
        @Column(name = "bot_state", nullable = false)
        @NotBlank
        private State botState;
    
    // Конструктор нужен для создания нового пользователя (а может и нет? :))
        public User(int chatId) {
            this.chatId = chatId;
            this.name = String.valueOf(chatId);
            this.score = 0;
            this.highScore = 0;
            this.botState = State.START;
        }
    }
    
  • Kelas pitakonan :
    
    package com.whiskels.telegram.model;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Table;
    import javax.validation.constraints.NotBlank;
    
    @Entity
    @Table(name = "java_quiz")
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public class Question extends AbstractBaseEntity {
        @Column(name = "question", nullable = false)
        @NotBlank
        private String question;
    
        @Column(name = "answer_correct", nullable = false)
        @NotBlank
        private String correctAnswer;
    
        @Column(name = "option2", nullable = false)
        @NotBlank
        private String optionOne;
    
        @Column(name = "option1", nullable = false)
        @NotBlank
        private String optionTwo;
    
        @Column(name = "option3", nullable = false)
        @NotBlank
        private String optionThree;
    
        @Override
        public String toString() {
            return "Question{" +
                    "question='" + question + '\'' +
                    ", correctAnswer='" + correctAnswer + '\'' +
                    ", optionOne='" + optionOne + '\'' +
                    ", optionTwo='" + optionTwo + '\'' +
                    ", optionThree='" + optionThree + '\'' +
                    '}';
        }
    }
<h3>Nggawe repositori</h3>Saiki ayo nulis repositori Spring Data Jpa. Kita nggawe paket repositori sing bakal duwe rong antarmuka : JpaUserRepository, JpaQuestionRepository. Dheweke bakal entuk warisan saka JpaRepository, antarmuka Data Spring sing ngidini kita nggawe sihir. Kanggo mangerteni karyane, aku nyaranake nonton video dening Evgeny Borisov . Kelas bakal cilik banget:
  • JpaUserRepository:
    
    package com.whiskels.telegram.repository;
    
    import com.whiskels.telegram.model.User;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.Optional;
    
    @Repository
    @Transactional(readOnly = true)
    public interface JpaUserRepository extends JpaRepository<user, integer=""> {
    // По названию метода Spring сам поймет, что мы хотим получить пользователя по переданному chatId
        Optional<user> getByChatId(int chatId);
    }
    </user></user,>
  • JpaQuestionRepository:
    
    package com.whiskels.telegram.repository;
    
    import com.whiskels.telegram.model.Question;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Query;
    
    @Repository
    @Transactional(readOnly = true)
    public interface JpaQuestionRepository extends JpaRepository<question, integer=""> {
    // А здесь мы написали SQL Query, которая будет выбирать 1 случайный вопрос из таблицы вопросов
        @Query(nativeQuery = true, value = "SELECT *  FROM java_quiz ORDER BY random() LIMIT 1")
        Question getRandomQuestion();
    }
    </question,>
<h3>Tambah fungsionalitas menyang bot</h3>Ing kelas Panganggo kita duwe lapangan kelas Negara sing durung digawe , sing bakal menehi katrangan babagan tahap nggarap bot pangguna saiki. Ayo nggawe ing paket /bot:

package com.whiskels.telegram.bot;

public enum State {
    NONE,
    START,
    ENTER_NAME,
    PLAYING_QUIZ,
}
Sabanjure, kita bakal nggawe paket bot / handler sing bakal ngumumake antarmuka handler:

package com.whiskels.telegram.bot.handler;

import com.whiskels.telegram.bot.State;
import com.whiskels.telegram.model.User;
import org.telegram.telegrambots.meta.api.methods.PartialBotApiMethod;

import java.io.Serializable;
import java.util.List;

public interface Handler {

// основной метод, который будет обрабатывать действия пользователя
    List<partialbotapimethod<? extends="" serializable="">> handle(User user, String message);
// метод, который позволяет узнать, можем ли мы обработать текущий State у пользователя
    State operatedBotState();
// метод, который позволяет узнать, Howие команды CallBackQuery мы можем обработать в этом классе
    List<string> operatedCallBackQuery();
}

</string></partialbotapimethod<?>
Kita bakal nggawe panangan mengko, nanging saiki ayo utusan proses acara menyang kelas UpdateReceiver anyar , sing bakal digawe ing root paket bot: ATTENTION! Ing kene lan luwih bakal ana cara sing ditampilake minangka List> handle(args); Ing kasunyatan, padha katon kaya iki, nanging pemformat kode nyuwil:Nggawe bot telegram nggunakake Spring Boot Pt.2: Quiz Bot - 6

package com.whiskels.telegram.bot;

import com.whiskels.telegram.bot.handler.Handler;
import com.whiskels.telegram.model.User;
import com.whiskels.telegram.repository.JpaUserRepository;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.methods.PartialBotApiMethod;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

@Component
public class UpdateReceiver {
    // Храним доступные хендлеры в списке (подсмотрел у Miroha)
    private final List<handler> handlers;
    // Имеем доступ в базу пользователей
    private final JpaUserRepository userRepository;

    public UpdateReceiver(List<handler> handlers, JpaUserRepository userRepository) {
        this.handlers = handlers;
        this.userRepository = userRepository;
    }

    // Обрабатываем полученный Update
    public List<partialbotapimethod<? extends="" serializable="">> handle(Update update) {
        // try-catch, чтобы при несуществующей команде просто возвращать пустой список
        try {
            // Проверяем, если Update - сообщение с текстом
            if (isMessageWithText(update)) {
                // Получаем Message из Update
                final Message message = update.getMessage();
                // Получаем айди чата с пользователем
                final int chatId = message.getFrom().getId();
                
                // Просим у репозитория пользователя. Если такого пользователя нет - создаем нового и возвращаем его.
                // Как раз на случай нового пользователя мы и сделали конструктор с одним параметром в классе User
                final User user = userRepository.getByChatId(chatId)
                        .orElseGet(() -> userRepository.save(new User(chatId)));
                // Ищем нужный обработчик и возвращаем результат его работы
                return getHandlerByState(user.getBotState()).handle(user, message.getText());
                
            } else if (update.hasCallbackQuery()) {
                final CallbackQuery callbackQuery = update.getCallbackQuery();
                final int chatId = callbackQuery.getFrom().getId();
                final User user = userRepository.getByChatId(chatId)
                        .orElseGet(() -> userRepository.save(new User(chatId)));

                return getHandlerByCallBackQuery(callbackQuery.getData()).handle(user, callbackQuery.getData());
            }

            throw new UnsupportedOperationException();
        } catch (UnsupportedOperationException e) {
            return Collections.emptyList();
        }
    }

    private Handler getHandlerByState(State state) {
        return handlers.stream()
                .filter(h -> h.operatedBotState() != null)
                .filter(h -> h.operatedBotState().equals(state))
                .findAny()
                .orElseThrow(UnsupportedOperationException::new);
    }

    private Handler getHandlerByCallBackQuery(String query) {
        return handlers.stream()
                .filter(h -> h.operatedCallBackQuery().stream()
                        .anyMatch(query::startsWith))
                .findAny()
                .orElseThrow(UnsupportedOperationException::new);
    }

    private boolean isMessageWithText(Update update) {
        return !update.hasCallbackQuery() && update.hasMessage() && update.getMessage().hasText();
    }
}

</partialbotapimethod<?></handler></handler>
Lan kita utusan pangolahan ing kelas Bot:

package com.whiskels.telegram.bot;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.PartialBotApiMethod;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

import java.io.Serializable;
import java.util.List;

@Slf4j
@Component
public class Bot extends TelegramLongPollingBot {
    @Value("${bot.name}")
    @Getter
    private String botUsername;

    @Value("${bot.token}")
    @Getter
    private String botToken;

    private final UpdateReceiver updateReceiver;

    public Bot(UpdateReceiver updateReceiver) {
        this.updateReceiver = updateReceiver;
    }

    @Override
    public void onUpdateReceived(Update update) {
        List<partialbotapimethod<? extends="" serializable="">> messagesToSend = updateReceiver.handle(update);

        if (messagesToSend != null && !messagesToSend.isEmpty()) {
            messagesToSend.forEach(response -> {
                if (response instanceof SendMessage) {
                    executeWithExceptionCheck((SendMessage) response);
                }
            });
        }
    }

    public void executeWithExceptionCheck(SendMessage sendMessage) {
        try {
            execute(sendMessage);
        } catch (TelegramApiException e) {
            log.error("oops");
        }
    }
}

</partialbotapimethod<?>
Saiki bot kita delegasi pangolahan acara menyang kelas UpdateReceiver , nanging kita durung duwe panangan. Ayo padha nggawe! DISCLAIMER! Aku pancene pengin nuduhake kemungkinan nulis bot kasebut, supaya kode luwih lanjut (kaya ing prinsip kode UpdateReceiver) bisa uga refactored nggunakake macem-macem pola. Nanging kita sinau lan tujuan kita yaiku bot sing minimal, dadi minangka tugas peer liyane, sampeyan bisa refactor kabeh sing sampeyan deleng :) Gawe paket utilitas, lan ing kana - kelas TelegramUtil :

package com.whiskels.telegram.util;

import com.whiskels.telegram.model.User;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;

public class TelegramUtil {
    public static SendMessage createMessageTemplate(User user) {
        return createMessageTemplate(String.valueOf(user.getChatId()));
    }

    // Создаем шаблон SendMessage с включенным Markdown
    public static SendMessage createMessageTemplate(String chatId) {
        return new SendMessage()
                .setChatId(chatId)
                .enableMarkdown(true);
    }

    // Создаем кнопку
    public static InlineKeyboardButton createInlineKeyboardButton(String text, String command) {
        return new InlineKeyboardButton()
                .setText(text)
                .setCallbackData(command);
    }
}
Kita bakal nulis papat pawang: HelpHandler, QuizHandler, RegistrationHandler, StartHandler. StartHandler:

package com.whiskels.telegram.bot.handler;

import com.whiskels.telegram.bot.State;
import com.whiskels.telegram.model.User;
import com.whiskels.telegram.repository.JpaUserRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.methods.PartialBotApiMethod;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

import static com.whiskels.telegram.util.TelegramUtil.createMessageTemplate;

@Component
public class StartHandler implements Handler {
    @Value("${bot.name}")
    private String botUsername;

    private final JpaUserRepository userRepository;

    public StartHandler(JpaUserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public List<partialbotapimethod<? extends="" serializable="">> handle(User user, String message) {
        // Приветствуем пользователя
        SendMessage welcomeMessage = createMessageTemplate(user)
                .setText(String.format(
                        "Hola! I'm *%s*%nI am here to help you learn Java", botUsername
                ));
        // Просим назваться
        SendMessage registrationMessage = createMessageTemplate(user)
                .setText("In order to start our journey tell me your name");
        // Меняем пользователю статус на - "ожидание ввода имени"
        user.setBotState(State.ENTER_NAME);
        userRepository.save(user);

        return List.of(welcomeMessage, registrationMessage);
    }

    @Override
    public State operatedBotState() {
        return State.START;
    }

    @Override
    public List<string> operatedCallBackQuery() {
        return Collections.emptyList();
    }
}

</string></partialbotapimethod<?>
Petugas Pendaftaran:

package com.whiskels.telegram.bot.handler;

import com.whiskels.telegram.bot.State;
import com.whiskels.telegram.model.User;
import com.whiskels.telegram.repository.JpaUserRepository;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.methods.PartialBotApiMethod;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;

import java.io.Serializable;
import java.util.List;

import static com.whiskels.telegram.bot.handler.QuizHandler.QUIZ_START;
import static com.whiskels.telegram.util.TelegramUtil.createInlineKeyboardButton;
import static com.whiskels.telegram.util.TelegramUtil.createMessageTemplate;

@Component
public class RegistrationHandler implements Handler {
    //Храним поддерживаемые CallBackQuery в виде констант
    public static final String NAME_ACCEPT = "/enter_name_accept";
    public static final String NAME_CHANGE = "/enter_name";
    public static final String NAME_CHANGE_CANCEL = "/enter_name_cancel";

    private final JpaUserRepository userRepository;

    public RegistrationHandler(JpaUserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public List<partialbotapimethod<? extends="" serializable="">> handle(User user, String message) {
        // Проверяем тип полученного события
        if (message.equalsIgnoreCase(NAME_ACCEPT) || message.equalsIgnoreCase(NAME_CHANGE_CANCEL)) {
            return accept(user);
        } else if (message.equalsIgnoreCase(NAME_CHANGE)) {
            return changeName(user);
        }
        return checkName(user, message);

    }

    private List<partialbotapimethod<? extends="" serializable="">> accept(User user) {
        // Если пользователь принял Name - меняем статус и сохраняем
        user.setBotState(State.NONE);
        userRepository.save(user);

        // Создаем кнопку для начала игры
        InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();

        List<inlinekeyboardbutton> inlineKeyboardButtonsRowOne = List.of(
                createInlineKeyboardButton("Start quiz", QUIZ_START));

        inlineKeyboardMarkup.setKeyboard(List.of(inlineKeyboardButtonsRowOne));

        return List.of(createMessageTemplate(user).setText(String.format(
                "Your name is saved as: %s", user.getName()))
                .setReplyMarkup(inlineKeyboardMarkup));
    }

    private List<partialbotapimethod<? extends="" serializable="">> checkName(User user, String message) {
        // При проверке имени мы превентивно сохраняем пользователю новое Name в базе 
        // идея для рефакторинга - добавить временное хранение имени
        user.setName(message);
        userRepository.save(user);

        // Doing кнопку для применения изменений
        InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();

        List<inlinekeyboardbutton> inlineKeyboardButtonsRowOne = List.of(
                createInlineKeyboardButton("Accept", NAME_ACCEPT));

        inlineKeyboardMarkup.setKeyboard(List.of(inlineKeyboardButtonsRowOne));

        return List.of(createMessageTemplate(user)
                .setText(String.format("You have entered: %s%nIf this is correct - press the button", user.getName()))
                .setReplyMarkup(inlineKeyboardMarkup));
    }
    
    private List<partialbotapimethod<? extends="" serializable="">> changeName(User user) {
        // При requestе изменения имени мы меняем State
        user.setBotState(State.ENTER_NAME);
        userRepository.save(user);

        // Создаем кнопку для отмены операции
        InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();

        List<inlinekeyboardbutton> inlineKeyboardButtonsRowOne = List.of(
                createInlineKeyboardButton("Cancel", NAME_CHANGE_CANCEL));

        inlineKeyboardMarkup.setKeyboard(List.of(inlineKeyboardButtonsRowOne));

        return List.of(createMessageTemplate(user).setText(String.format(
                "Your current name is: %s%nEnter new name or press the button to continue", user.getName()))
                .setReplyMarkup(inlineKeyboardMarkup));
    }

    @Override
    public State operatedBotState() {
        return State.ENTER_NAME;
    }

    @Override
    public List<string> operatedCallBackQuery() {
        return List.of(NAME_ACCEPT, NAME_CHANGE, NAME_CHANGE_CANCEL);
    }
}

</string></inlinekeyboardbutton></partialbotapimethod<?></inlinekeyboardbutton></partialbotapimethod<?></inlinekeyboardbutton></partialbotapimethod<?></partialbotapimethod<?>
Penanganan Bantuan:

package com.whiskels.telegram.bot.handler;

import com.whiskels.telegram.bot.State;
import com.whiskels.telegram.model.User;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.methods.PartialBotApiMethod;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.whiskels.telegram.bot.handler.RegistrationHandler.NAME_CHANGE;
import static com.whiskels.telegram.util.TelegramUtil.createInlineKeyboardButton;
import static com.whiskels.telegram.util.TelegramUtil.createMessageTemplate;

@Component
public class HelpHandler implements Handler {

    @Override
    public List<partialbotapimethod<? extends="" serializable="">> handle(User user, String message) {
        // Создаем кнопку для смены имени
        InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();

        List<inlinekeyboardbutton> inlineKeyboardButtonsRowOne = List.of(
                createInlineKeyboardButton("Change name", NAME_CHANGE));

        inlineKeyboardMarkup.setKeyboard(List.of(inlineKeyboardButtonsRowOne));

        return List.of(createMessageTemplate(user).setText(String.format("" +
                "You've asked for help %s? Here it comes!", user.getName()))
        .setReplyMarkup(inlineKeyboardMarkup));

    }

    @Override
    public State operatedBotState() {
        return State.NONE;
    }

    @Override
    public List<string> operatedCallBackQuery() {
        return Collections.emptyList();
    }
}

</string></inlinekeyboardbutton></partialbotapimethod<?>
QuizHandler (paling awon
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION