JavaRush /Blog Java /Random-ES /Estamos agregando la posibilidad de suscribirse a un grup...

Estamos agregando la posibilidad de suscribirse a un grupo de artículos. (Parte 3) - "Proyecto Java de la A a la Z"

Publicado en el grupo Random-ES
Hola de nuevo. Este es el último artículo de STEP_6, en el que hablaremos sobre cómo agregar funcionalidad a la tarea JRTB-6 . En esos dos artículos anteriores ( parte 1 , parte 2 ) ya hemos preparado casi todo lo que necesitas. Esta parte es la culminación del proceso. A todos los que han leído esta serie de artículos hasta este punto desde el principio: un gran respeto. Esto significa que tienes suficiente motivación para encontrar un gran trabajo. Ahora pongámonos manos a la obra."Proyecto Java de la A a la Z": Agregar la posibilidad de suscribirse a un grupo de artículos.  Parte 3 - 1

Implementamos JRTB-6

Esta vez haremos la tarea desde el lado del bot de Telegram, porque el trabajo de actualización de la base de datos está terminado, las entidades de la base de datos están configuradas y listas para funcionar. Agreguemos un nuevo valor a CommandName : LIST_GROUP_SUB:
LIST_GROUP_SUB("/listGroupSub");
Creemos un comando ListGroupSubCommand :
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.telegram.telegrambots.meta.api.objects.Update;

import javax.ws.rs.NotFoundException;
import java.util.stream.Collectors;

import static com.github.javarushcommunity.jrtb.command.CommandUtils.getChatId;

/**
* {@link Command} for getting list of {@link GroupSub}.
*/
public class ListGroupSubCommand implements Command {

   private final SendBotMessageService sendBotMessageService;
   private final TelegramUserService telegramUserService;

   public ListGroupSubCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
       this.sendBotMessageService = sendBotMessageService;
       this.telegramUserService = telegramUserService;
   }

   @Override
   public void execute(Update update) {
       //todo add exception handling
       TelegramUser telegramUser = telegramUserService.findByChatId(getChatId(update))
               .orElseThrow(NotFoundException::new);

       String message = "Я нашел все подписки на группы: \n\n";
       String collectedGroups = telegramUser.getGroupSubs().stream()
               .map(it -> "Группа: " + it.getTitle() + " , ID = " + it.getId() + " \n")
               .collect(Collectors.joining());

       sendBotMessageService.sendMessage(telegramUser.getChatId(), message + collectedGroups);
   }
}
Aquí todo es lo más simple posible: hacemos que el usuario utilice el chat_id existente y todas sus suscripciones a grupos se recopilarán en su objeto. Configuramos esto en la segunda parte. Nuevamente, agregué //todo para no olvidarme de agregar el manejo de excepciones que puedan surgir durante la operación. El siguiente paso es actualizar CommandContainer agregándole un nuevo comando:
put(LIST_GROUP_SUB.getCommandName(), new GroupSubListCommand(sendBotMessageService, telegramUserService))
Eso es básicamente todo: ahora necesitas escribir más pruebas, actualizar el comando /help (agregar una descripción para los nuevos comandos) y probar la nueva funcionalidad a través de Telegram. Escribamos una prueba para ListGroupSubCommand . Como la lógica del comando no es típica, escribiremos una prueba sin estar vinculados a la clase AbstractCommandTest , como hicimos antes:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.github.javarushcommunity.jrtb.command.CommandName.LIST_GROUP_SUB;

@DisplayName("Unit-level testing for ListGroupSubCommand")
public class ListGroupSubCommandTest {

