JavaRush /Blog Java /Random-ES /Bot de Telegram: ¡recordatorio a través de webHook en Jav...
Vladimir Popov
Nivel 41

Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google! Parte 1

Publicado en el grupo Random-ES
Mi nombre es Vladimir. Tengo 43 años. Y si tú, lector, tienes más de 40 años, entonces sí, después de los 40 podrás convertirte en programador si te gusta. Mi trabajo no tiene nada que ver con la programación, soy gerente de proyectos en el campo de la automatización y todo eso. Pero estoy pensando en cambiar de ocupación. Oh, estas nuevas tendencias... cambian de campo de actividad cada 5-7 años. Entonces : El proyecto resultó ser bastante grande, por lo que habrá que omitir o comentar brevemente algunos puntos, con la esperanza de que el lector sepa cómo buscar en Google. Internet está lleno de publicaciones de robots de Telegram que funcionan según el principio de sondeo largo. Y hay muy pocos que funcionen según el principio de Webhook. ¿Lo que es? Sondeo largo : esto significa que su propia aplicación sondeará el servidor de Telegram en busca de mensajes con una frecuencia determinada, lentamente. Webhook : significa que el servidor de Telegram redirigirá instantáneamente los mensajes al servidor que usted especifique. En nuestro caso, cortesía del servicio Heroku. Por supuesto, puede leer más sobre todo esto y sobre el bot en general en el sitio web de Telegram: https://tlgrm.ru/docs/bots/api La interfaz del bot se ve así: Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 1 Considero esta aplicación precisamente como un entrenamiento proyecto porque al escribir aprendí más información de este bot que cuando entrenaba. ¿Quieres aprender a programar? ¡¡¡Empieza a escribir código!!! ¡Pero! No habrá instrucciones detalladas sobre cómo cargar la aplicación en github o cómo crear una base de datos. Hay mucho de esto en Internet y está descrito con gran detalle; además, será una lectura muy larga. La aplicación funcionará de la siguiente manera: Ingresa una descripción del evento, ingresa la fecha y hora del evento, selecciona la frecuencia (puedes hacerlo una vez, puedes tener un recordatorio todos los días a una hora determinada, puedes tenerlo una vez un mes en un momento determinado, o una vez al año). Se pueden agregar infinitas variaciones de notificaciones; tengo muchas ideas. A continuación, los datos ingresados ​​se guardan en la base de datos (también implementada de forma gratuita en Heroku, 10,000 filas son gratuitas). Luego, una vez al comienzo del día a las 0:00 hora del servidor, Spring recupera de la base de datos todos los eventos según los criterios. que debería activarse ese día y enviarlos para su ejecución a la hora especificada. ¡¡¡ATENCIÓN!!! ¡ESTA PARTE DEL PROGRAMA ES EXPERIMENTAL! ¡HAY UNA IMPLEMENTACIÓN MÁS SIMPLE Y VERDADERA! ¡ESTO SE HIZO ESPECÍFICAMENTE PARA VER CÓMO FUNCIONA LA CLASE DE TIEMPO! Puedes tocar el robot en funcionamiento con tus propias manos escribiendo @calendar_event_bot en el carrito, pero no cuentes con ello, porque todavía me estoy burlando de ello. código - https://github.com/papoff8295/webHookBotForHabr Básicamente, para iniciar el tuyo propio necesitas seguir los siguientes pasos: • Regístrate con @BotFather , no es difícil, obtén un token y un nombre • Bifurca el proyecto en github • Regístrate en heroku, cree una aplicación (la veremos paso a paso), impleméntela desde su repositorio. • Cree una base de datos en Heroku • Reemplace los campos correspondientes en el repositorio con los suyos propios (token, nombre de tablas en entidades, webHookPath, nombre de usuario, contraseña y ruta a la base de datos, todo esto será analizado) • Haga que Heroku funcione 24/ 7 usando https:/ /uptimerobot.com/ La estructura final del proyecto es la siguiente: Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 2 Comencemos creando un proyecto en https://start.spring.io Seleccione las dependencias que necesitamos como se muestra en la figura: Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 3Seleccione las nuestras nombre del proyecto y haga clic en Generar . A continuación se le pedirá que guarde el proyecto en su disco. Todo lo que queda es abrir el archivo pom.xml desde su entorno de desarrollo. Hay un proyecto terminado frente a ti. Ahora solo necesitamos agregar nuestra biblioteca principal. Usé la biblioteca de https://github.com/rubenlagus/TelegramBots . En general, puedes confundirte y prescindir de ella. Después de todo, el objetivo del trabajo es concatenar una URL como esta: https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io Veámoslo un poco : https://api.telegram.org – servidor de telegramas. bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/ - después de la palabra bot hay un token secreto que recibe al registrar un bot. setWebhook?url=https://e9c658b548aa.ngrok.io – nombre del método y sus parámetros. En este caso, instalamos su servidor de webhook y todos los mensajes se enviarán a él. En general, decidí que el proyecto no era demasiado pequeño para publicarlo, pero si se implementara manualmente, en general sería ilegible. Entonces, el aspecto final del archivo pom es:
<!--?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>
Todo está listo para escribir nuestro bot. Creemos la clase TelegramBot . No escribiré los nombres de las carpetas, puedes verlos en la estructura del proyecto arriba.
@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);
    }
}
La clase extiende SpringWebhookBot desde nuestra biblioteca de Telegram y solo necesitamos implementar un método, onWebhookUpdateReceived . Acepta JSON analizado como un objeto de actualización y devuelve lo que el servidor de Telegram quiere "escuchar" de nosotros. Aquí tenemos anotaciones de la biblioteca de Lombok . Lombok : ¡haciendo la vida del programador más fácil! Bueno, eso es. No necesitamos redefinir captadores y definidores, Lombok lo hace por nosotros y tampoco necesitamos escribir un identificador de nivel de acceso. Ya no vale la pena escribir que esto se hace mediante las anotaciones @Getter, @Setter, @FieldDefaults. El campo botPath significa nuestra dirección de webhook, que recibiremos en Heroku más adelante. El campo botUsername significa el nombre de nuestro bot, que recibiremos al registrar nuestro bot en Telegram. El campo botToken es nuestro token, que recibiremos al registrar nuestro bot en Telegram. El campo telegramFacade es nuestra clase donde se procesará el mensaje, volveremos a él un poco más tarde, déjelo en rojo por ahora. Ahora es el momento de que contactemos a @BotFather y obtengamos el codiciado botToken y botUsername. Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 4Simplemente escríbele por Telegram y te lo contará todo. Escribimos los datos en nuestra aplicación.properties, al final quedará así:
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 configuración está configurada para trabajar con una base de datos local, posteriormente realizaremos los cambios necesarios. Reemplace botToken y nombre de usuario por los suyos propios. No es bueno utilizar datos de application.properties directamente en la aplicación. Creemos un bean o una clase contenedora a partir de estos datos.
@Component
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)

public class TelegramBotConfig {
    @Value("${telegrambot.webHookPath}")
    String webHookPath;
    @Value("${telegrambot.userName}")
    String userName;
    @Value("${telegrambot.botToken}")
    String botToken;
Aquí la anotación @Value inicializa las líneas correspondientes del archivo application.properties, que Spring conoce de forma predeterminada. Y la anotación @Component crea un Bean para nosotros cuando se inicia la aplicación. Veamos ahora el archivo de configuración de 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;
    }
}
No hay magia aquí; al inicio, Spring crea objetos SetWebhook y TelegramBot para nosotros. Ahora creemos puntos de entrada para nuestros mensajes:
@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();
    }
}
El servidor de Telegram envía mensajes en formato JSON a la dirección del webhook registrado utilizando el método POST, nuestro controlador los recibe y los transmite a la biblioteca de Telegram en forma de un objeto Update. Hice el método get así como así) Ahora solo necesitamos implementar algo de lógica para procesar mensajes y respuestas en la clase TelegramFacade , le daré su código corto para que pueda iniciar la aplicación y luego seguir su propio camino o cambiar para implementar en Heroku, entonces será la versión 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 cualquier ¡Hola mundo! Para iniciar nuestra aplicación, solo necesitamos asegurarnos de que podemos probar nuestra aplicación directamente desde IDEA. Para hacer esto, necesitamos descargar la utilidad ngrok. https://ngrok.com/download Esta utilidad es una línea de comando que nos proporciona una dirección temporal durante 2 horas y redirige todos los mensajes al puerto especificado del servidor local. Lanzamos y escribimos ngrok http 5000 en la línea (o puede especificar su puerto): Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 5Obtenemos el resultado: Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 6https://23b1a54ccbbd.ngrok.io: esta es nuestra dirección de webhook. Como habrás notado en el archivo de propiedades que escribimos server.port=5000 al iniciar el servidor Tomcat, ocupará el puerto 5000, asegúrate de que estos campos sean los mismos. Además, no olvides que la dirección se da durante dos horas. En la línea de comando, esto es monitoreado por el campo Session Expires. Cuando se acabe el tiempo, deberá obtener la dirección nuevamente y realizar el procedimiento para registrarla en Telegram. Ahora tomamos la línea https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io Y con hábiles movimientos de la mano reemplazamos el token por el nuestro, la url por la nuestra, pegamos la línea resultante en el navegador y haga clic en Intro. Deberías obtener el siguiente resultado: Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 7Eso es todo, ahora puedes ejecutar la aplicación: Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 8Comprueba que tu clase con el método principal quedó así:
@SpringBootApplication
public class TelegramBotApplication {

   public static void main(String[] args) {
      SpringApplication.run(TelegramBotApplication.class, args);
   }
}
Si hiciste todo correctamente, ahora tu bot responderá a cualquier mensaje con la frase “ Hola mundo” . Entonces podrás seguir tu propio camino. Si está conmigo y está interesado en seguir todos los pasos, comencemos a escribir entidades para la base de datos y creemos la base de datos en sí. Comencemos con la base de datos: como ya dije, supongo que ya tiene habilidades mínimas para trabajar con la base de datos y tiene instalada una base de datos postgreSQL local ; si no, siga este camino. https://www.postgresql.org/download/ En el archivo application.properties, reemplace el nombre de usuario y la contraseña de la base de datos con los suyos propios. En IDEA hay una pestaña de base de datos a la derecha, en ella debe hacer clic en +/Fuente de datos/PostgreSQL . Como resultado, cuando haga clic en Probar conexión debería obtener un resultado satisfactorio: Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 9ahora puede crear una base de datos con tablas directamente desde el entorno de desarrollo, o puede usar la interfaz web pgadmin , que se encuentra en el menú de inicio. Necesitaremos 3 mesas:
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
);
Recomiendo crear este script por separado; lo necesitaremos para crear una base de datos en Heroku, para no escribirlo dos veces. Caminemos un poco. Diré de inmediato que solo necesitamos la tabla event_cash para trabajar con Heroku debido a sus detalles y mi deseo insaciable de trabajar con la clase Time ; no será útil en la versión local. En la tabla de usuarios registraremos el id de la cuenta del usuario de Telegram, su nombre, que puede no existir, se calculará la zona horaria del usuario para el correcto envío de notificaciones, así como el estado de encendido/apagado del envío de notificaciones. Registraremos la identificación del usuario, la hora de notificación y la descripción en la tabla user_events , generaremos automáticamente una identificación para el evento y estableceremos la frecuencia de las notificaciones. La tabla event_cash registrará la notificación antes de enviarla y, si se envía, la eliminará de la tabla. Las tablas están listas, ahora agreguemos las 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;
    }
}
Repasemos un poco los puntos principales. @Entity : marca la clase para nuestro dada jpa que esta clase es una entidad para la base de datos, es decir. Al recuperar datos de la base de datos, se nos presentarán en forma de un objeto Evento, Usuario y EventCashEntity. @Table – decimos el nombre de nuestra tabla en la base de datos. Para asegurarnos de que el nombre de la tabla no esté subrayado en rojo, debemos aceptar en IDEA la opción de corrección de errores propuesta y hacer clic en Asignar fuentes de datos. Y seleccione nuestra base allí. @id y @GeneratedValue : utilizados por Spring para crear una base de datos si aún no existe. @Column se utiliza para indicar el nombre de los campos de la tabla si no coinciden, pero las reglas del buen código recomiendan escribir siempre esto. Actitud OneToMany : recomiendo dedicar tiempo y descubrir qué es aquí https://en.wikibooks.org/wiki/Java_Persistence. No puedo explicarlo más claramente, solo créanme. Permítanme decirles que en este caso la anotación @OneToMany dice que un usuario puede tener muchos eventos y se nos proporcionarán en forma de lista. Ahora necesitamos obtener datos de las tablas. En la biblioteca SRING DATA JPA ya todo está escrito para nosotros, solo necesitamos crear una interfaz para cada tabla y extenderla desde 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,>
La lógica principal para trabajar con la base de datos se transfiere a un servicio, el llamado Objeto de acceso a datos (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>
En este caso no tenemos ningún procesamiento de datos, simplemente recuperamos datos de las tablas. Estamos todos listos para proporcionar el código completo de la clase T elegramFacade y comenzar a analizar la 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);

    }
}
Veamos para qué campos se necesitan
final MessageHandler messageHandler;
    final CallbackQueryHandler callbackQueryHandler;
    final BotStateCash botStateCash;
Si todos codificamos en una clase, terminaremos con un calcetín hasta la luna; por lo tanto, asignamos la lógica para trabajar con mensajes de texto a la clase MessageHandler y la lógica para trabajar con mensajes de callbackquery a la clase CallbackQueryHandler . Es hora de descubrir qué es allbackquery y qué tipos de menús existen. Para ello te paso otra imagen de la interfaz del bot: Bot de Telegram: ¡recordatorio a través de webHook en Java o di no al calendario de Google!  - 10Hay dos tipos de menús. Los que están adjuntos en la parte inferior de la ventana: el menú principal y los que están asignados al mensaje, por ejemplo, los botones de eliminación, edición y cambio del cinturón. Al hacer clic en el botón del menú principal, se envía un mensaje con el mismo nombre, por ejemplo, al hacer clic en “Mis recordatorios” , simplemente se enviará el texto “Mis recordatorios” . Y al instalar el teclado callbackquery, se establece un valor específico para cada botón y su valor se enviará sin mostrarlo en la pantalla. A continuación tenemos el campo BotStateCash . Esta es una clase especialmente creada que monitoreará el estado del bot, y atención, este es un elemento complejo, debes esforzarte. Se superó el número de caracteres que, por cierto, no está escrito en ninguna parte)). Así que aquí está el enlace a la segunda parte.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION