JavaRush /Blogue Java /Random-PT /Bot do Telegram - lembrete via webHook em Java ou diga nã...
Vladimir Popov
Nível 41

Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google! Parte 1

Publicado no grupo Random-PT
Meu nome é Vladimir. Tenho 43 anos. E se você, leitor, tem mais de 40 anos, então sim, depois dos 40 você pode se tornar um programador se quiser. Meu trabalho não tem nada a ver com programação, sou gerente de projetos na área de automação e tudo mais. Mas estou planejando mudar de profissão. Ah, essas novas tendências... mudam seu ramo de atividade a cada 5-7 anos. Então : O projeto acabou sendo bastante grande, então alguns pontos terão que ser omitidos ou comentados brevemente, na esperança de que o leitor saiba como pesquisar no Google. A Internet está repleta de publicações de bots de telegramas que trabalham com base no princípio da pesquisa longa. E há muito poucos que funcionam com base no princípio do Webhook. O que é isso? Sondagem longa - isso significa que seu próprio aplicativo pesquisará o servidor de telegramas em busca de mensagens em uma determinada frequência, lentamente. Webhook - significa que o servidor de telegramas redirecionará instantaneamente as mensagens para o servidor que você especificar. No nosso caso, cortesia do serviço Heroku. Você pode, claro, ler mais sobre tudo isso e sobre o bot em geral no site do Telegram - https://tlgrm.ru/docs/bots/api A interface do bot é assim: Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 1 Considero este aplicativo justamente como um treinamento projeto porque, ao escrever, aprendi mais informações com esse bot do que durante o treinamento. Você quer aprender a programar? Comece a escrever código!!! Mas! Não haverá instruções detalhadas sobre como fazer upload do aplicativo para o github ou como criar um banco de dados. Há muito disso na Internet e é descrito detalhadamente; além disso, será uma leitura muito longa. O aplicativo funcionará da seguinte forma: Insira uma descrição do evento, insira a data e hora do evento, selecione a frequência (você pode fazer uma vez, pode ter um lembrete todos os dias em um determinado horário, pode ter uma vez por mês em um determinado horário ou uma vez por ano). Variações de notificações podem ser adicionadas infinitamente; tenho muitas ideias. Em seguida, os dados inseridos são salvos no banco de dados (também implantado gratuitamente no Heroku, 10.000 linhas são gratuitas). Então, uma vez no início do dia às 0:00, horário do servidor, o Spring recupera do banco de dados todos os eventos com base nos critérios que deve disparar naquele dia e enviá-los para execução no horário especificado. ATENÇÃO!!! ESTA PARTE DO PROGRAMA É EXPERIMENTAL! HÁ UMA IMPLEMENTAÇÃO MAIS SIMPLES E VERDADEIRA! ISSO FOI FEITO ESPECIFICAMENTE PARA VER COMO FUNCIONA A AULA DO TEMPO! Você pode tocar no bot funcional com suas próprias mãos digitando @calendar_event_bot no carrinho, mas não conte com isso, porque ainda estou zombando dele. código - https://github.com/papoff8295/webHookBotForHabr Basicamente, para lançar o seu próprio você precisa seguir os seguintes passos: • Cadastre-se no @BotFather , não é difícil, obtenha um token e um nome • Bifurque o projeto no github • Cadastre-se no Heroku, crie um aplicativo (faremos isso passo a passo), implante a partir do seu repositório. • Crie um banco de dados no Heroku • Substitua os campos correspondentes no repositório pelos seus próprios (token, nome das tabelas nas entidades, webHookPath, nome de usuário, senha e caminho do banco de dados, tudo isso será analisado) • Faça o Heroku funcionar 24/ 7 usando https://uptimerobot.com/ A estrutura final do projeto é a seguinte: Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 2 Vamos começar criando um projeto em https://start.spring.io Selecione as dependências que precisamos conforme mostrado na figura: Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 3Selecione as nossas nome para o projeto e clique em Gerar . Em seguida, você será solicitado a salvar o projeto em seu disco. Resta apenas abrir o arquivo pom.xml em seu ambiente de desenvolvimento. Há um projeto finalizado à sua frente. Agora só precisamos adicionar nossa biblioteca principal. Usei a biblioteca de https://github.com/rubenlagus/TelegramBots Em geral, você pode ficar confuso e passar sem ela. Afinal, o objetivo do trabalho é concatenar uma URL como esta: https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io Vamos dar uma olhada um pouco : https://api.telegram.org – servidor de telegramas. bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/ - após a palavra bot está um token secreto que você recebe ao registrar um bot. setWebhook?url=https://e9c658b548aa.ngrok.io – nome do método e seus parâmetros. Neste caso, instalamos o seu servidor webhook, todas as mensagens serão enviadas para ele. Em geral, decidi que o projeto não era muito pequeno para publicação, mas com implementação manual seria geralmente ilegível. Então, a aparência final do arquivo pom é:
<!--?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelversion>4.0.0</modelversion>
   <parent>
      <groupid>org.springframework.boot</groupid>
      <artifactid>spring-boot-starter-parent</artifactid>
      <version>2.5.0</version>
      <relativepath> <!-- lookup parent from repository -->
   </relativepath></parent>
   <groupid>ru.popov</groupid>
   <artifactid>telegrambot</artifactid>
   <version>0.0.1-SNAPSHOT</version>
   <name>telegrambot</name>
   <description>Demo project for Spring Boot</description>
   <properties>
      <java.version>1.8</java.version>
   </properties>
   <dependencies>
      <dependency>
         <groupid>org.springframework.boot</groupid>
         <artifactid>spring-boot-starter-web</artifactid>
      </dependency>

      <dependency>
         <groupid>org.springframework.boot</groupid>
         <artifactid>spring-boot-starter-data-jpa</artifactid>
      </dependency>

      <dependency>
         <groupid>org.springframework.boot</groupid>
         <artifactid>spring-boot-starter-test</artifactid>
         <scope>test</scope>
      </dependency>

      <!-- https://mvnrepository.com/artifact/org.telegram/telegrambots-spring-boot-starter -->
      <dependency>
         <groupid>org.telegram</groupid>
         <artifactid>telegrambots-spring-boot-starter</artifactid>
         <version>5.2.0</version>
      </dependency>

      <dependency>
         <groupid>org.projectlombok</groupid>
         <artifactid>lombok</artifactid>
         <version>1.18.16</version>
      </dependency>

      <dependency>
         <groupid>org.postgresql</groupid>
         <artifactid>postgresql</artifactid>
         <scope>runtime</scope>
      </dependency>

   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-maven-plugin</artifactid>
         </plugin>
      </plugins>
   </build>

