JavaRush /Blogue Java /Random-PT /Estamos adicionando a capacidade de assinar um grupo de a...
Roman Beekeeper
Nível 35

Estamos adicionando a capacidade de assinar um grupo de artigos. (Parte 3) - "Projeto Java de A a Z"

Publicado no grupo Random-PT
Oi de novo. Este é o artigo final do STEP_6, no qual falaremos sobre como adicionar funcionalidade à tarefa JRTB-6 . Nesses dois artigos anteriores ( parte 1 , parte 2 ) já preparamos quase tudo que você precisa. Esta parte é o culminar do processo. A todos que leram esta série de artigos até agora, desde o início – grande respeito. Isso significa que você tem motivação suficiente para encontrar um ótimo emprego. Agora vamos ao que interessa."Projeto Java de A a Z": Adicionando a capacidade de assinar um grupo de artigos.  Parte 3 - 1

Implementamos JRTB-6

Desta vez faremos a tarefa pelo lado do bot do telegrama, pois o trabalho de atualização do banco de dados está todo feito, as entidades do banco de dados estão configuradas e prontas para funcionar. Vamos adicionar um novo valor ao CommandName - LIST_GROUP_SUB:
LIST_GROUP_SUB("/listGroupSub");
Vamos criar um 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);
   }
}
Aqui tudo é o mais simples possível - pegamos o usuário usando o chat_id existente, e todas as suas assinaturas em grupos serão coletadas em seu objeto. Nós configuramos isso na segunda parte. Novamente, adicionei //todo para não esquecer de adicionar o tratamento de exceções que podem aparecer durante a operação. A próxima etapa é atualizar o CommandContainer adicionando um novo comando a ele:
put(LIST_GROUP_SUB.getCommandName(), new GroupSubListCommand(sendBotMessageService, telegramUserService))
Basicamente é isso: agora você precisa escrever mais testes, atualizar o comando /help (adicionar uma descrição para novos comandos) e testar a nova funcionalidade via Telegram. Vamos escrever um teste para ListGroupSubCommand . Como a lógica do comando não é típica, escreveremos um teste sem estar vinculado à classe AbstractCommandTest , como fizemos 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;
   }
}

Vamos atualizar o comando /help

No nosso caso, o comando /help funciona como documentação para trabalhar com o bot, por isso devemos lembrar de atualizá-lo para que o usuário possa utilizá-lo. Adicionamos dois comandos, então vamos atualizar o texto que virá:
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());
Também atualizei o texto das respostas do bot: fiz para que fosse sempre pelo primeiro nome do usuário, caso contrário haveria “você” e “você”... Agora será possível criar pelo menos algum tipo de conexão no trabalho do bot.

Testando o bot atualizado

Lançamos nosso bot localmente e fazemos o seguinte:
  1. Executamos o comando /start para ter certeza de que o usuário no caso de teste foi adicionado ao banco de dados.
  2. Executamos o comando /help - verificamos se está tudo bem, como queríamos.
  3. Em seguida, executamos o comando /addGroupSub .
  4. Da lista proposta de IDs de grupo, adicionamos vários à mistura.
  5. Executamos o comando /listGroupSub para garantir que os grupos estejam registrados para o usuário.
Ir! Lançamos o banco de dados via docker-compose-test.yml e iniciamos nosso SpringBoot. Em seguida, vá para nosso bot de teste e execute o comando /start, seguido de /help : "Projeto Java de A a Z": Adicionando a capacidade de assinar um grupo de artigos.  Parte 3 - 2Em seguida, insira o comando /addGroupSub : "Projeto Java de A a Z": Adicionando a capacidade de assinar um grupo de artigos.  Parte 3 - 3A lista suspensa diz que o cliente Java está funcionando como deveria: temos todos os grupos com seus IDs, uma descrição do comando ajuda (espero) a entender o que precisamos em seguida, então adicionamos vários grupos à assinatura: "Projeto Java de A a Z": Adicionando a capacidade de assinar um grupo de artigos.  Parte 3 - 4Agora temos 5 assinaturas, então podemos executar o comando /listGroupSub : E então temos algum tipo de coisa maluca ... Não está claro por que o título"Projeto Java de A a Z": Adicionando a capacidade de assinar um grupo de artigos.  Parte 3 - 5 apareceu sem problemas, mas não aqui. Vamos ao banco de dados para ver o que tem lá: As mesmas questões ficam registradas no banco de dados, mas apenas para quem tem alfabeto cirílico. Isso significa que há algum problema com a codificação. Aparentemente, você precisa configurar o banco de dados e o driver para conexão ao banco de dados. Precisamos de UTF-8. Mas como adicioná-lo? Após vários minutos de pesquisa na Internet, descobri : o driver precisa atualizar a variável url. E para configurar uma imagem docker no docker-compose, o primeiro link , mas a resposta não é a primeira)) Portanto, sabendo disso, vamos atualizar as propriedades e os arquivos do docker-compose. "Projeto Java de A a Z": Adicionando a capacidade de assinar um grupo de artigos.  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
Após essas atualizações, você precisa apagar todos os dados do banco de dados e recomeçar. Apagar é muito simples: você precisa executar o comando: docker-compose -f docker-compose-test.yml down após o qual todos os dados e banco de dados serão excluídos. E execute-o novamente, com a codificação atualizada: docker-compose -f docker-compose-test.uml up O banco de dados está pronto. Vamos iniciar o aplicativo atualizado e dar uma olhada. Vou repassar isso rapidamente e mostrar o resultado: "Projeto Java de A a Z": Adicionando a capacidade de assinar um grupo de artigos.  Parte 3 - 7e agora conseguimos exatamente o que queríamos. Agora isso parece verdade.

Final

Agora acho que podemos concluir esta etapa. Muito foi feito, muito mesmo. Vamos atualizar a versão do aplicativo para 0.5.0-SNAPSHOT e RELEASE_NOTES.
# Notas de versão ## 0.5.0-SNAPSHOT * JRTB-5: capacidade adicional de assinar em grupo * JRTB-6: capacidade adicional de obter uma lista de assinaturas de grupo.
Então tudo fica normal: criamos um novo commit com todas as alterações. O principal é adicionar uma descrição das duas tarefas que foram concluídas durante esta etapa para fins de relatório. Então aqui está o comentário:
STEP_6 JRTB-5: capacidade adicional de assinatura no grupo JRTB-6: capacidade adicional de ver a lista de assinaturas do grupo.
Isso resultou em 47 arquivos alterados... Essa é uma grande mudança. Embora você não possa dizer pela descrição da funcionalidade. Afinal, para entender toda a profundidade, você precisa saber que precisa escrever um cliente Java para a API, essencialmente atualizando todo o aplicativo. É assim, trabalhar no servidor - dá muito trabalho, mas a visibilidade do lado do cliente é pequena...)) Amigos, tradicionalmente ofereço a vocês uma forma de demonstrar interesse pelo meu trabalho - inscreva-se em um github conta , entre no canal do Telegram e escreva uma pergunta sobre o artigo, se algo não estiver claro! Aqui está um link para a solicitação pull com alterações para este STEP_6 . Obrigado a todos pela leitura. Mais por vir - vamos falar sobre como excluir uma assinatura, desativar um perfil e muito mais. Não mude))

Uma lista de todos os materiais da série está no início deste artigo.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION