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.
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 :- 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.
- Nous exécutons la commande /help - nous vérifions que tout va bien, comme nous le souhaitions.
- Ensuite, nous exécutons la commande /addGroupSub .
- À partir de la liste proposée d’identifiants de groupe, nous en ajoutons plusieurs au mélange.
- Nous exécutons la commande /listGroupSub pour nous assurer que les groupes sont enregistrés auprès de l'utilisateur.
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 : et 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))
GO TO FULL VERSION