   @Test
   public void shouldProperlyShowsListGroupSub() {
       //given
       TelegramUser telegramUser = new TelegramUser();
       telegramUser.setActive(true);
       telegramUser.setChatId("1");

       List<GroupSub> groupSubList = new ArrayList<>();
       groupSubList.add(populateGroupSub(1, "gs1"));
       groupSubList.add(populateGroupSub(2, "gs2"));
       groupSubList.add(populateGroupSub(3, "gs3"));
       groupSubList.add(populateGroupSub(4, "gs4"));

       telegramUser.setGroupSubs(groupSubList);

       SendBotMessageService sendBotMessageService = Mockito.mock(SendBotMessageService.class);
       TelegramUserService telegramUserService = Mockito.mock(TelegramUserService.class);

       Mockito.when(telegramUserService.findByChatId(telegramUser.getChatId())).thenReturn(Optional.of(telegramUser));

       ListGroupSubCommand command = new ListGroupSubCommand(sendBotMessageService, telegramUserService);

       Update update = new Update();
       Message message = Mockito.mock(Message.class);
       Mockito.when(message.getChatId()).thenReturn(Long.valueOf(telegramUser.getChatId()));
       Mockito.when(message.getText()).thenReturn(LIST_GROUP_SUB.getCommandName());
       update.setMessage(message);

       String collectedGroups = "Я нашел все подписки на группы: \n\n" +
               telegramUser.getGroupSubs().stream()
                       .map(it -> "Группа: " + it.getTitle() + " , ID = " + it.getId() + " \n")
                       .collect(Collectors.joining());

       //when
       command.execute(update);

       //then
       Mockito.verify(sendBotMessageService).sendMessage(telegramUser.getChatId(), collectedGroups);
   }

   private GroupSub populateGroupSub(Integer id, String title) {
       GroupSub gs = new GroupSub();
       gs.setId(id);
       gs.setTitle(title);
       return gs;
   }
}

Actualicemos el comando /help

En nuestro caso, el comando /help actúa como documentación para trabajar con el bot, por lo que debemos recordar actualizarlo para que el usuario pueda utilizarlo. Hemos agregado dos comandos, así que actualicemos el texto que vendrá:
public static final String HELP_MESSAGE = String.format("✨Дотупные команды✨\n\n"

               + "Начать\\закончить работу с ботом:\n"
               + "%s - начать работу со мной\n"
               + "%s - приостановить работу со мной\n\n"

               + "Работа с подписками на группы:\n"
               + "%s - подписаться на группу статей\n"
               + "%s - получить список групп, на которые подписан\n\n"

               + "%s - получить помощь в работе со мной\n"
               + "%s - получить мою статистику использования\n",
       START.getCommandName(), STOP.getCommandName(), ADD_GROUP_SUB.getCommandName(),
       LIST_GROUP_SUB.getCommandName(), HELP.getCommandName(), STAT.getCommandName());
También actualicé el texto de las respuestas del bot: lo hice para que siempre estuviera en términos de nombre con el usuario, de lo contrario habría "tú" y "tú"... Ahora será posible crear al menos algún tipo de conexión en el trabajo del bot.

Probando el bot actualizado

Lanzamos nuestro bot localmente y hacemos lo siguiente:
  1. Ejecutamos el comando /start para asegurarnos de que el usuario en el caso de prueba haya sido agregado a la base de datos.
  2. Ejecutamos el comando /help - comprobamos que todo está bien, como queríamos.
  3. A continuación ejecutamos el comando /addGroupSub .
  4. De la lista propuesta de ID de grupo, agregamos varios a la mezcla.
  5. Ejecutamos el comando /listGroupSub para asegurarnos de que los grupos estén registrados para el usuario.
¡Ir! Lanzamos la base de datos a través de docker-compose-test.yml e iniciamos nuestro SpringBoot. Luego, vaya a nuestro bot de prueba y ejecute el comando /start, seguido de /help : "Proyecto Java de la A a la Z": Agregar la posibilidad de suscribirse a un grupo de artículos.  Parte 3 - 2Luego, ingrese el comando /addGroupSub : "Proyecto Java de la A a la Z": Agregar la posibilidad de suscribirse a un grupo de artículos.  Parte 3 - 3La lista desplegable dice que el cliente Java está funcionando como debería: tenemos todos los grupos con sus ID, una descripción del comando ayuda (con suerte) a comprender lo que necesitamos a continuación, por lo que agregamos varios grupos a la suscripción: "Proyecto Java de la A a la Z": Agregar la posibilidad de suscribirse a un grupo de artículos.  Parte 3 - 4Ahora tenemos 5 suscripciones, por lo que podemos ejecutar el comando /listGroupSub : Y luego obtenemos una especie de locura. ... No está claro por qué el título"Proyecto Java de la A a la Z": Agregar la posibilidad de suscribirse a un grupo de artículos.  Parte 3 - 5 se mostraba sin problemas, pero no aquí. Vayamos a la base de datos para ver qué hay allí: Las mismas preguntas están registradas en la base de datos, pero sólo para aquellas con alfabeto cirílico. Esto significa que hay algún problema con la codificación. Aparentemente, necesita configurar la base de datos y el controlador para conectarse a la base de datos. Necesitamos UTF-8. ¿Pero cómo agregarlo? Después de varios minutos de búsqueda en Internet, encontré : el controlador necesita actualizar la variable URL. Y para configurar una imagen de Docker en Docker-Compose, el primer enlace , pero la respuesta no es la primera)) Por lo tanto, sabiendo esto, actualicemos las propiedades y los archivos de Docker-Compose. "Proyecto Java de la A a la Z": Agregar la posibilidad de suscribirse a un grupo de artículos.  Parte 3 - 6
application.properties:
spring.datasource.url=jdbc:mysql://jrtb-db:3306/jrtb_db?characterEncoding=UTF-8

application-test.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/dev_jrtb_db?characterEncoding=UTF-8

docker-compose.yml (добавил последнюю строку):
jrtb-db:
 image: mysql:5.7
 restart: always
 environment:
   MYSQL_USER: ${BOT_DB_USERNAME}
   MYSQL_PASSWORD: ${BOT_DB_PASSWORD}
   MYSQL_DATABASE: 'jrtb_db'
   MYSQL_ROOT_PASSWORD: 'root'
 ports:
   - '3306:3306'
 expose:
   - '3306'
 command: --character-set-server=utf8 --collation-server=utf8_general_ci

docker-compose-test.yml (добавил последнюю строку)
jrtb-db-dev:
 image: mysql:5.7
 restart: always
 environment:
   MYSQL_DATABASE: 'dev_jrtb_db'
   # So you don't have to use root, but you can if you like
   MYSQL_USER: 'dev_jrtb_db_user'
   # You can use whatever password you like
   MYSQL_PASSWORD: 'dev_jrtb_db_password'
   # Password for root access
   MYSQL_ROOT_PASSWORD: 'root'
 ports:
   # <Port exposed> : < MySQL Port running inside container>
   - '3306:3306'
 expose:
   # Opens port 3306 on the container
     - '3306'
 command: --character-set-server=utf8 --collation-server=utf8_general_ci
Después de estas actualizaciones, debe borrar todos los datos de la base de datos y comenzar de nuevo. Borrar es muy simple: debe ejecutar el comando: docker-compose -f docker-compose-test.yml down, después de lo cual se eliminan todos los datos y la base de datos. Y ejecútelo nuevamente, con la codificación actualizada: docker-compose -f docker-compose-test.uml up La base de datos está lista. Iniciemos la aplicación actualizada y echemos un vistazo. Lo repasaré rápidamente y les mostraré el resultado: "Proyecto Java de la A a la Z": Agregar la posibilidad de suscribirse a un grupo de artículos.  Parte 3 - 7y ahora tenemos exactamente lo que queríamos. Ahora esto parece ser la verdad.

Finalizando

Ahora creo que podemos completar este paso. Se ha hecho mucho, realmente mucho. Actualicemos la versión de la aplicación a 0.5.0-SNAPSHOT y RELEASE_NOTES.
# Notas de la versión ## 0.5.0-SNAPSHOT * JRTB-5: capacidad agregada para suscribirse en un grupo * JRTB-6: capacidad agregada para obtener una lista de suscripciones grupales.
Luego todo es como siempre: creamos un nuevo commit con todos los cambios. Lo principal es agregar una descripción de las dos tareas que se completaron durante este paso para fines de generación de informes. Así que aquí está el comentario:
STEP_6 JRTB-5: capacidad agregada para suscribirse en el grupo JRTB-6: capacidad agregada para ver la lista de suscripción del grupo.
Esto resultó en 47 archivos modificados... Ese es un gran cambio. Aunque no se puede saber por la descripción de la funcionalidad. Después de todo, para comprender toda la profundidad, necesita saber que necesita escribir un cliente Java para la API, esencialmente actualizando toda la aplicación. Así es, trabajar en un servidor: hay mucho trabajo, pero la visibilidad desde el lado del cliente es pequeña...)) Amigos, tradicionalmente les ofrezco una manera de mostrar interés en mi trabajo: suscríbase a github . cuenta , únete al canal de Telegram y escribe una pregunta sobre el artículo, si algo no queda claro. Aquí hay un enlace a la solicitud de extracción con cambios para este STEP_6 . Gracias a todos por leer. Más por venir: hablemos sobre eliminar una suscripción, desactivar un perfil y más. No cambies))

Al principio de este artículo encontrará una lista de todos los materiales de la serie.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION