JavaRush /Blog Java /Random-FR /Nous ajoutons la possibilité de s'abonner à un groupe d'a...
Roman Beekeeper
Niveau 35

Nous ajoutons la possibilité de s'abonner à un groupe d'articles. (Partie 3) - "Projet Java de A à Z"

Publié dans le groupe Random-FR
Re-bonjour. Il s'agit du dernier article de STEP_6, dans lequel nous parlerons de l'ajout de fonctionnalités à la tâche JRTB-6 . Dans ces deux articles précédents ( partie 1 , partie 2 ) nous avons déjà préparé presque tout ce dont vous avez besoin. Cette partie est le point culminant du processus. À tous ceux qui ont lu cette série d’articles depuis le début – un grand respect. Cela signifie que vous êtes suffisamment motivé pour trouver un bon emploi. Passons maintenant aux choses sérieuses."Projet Java de A à Z" : Ajout de la possibilité de s'abonner à un groupe d'articles.  Partie 3 - 1

Nous implémentons JRTB-6

Cette fois, nous effectuerons la tâche du côté du robot Telegram, car le travail de mise à jour de la base de données est terminé, les entités de la base de données sont configurées et prêtes à fonctionner. Ajoutons une nouvelle valeur à CommandName - LIST_GROUP_SUB :
LIST_GROUP_SUB("/listGroupSub");
Créons une commande 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);
   }
}
Ici, tout est aussi simple que possible - nous obtenons l'utilisateur en utilisant le chat_id existant, et tous ses abonnements aux groupes seront collectés dans son objet. Nous avons mis cela en place dans la deuxième partie. Encore une fois, j'ai ajouté //todo pour ne pas oublier d'ajouter la gestion des exceptions pouvant survenir pendant le fonctionnement. L'étape suivante consiste à mettre à jour le CommandContainer en y ajoutant une nouvelle commande :
put(LIST_GROUP_SUB.getCommandName(), new GroupSubListCommand(sendBotMessageService, telegramUserService))
C'est essentiellement tout : vous devez maintenant écrire plus de tests, mettre à jour la commande /help (ajouter une description pour les nouvelles commandes) et tester la nouvelle fonctionnalité via Telegram. Écrivons un test pour ListGroupSubCommand . Puisque la logique de la commande n'est pas typique, nous allons écrire un test sans être lié à la classe AbstractCommandTest , comme nous l'avons fait auparavant :
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;
   }
}

Mettons à jour la commande /help

Dans notre cas, la commande /help fait office de documentation pour travailler avec le bot, nous devons donc penser à la mettre à jour pour que l'utilisateur puisse l'utiliser. Nous avons ajouté deux commandes, mettons donc à jour le texte à venir :
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());
J'ai également mis à jour le texte des réponses du bot : j'ai fait en sorte qu'il soit toujours par prénom avec l'utilisateur, sinon il y aurait à la fois « vous » et « vous »... Il sera désormais possible de créer au moins une sorte de connexion dans le travail du bot.

Tester le bot mis à jour

Nous lançons notre bot localement et procédons comme suit :
  1. Nous exécutons la commande /start pour nous assurer que l'utilisateur dans le scénario de test a été ajouté à la base de données.
  2. Nous exécutons la commande /help - nous vérifions que tout va bien, comme nous le souhaitions.
  3. Ensuite, nous exécutons la commande /addGroupSub .
  4. À partir de la liste proposée d’identifiants de groupe, nous en ajoutons plusieurs au mélange.
  5. Nous exécutons la commande /listGroupSub pour nous assurer que les groupes sont enregistrés auprès de l'utilisateur.
Aller! Nous lançons la base de données via docker-compose-test.yml et démarrons notre SpringBoot. Ensuite, allez sur notre robot de test et exécutez la commande /start, suivie de /help : "Projet Java de A à Z" : Ajout de la possibilité de s'abonner à un groupe d'articles.  Partie 3 - 2Ensuite, entrez la commande /addGroupSub : "Projet Java de A à Z" : Ajout de la possibilité de s'abonner à un groupe d'articles.  Partie 3 - 3La liste déroulante indique que le client Java fonctionne comme il se doit : nous avons tous les groupes avec leur ID, une description de la commande aide (espérons-le) à comprendre ce dont nous avons besoin ensuite, nous ajoutons donc plusieurs groupes à l'abonnement : "Projet Java de A à Z" : Ajout de la possibilité de s'abonner à un groupe d'articles.  Partie 3 - 4Maintenant nous avons 5 abonnements, nous pouvons donc exécuter la commande /listGroupSub : Et puis nous obtenons une sorte de truc fou ... On ne sait pas pourquoi le titre"Projet Java de A à Z" : Ajout de la possibilité de s'abonner à un groupe d'articles.  Partie 3 à 5 s'affichait sans problème, mais pas ici. Allons dans la base de données pour voir ce qu'il y a : les mêmes questions sont enregistrées dans la base de données, mais uniquement pour celles avec l'alphabet cyrillique. Cela signifie qu'il y a un problème avec l'encodage. Apparemment, vous devez configurer la base de données et le pilote pour vous connecter à la base de données. Nous avons besoin d'UTF-8. Mais comment l'ajouter ? Après plusieurs minutes de recherche sur Internet, j'ai trouvé : le pilote doit mettre à jour la variable url. Et pour configurer une image docker dans docker-compose, le tout premier lien , mais la réponse n'est pas le premier)) Par conséquent, sachant cela, mettons à jour les propriétés et les fichiers docker-compose. "Projet Java de A à Z" : Ajout de la possibilité de s'abonner à un groupe d'articles.  Partie 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
Après ces mises à jour, vous devez effacer toutes les données de la base de données et recommencer. L'effacement est très simple : vous devez exécuter la commande : docker-compose -f docker-compose-test.yml down après quoi toutes les données et la base de données sont supprimées. Et exécutez-le à nouveau, avec l'encodage mis à jour : docker-compose -f docker-compose-test.uml up La base de données est prête. Lançons l'application mise à jour et jetons un œil. Je vais le parcourir rapidement et vous montrer le résultat : "Projet Java de A à Z" : Ajout de la possibilité de s'abonner à un groupe d'articles.  Partie 3 à 7et maintenant, nous avons obtenu exactement ce que nous voulions. Maintenant, cela ressemble à la vérité.

Fin

Maintenant, je pense que nous pouvons terminer cette étape. Beaucoup a été fait, vraiment beaucoup. Mettons à jour la version de l'application vers 0.5.0-SNAPSHOT et RELEASE_NOTES.
# Notes de version ## 0.5.0-SNAPSHOT * JRTB-5 : possibilité supplémentaire de s'abonner à un groupe * JRTB-6 : possibilité supplémentaire d'obtenir une liste d'abonnements de groupe.
Ensuite, tout se passe comme d'habitude : nous créons un nouveau commit avec tous les changements. L'essentiel est d'ajouter une description des deux tâches qui ont été réalisées au cours de cette étape à des fins de reporting. Voici donc le commentaire :
STEP_6 JRTB-5 : ajout de la possibilité de s'abonner sur le groupe JRTB-6 : ajout de la possibilité de voir la liste des abonnements du groupe.
Cela a entraîné 47 fichiers modifiés... C'est un grand changement. Bien que vous ne puissiez pas le dire à partir de la description des fonctionnalités. Après tout, pour comprendre toute la profondeur, vous devez savoir que vous devez écrire un client Java pour l'API, mettant essentiellement à jour l'ensemble de l'application. C'est comme ça, travailler sur un serveur - il y a beaucoup de travail, mais la visibilité du côté client est faible...)) Les amis, je vous propose traditionnellement un moyen de montrer votre intérêt pour mon travail - abonnez-vous à un github compte , rejoignez la chaîne Telegram et écrivez une question sur l'article, si quelque chose n'est pas clair ! Voici un lien vers la pull request avec les modifications pour ce STEP_6 . Merci à tous d'avoir lu. Plus à venir : parlons de la suppression d'un abonnement, de la désactivation d'un profil, et bien plus encore. Ne changez pas))

Une liste de tous les matériaux de la série se trouve au début de cet article.

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