</project>
Tudo está pronto para escrever nosso bot. Vamos criar a classe TelegramBot . Não vou escrever os nomes das pastas, você pode vê-las na estrutura do projeto acima.
@Getter
@Setter
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TelegramBot extends SpringWebhookBot {
    String botPath;
    String botUsername;
    String botToken;

    private TelegramFacade telegramFacade;

    public TelegramBot(TelegramFacade telegramFacade, DefaultBotOptions options, SetWebhook setWebhook) {
        super(options, setWebhook);
        this.telegramFacade = telegramFacade;
    }
    public TelegramBot(TelegramFacade telegramFacade, SetWebhook setWebhook) {
        super(setWebhook);
        this.telegramFacade = telegramFacade;
    }

    @Override
    public BotApiMethod<!--?--> onWebhookUpdateReceived(Update update) {
        return telegramFacade.handleUpdate(update);
    }
}
A classe estende SpringWebhookBot de nossa biblioteca de telegramas e só precisamos implementar um método, onWebhookUpdateReceived . Ele aceita JSON analisado como um objeto Update e retorna o que o servidor de telegrama deseja “ouvir” de nós. Aqui temos anotações da biblioteca Lombok . Lombok – facilitando a vida de um programador!! Bem, isso é. não precisamos redefinir getters e setters, o Lombok faz isso por nós e também não precisamos escrever um identificador de nível de acesso. Não vale mais a pena escrever que isso é feito pelas anotações @Getter, @Setter, @FieldDefaults O campo botPath significa nosso endereço de webhook, que receberemos no Heroku posteriormente. O campo botUsername significa o nome do nosso bot, que receberemos ao cadastrar nosso bot no Telegram. O campo botToken é o nosso token, que receberemos ao cadastrar nosso bot no Telegram. O campo telegramFacade é a nossa classe onde ocorrerá o processamento das mensagens, voltaremos a ele um pouco mais tarde, deixe-o vermelho por enquanto. Agora é hora de entrarmos em contato com @BotFather e obter os cobiçados botToken e botUsername. Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 4Basta escrever para ele no telegrama e ele lhe contará tudo. Escrevemos os dados em nosso application.properties, no final ficará assim:
server#server.port=5000

telegrambot.userName=@calendar_event_bot
telegrambot.botToken=1731265488:AAFDjUSk3vu5SFfgdfh556gOOFmuml7SqEjwrmnEF5Ak
#telegrambot.webHookPath=https://telegrambotsimpl.herokuapp.com/
telegrambot.webHookPath=https://f5d6beeb7b93.ngrok.io


telegrambot.adminId=39376213

eventservice.period =600000

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/telegramUsers
spring.datasource.username=postgres
spring.datasource.password=password

#spring.datasource.url=jdbc:postgresql:ec2-54-247-158-179.eu-west-1.compute.amazonaws.com:5432/d2um126le5notq?ssl=true&sslmode=require&sslfactory=org.postgresql.ssl.NonValidatingFactory
#spring.datasource.username=ulmbeywyhvsxa
#spring.datasource.password=4c7646c69dbbgeacb98fa96e8daa6d9b1bl4894e67f3f3ddd6a27fe7b0537fd
Esta configuração está configurada para funcionar com um banco de dados local, posteriormente faremos as alterações necessárias. Substitua botToken e nome de usuário pelos seus. Não é bom usar dados de application.properties diretamente no aplicativo. Vamos criar um bean ou uma classe wrapper a partir desses dados.
@Component
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)

public class TelegramBotConfig {
    @Value("${telegrambot.webHookPath}")
    String webHookPath;
    @Value("${telegrambot.userName}")
    String userName;
    @Value("${telegrambot.botToken}")
    String botToken;
Aqui, a anotação @Value inicializa as linhas correspondentes do arquivo application.properties, que o Spring conhece por padrão. E a anotação @Component cria um Bean para nós quando o aplicativo é iniciado. Vamos agora passar para o arquivo de configuração do Spring:
@Configuration
public class AppConfig {
    private final TelegramBotConfig botConfig;

    public AppConfig(TelegramBotConfig botConfig) {
        this.botConfig = botConfig;
    }

    @Bean
    public SetWebhook setWebhookInstance() {
        return SetWebhook.builder().url(botConfig.getWebHookPath()).build();
    }

    @Bean
    public TelegramBot springWebhookBot(SetWebhook setWebhook, TelegramFacade telegramFacade) {
        TelegramBot bot = new TelegramBot(telegramFacade, setWebhook);
        bot.setBotToken(botConfig.getBotToken());
        bot.setBotUsername(botConfig.getUserName());
        bot.setBotPath(botConfig.getWebHookPath());

        return bot;
    }
}
Não há mágica aqui; na inicialização, o Spring cria objetos SetWebhook e TelegramBot para nós. Vamos agora criar pontos de entrada para nossas mensagens:
@RestController
public class WebhookController {

    private final TelegramBot telegramBot;

    public WebhookController(TelegramBot telegramBot) {
        this.telegramBot = telegramBot;
    }

// point for message
    @PostMapping("/")
    public BotApiMethod<!--?--> onUpdateReceived(@RequestBody Update update) {
        return telegramBot.onWebhookUpdateReceived(update);
    }

    @GetMapping
    public ResponseEntity get() {
        return ResponseEntity.ok().build();
    }
}
O servidor Telegram envia mensagens no formato JSON para o endereço de webhook cadastrado através do método POST, nosso controlador as recebe e as transmite para a biblioteca de telegramas na forma de um objeto Update. Eu fiz o método get assim) Agora só precisamos implementar alguma lógica para processar mensagens e respostas na classe TelegramFacade , darei seu código curto para que você possa iniciar o aplicativo e depois seguir seu próprio caminho ou mudar para implantar no Heroku, então será a versão completa:
@Component
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TelegramFacade {

    public BotApiMethod<!--?--> handleUpdate(Update update) {

        if (update.hasCallbackQuery()) {
            CallbackQuery callbackQuery = update.getCallbackQuery();
            return null;
        } else {

            Message message = update.getMessage();
            SendMessage sendMessage = new SendMessage();
            sendMessage.setChatId(String.valueOf(message.getChatId()));
            if (message.hasText()) {
                sendMessage.setText("Hello world");
                return sendMessage;
            }
        }
        return null;
    }

}
Este método responderá a qualquer mensagem Olá, mundo! Para lançar nosso aplicativo, só precisamos ter certeza de que podemos testá-lo diretamente do IDEA. Para fazer isso, precisamos baixar o utilitário ngrok. https://ngrok.com/download Este utilitário é uma linha de comando que nos fornece um endereço temporário por 2 horas e redireciona todas as mensagens para a porta especificada do servidor local. Lançamos e escrevemos ngrok http 5000 na linha (ou você pode especificar sua porta): Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 5Obtemos o resultado: Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 6https://23b1a54ccbbd.ngrok.io - este é o nosso endereço de webhook. Como você deve ter notado no arquivo de propriedades que escrevemos server.port=5000 ao iniciar o servidor tomcat, ele ocupará a porta 5000, certifique-se de que esses campos sejam iguais. Além disso, não esqueça que o endereço é fornecido por duas horas. Na linha de comando, isso é monitorado pelo campo Session Expires. Quando o tempo acabar, você precisará pegar o endereço novamente e passar pelo procedimento de cadastramento no telegrama. Agora pegamos a linha https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io E com movimentos hábeis das mãos substituímos o token pelo nosso, o url pelo nosso, cole a linha resultante no navegador e clique em Enter. Você deverá obter o seguinte resultado: Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 7Pronto, agora você pode executar a aplicação: Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 8Verifique se sua classe com o método principal ficou assim:
@SpringBootApplication
public class TelegramBotApplication {

   public static void main(String[] args) {
      SpringApplication.run(TelegramBotApplication.class, args);
   }
}
Se você fez tudo corretamente, agora seu bot responderá a qualquer mensagem com a frase “ Olá mundo” . Então você pode seguir seu próprio caminho. Se você está comigo e tem interesse em seguir todas as etapas, então vamos começar a escrever entidades para o banco de dados e criar o próprio banco de dados. Vamos começar com o banco de dados: Como já disse, presumo que você já tenha habilidades mínimas para trabalhar com banco de dados e tenha um banco de dados postgreSQL local instalado , caso contrário, siga este caminho. https://www.postgresql.org/download/ No arquivo application.properties, substitua o login e a senha do banco de dados pelos seus. No IDEA existe uma aba de banco de dados à direita, nela você precisa clicar em +/Data source/PostgreSQL . Como resultado, ao clicar em Test Connection você deverá obter um resultado satisfatório: Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 9Agora você pode criar um banco de dados com tabelas diretamente do ambiente de desenvolvimento, ou pode usar a interface web pgadmin , que está localizada no menu iniciar. Precisaremos de 3 tabelas:
CREATE TABLE users
(
    id               INTEGER PRIMARY KEY UNIQUE NOT NULL,
    name             VARCHAR,
    time_zone        INTEGER DEFAULT 0,
    on_off           BOOLEAN DEFAULT true
);

CREATE TABLE user_events
(
    user_id INTEGER ,
    time timestamp ,
    description varchar ,
    event_id serial,
    event_freq varchar default 'TIME',
    FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);

CREATE TABLE event_cash
(
    time timestamp ,
    description varchar ,
    user_id INTEGER ,
    id serial
);
Recomendo criar este script separadamente, precisaremos dele para criar um banco de dados no Heroku, para não escrevê-lo duas vezes. Vamos caminhar um pouco. Direi imediatamente que só precisamos da tabela event_cash para trabalhar com o Heroku devido às suas especificidades e ao meu desejo insaciável de trabalhar com a classe Time ; não será útil na versão local. Na tabela de usuários registraremos o id da conta do usuário do telegrama, seu nome, que pode não existir, será calculado o fuso horário do usuário para o correto envio de notificações, bem como o status ligado/desligado do envio de notificações. Registraremos o id do usuário, horário da notificação, descrição na tabela user_events , geraremos automaticamente um id para o evento e definiremos a frequência das notificações. A tabela event_cash registrará a notificação antes de ela ser enviada e, se enviada, removê-la da tabela. As tabelas estão prontas, vamos agora adicionar as entidades.
@Entity
@Table(name = "user_events")
@Getter
@Setter
public class Event {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column( name = "event_id", columnDefinition = "serial")
    private int eventId;

    @Column(name = "time")
    @NotNull(message = "Need date!")
    private Date date;

    @Column(name = "description")
    @Size(min = 4, max = 200, message = "Description must be between 0 and 200 chars!")
    private String description;

    @Column(name = "event_freq", columnDefinition = "TIME")
    @Enumerated(EnumType.STRING)
    private EventFreq freq;

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="user_id")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private User user;

    public Event() {
    }

    public Event(int eventId,
                 @NotNull(message = "Need date!") Date date,
                 @Size(min = 4, max = 200, message = "Description must be between 0 and 200 chars!")
                         String description,
                 EventFreq freq, User user) {
        this.eventId = eventId;
        this.date = date;
        this.description = description;
        this.freq = freq;
        this.user = user;
    }
}
@Entity
@Table(name = "users")
@Getter
@Setter
public class User {

    @Id
    @Column(name = "id")
    private long id;

    @Column(name = "name")
    private String name;

    @Column(name = "time_zone", columnDefinition = "default 0")
    //sets the broadcast time of events for your time zone
    private int timeZone;

    @OneToMany(mappedBy="user")
    private List<event> events;

    @Column(name = "on_off")
    // on/off send event
    private boolean on;

    public User() {
    }
}

</event>
@Entity
@Table(name = "event_cash")
@Getter
@Setter
//serves to save unhandled events after rebooting heroku
public class EventCashEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column( name = "id", columnDefinition = "serial")
    private long id;

    @Column(name = "time")
    private Date date;

    @Column(name = "description")
    private String description;

    @Column(name = "user_id")
    private long userId;

    public EventCashEntity() {
    }

    public static EventCashEntity eventTo(Date date, String description, long userId) {
        EventCashEntity eventCashEntity = new EventCashEntity();
        eventCashEntity.setDate(date);
        eventCashEntity.setDescription(description);
        eventCashEntity.setUserId(userId);
        return eventCashEntity;
    }
}
Vamos repassar um pouco os pontos principais. @Entity – marca a classe para nosso dada jpa que esta classe é uma entidade para o banco de dados, ou seja, ao recuperar dados do banco de dados, eles nos serão apresentados na forma de um objeto Event, User e EventCashEntity. @Table – dizemos o nome da nossa tabela no banco de dados. Para garantir que o nome da tabela não esteja sublinhado em vermelho, precisamos concordar no IDEA com a opção de correção de erros proposta e clicar em Atribuir fontes de dados. E selecione nossa base lá. @id e @GeneratedValue - usados ​​pelo Spring para criar um banco de dados se ele ainda não existir. @Column é usado para indicar o nome dos campos na tabela caso eles não correspondam, mas as regras de um bom código recomendam que você sempre escreva isso. Atitude OneToMany - recomendo gastar tempo e descobrir o que é aqui https://en.wikibooks.org/wiki/Java_Persistence Não consigo explicar com mais clareza, apenas acredite em mim. Deixe-me apenas dizer que neste caso a anotação @OneToMany diz que um usuário pode ter muitos eventos, e eles nos serão fornecidos na forma de uma lista. Agora precisamos obter os dados das tabelas. Na biblioteca SRING DATA JPA tudo já está escrito para nós, só precisamos criar uma interface para cada tabela e estendê-la do JpaRepository.
public interface EventRepository extends JpaRepository<event, long=""> {
    Event findByEventId(long id);
}
public interface UserRepository extends JpaRepository<user, long=""> {

    User findById(long id);
}
public interface EventCashRepository extends JpaRepository<eventcashentity, long=""> {
    EventCashEntity findById(long id);
}

</eventcashentity,></user,></event,>
A principal lógica de trabalho com o banco de dados é transferida para um serviço, o chamado Data Access Object (DAO):
@Service
public class UserDAO {

    private final UserRepository userRepository;

    @Autowired
    public UserDAO(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User findByUserId(long id) {
        return userRepository.findById(id);
    }

    public List<user> findAllUsers() {
        return userRepository.findAll();
    }

    public void removeUser(User user) {
        userRepository.delete(user);
    }


    public void save(User user) {
        userRepository.save(user);
    }

    public boolean isExist(long id) {
        User user = findByUserId(id);
        return user != null;
    }
}
@Service
public class EventDAO {

    private final UserRepository userRepository;
    private final EventRepository eventRepository;

    @Autowired
    public EventDAO(UserRepository userRepository, EventRepository eventRepository) {
        this.userRepository = userRepository;
        this.eventRepository = eventRepository;
    }

    public List<event> findByUserId(long userId) {
        User user = userRepository.findById(userId);
        return user.getEvents();
    }
    public List<event> findAllEvent() {
       return eventRepository.findAll();
    }

    public Event findByEventId(long eventId) {
        return eventRepository.findByEventId(eventId);
    }

    public void remove(Event event) {
        eventRepository.delete(event);
    }

    public void save(Event event) {
        eventRepository.save(event);
    }
}

</event></event></user>
@Service
//handles events not dispatched after reboot heroku
public class EventCashDAO {

    private EventCashRepository eventCashRepository;

    @Autowired
    public void setEventCashRepository(EventCashRepository eventCashRepository) {
        this.eventCashRepository = eventCashRepository;
    }

    public List<eventcashentity> findAllEventCash() {
        return eventCashRepository.findAll();
    }

    public void save(EventCashEntity eventCashEntity) {
        eventCashRepository.save(eventCashEntity);
    }

    public void delete(long id) {
        eventCashRepository.deleteById(id);
    }
}

</eventcashentity>
Neste caso, não temos nenhum processamento de dados, simplesmente recuperamos os dados das tabelas. Estamos todos prontos para fornecer o código completo da classe T elegramFacade e começar a analisar a lógica.
@Component
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TelegramFacade {

    final MessageHandler messageHandler;
    final CallbackQueryHandler callbackQueryHandler;
    final BotStateCash botStateCash;

    @Value("${telegrambot.adminId}")
    int adminId;


    public TelegramFacade(MessageHandler messageHandler, CallbackQueryHandler callbackQueryHandler, BotStateCash botStateCash) {
        this.messageHandler = messageHandler;
        this.callbackQueryHandler = callbackQueryHandler;
        this.botStateCash = botStateCash;
    }

    public BotApiMethod<!--?--> handleUpdate(Update update) {

        if (update.hasCallbackQuery()) {
            CallbackQuery callbackQuery = update.getCallbackQuery();
            return callbackQueryHandler.processCallbackQuery(callbackQuery);
        } else {

            Message message = update.getMessage();
            if (message != null && message.hasText()) {
                return handleInputMessage(message);
            }
        }
        return null;
    }

    private BotApiMethod<!--?--> handleInputMessage(Message message) {
        BotState botState;
        String inputMsg = message.getText();
        //we process messages of the main menu and any other messages
        //set state
        switch (inputMsg) {
            case "/start":
                botState = BotState.START;
                break;
            case "Мои напоминания":
                botState = BotState.MYEVENTS;
                break;
            case "Создать напоминание":
                botState = BotState.CREATE;
                break;
            case "Отключить напоминания":
            case "Включить напоминания":
                botState = BotState.ONEVENT;
                break;
            case "All users":
                if (message.getFrom().getId() == adminId)
                botState = BotState.ALLUSERS;
                else botState = BotState.START;
                break;
            case "All events":
                if (message.getFrom().getId() == adminId)
                botState = BotState.ALLEVENTS;
                else botState = BotState.START;
                break;
            default:
                botState = botStateCash.getBotStateMap().get(message.getFrom().getId()) == null?
                        BotState.START: botStateCash.getBotStateMap().get(message.getFrom().getId());
        }
        //we pass the corresponding state to the handler
        //the corresponding method will be called
        return messageHandler.handle(message, botState);

    }
}
Vejamos quais campos são necessários para
final MessageHandler messageHandler;
    final CallbackQueryHandler callbackQueryHandler;
    final BotStateCash botStateCash;
Se todos codificarmos em uma classe, terminaremos com um calçado para a lua; portanto, atribuímos a lógica para trabalhar com mensagens de texto à classe MessageHandler e a lógica para trabalhar com mensagens de callbackquery à classe CallbackQueryHandler . É hora de descobrir o que é allbackquery e que tipos de menus existem. Para fazer isso, darei outra imagem da interface do bot: Bot do Telegram - lembrete via webHook em Java ou diga não ao calendário do Google!  - 10Existem dois tipos de menus. Aqueles que estão anexados na parte inferior da janela - o menu principal, e aqueles que são atribuídos à mensagem, por exemplo, os botões de exclusão, edição, alteração da faixa. Ao clicar no botão do menu principal, é enviada uma mensagem com o mesmo nome, por exemplo, ao clicar em “Meus Lembretes” , simplesmente será enviado o texto “Meus Lembretes” . E ao instalar o teclado callbackquery, um valor específico é definido para cada botão e seu valor será enviado sem exibi-lo na tela. Em seguida temos o campo BotStateCash . Esta é uma classe especialmente criada que irá monitorar o estado do bot, e atenção, este é um elemento complexo, você precisa se esforçar. O número de caracteres foi ultrapassado, o que, aliás, não está escrito em lugar nenhum)). Então aqui está o link para a parte dois
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION