JavaRush /Java Blog /Random-IT /Stiamo aggiungendo la possibilità di iscriversi a un grup...
Roman Beekeeper
Livello 35

Stiamo aggiungendo la possibilità di iscriversi a un gruppo di articoli. (Parte 3) - "Progetto Java dalla A alla Z"

Pubblicato nel gruppo Random-IT
Ciao di nuovo. Questo è l'articolo finale di STEP_6, in cui parleremo dell'aggiunta di funzionalità all'attività JRTB-6 . In questi due articoli precedenti ( parte 1 , parte 2 ) abbiamo già preparato quasi tutto ciò di cui hai bisogno. Questa parte è il culmine del processo. A tutti coloro che hanno letto questa serie di articoli fino a questo punto fin dall'inizio: grande rispetto. Ciò significa che hai abbastanza motivazione per trovare un ottimo lavoro. Ora passiamo agli affari."Progetto Java dalla A alla Z": aggiunta la possibilità di iscriversi a un gruppo di articoli.  Parte 3 - 1

Implementiamo JRTB-6

Questa volta eseguiremo l'attività dal lato del bot di Telegram, perché il lavoro sull'aggiornamento del database è finito, le entità del database sono configurate e pronte per il lavoro. Aggiungiamo un nuovo valore a CommandName - LIST_GROUP_SUB:
LIST_GROUP_SUB("/listGroupSub");
Creiamo 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);
   }
}
Qui tutto è il più semplice possibile: otteniamo l'utente utilizzando il chat_id esistente e tutte le sue iscrizioni ai gruppi verranno raccolte nel suo oggetto. Lo impostiamo nella seconda parte. Ancora una volta, ho aggiunto //todo in modo da non dimenticare di aggiungere la gestione delle eccezioni che potrebbero apparire durante il funzionamento. Il passaggio successivo è aggiornare CommandContainer aggiungendovi un nuovo comando:
put(LIST_GROUP_SUB.getCommandName(), new GroupSubListCommand(sendBotMessageService, telegramUserService))
In pratica è tutto: ora devi scrivere altri test, aggiornare il comando /help (aggiungere una descrizione per i nuovi comandi) e testare la nuova funzionalità tramite Telegram. Scriviamo un test per ListGroupSubCommand . Dato che la logica del comando non è tipica, scriveremo un test senza essere legati alla classe AbstractCommandTest , come abbiamo fatto prima:
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;
   }
}

Aggiorniamo il comando /help

Nel nostro caso, il comando /help funge da documentazione per lavorare con il bot, quindi dobbiamo ricordarci di aggiornarlo in modo che l'utente possa utilizzarlo. Abbiamo aggiunto due comandi, quindi aggiorniamo il testo che verrà:
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());
Ho aggiornato anche il testo delle risposte del bot: ho fatto in modo che con l'utente ci fosse sempre il nome per nome, altrimenti ci sarebbero sia “tu” che “tu”... Adesso sarà possibile creare almeno una sorta di connessione nel lavoro del bot.

Test del bot aggiornato

Lanciamo il nostro bot localmente e facciamo quanto segue:
  1. Eseguiamo il comando /start per essere sicuri che l'utente nel test case sia stato aggiunto al database.
  2. Eseguiamo il comando /help : controlliamo che tutto sia ok, come volevamo.
  3. Successivamente eseguiamo il comando /addGroupSub .
  4. Dall'elenco proposto di ID di gruppo, ne aggiungiamo diversi al mix.
  5. Eseguiamo il comando /listGroupSub per assicurarci che i gruppi siano registrati per l'utente.
Andare! Lanciamo il database tramite docker-compose-test.yml e avviamo il nostro SpringBoot. Successivamente, vai al nostro bot di prova ed esegui il comando /start, seguito da /help : "Progetto Java dalla A alla Z": aggiunta la possibilità di iscriversi a un gruppo di articoli.  Parte 3 - 2Successivamente, inserisci il comando /addGroupSub : "Progetto Java dalla A alla Z": aggiunta la possibilità di iscriversi a un gruppo di articoli.  Parte 3 - 3L'elenco a discesa dice che il client Java funziona come dovrebbe: abbiamo tutti i gruppi con i loro ID, una descrizione del comando aiuta (si spera) a capire di cosa abbiamo bisogno dopo, quindi aggiungiamo diversi gruppi alla sottoscrizione: "Progetto Java dalla A alla Z": aggiunta la possibilità di iscriversi a un gruppo di articoli.  Parte 3 - 4Ora abbiamo 5 sottoscrizioni, quindi possiamo eseguire il comando /listGroupSub : E poi otteniamo una specie di cosa pazzesca ... Non è chiaro il motivo per cui il titolo"Progetto Java dalla A alla Z": aggiunta la possibilità di iscriversi a un gruppo di articoli.  Parte 3 - 5 veniva visualizzato senza problemi, ma non qui. Andiamo nel database per vedere cosa c'è: nel database sono registrate le stesse domande, ma solo per quelle con l'alfabeto cirillico. Ciò significa che c'è qualche problema con la codifica. A quanto pare, è necessario configurare il database e il driver per la connessione al database. Abbiamo bisogno di UTF-8. Ma come aggiungerlo? Dopo diversi minuti di ricerca su Internet, ho trovato : il driver deve aggiornare la variabile URL. E per impostare un'immagine docker in docker-compose, il primo collegamento , ma la risposta non è la prima)) Pertanto, sapendo questo, aggiorniamo le proprietà e i file docker-compose. "Progetto Java dalla A alla Z": aggiunta la possibilità di iscriversi a un gruppo di articoli.  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
Dopo questi aggiornamenti, è necessario cancellare tutti i dati nel database e ricominciare da capo. Cancellare è molto semplice: è necessario eseguire il comando: docker-compose -f docker-compose-test.yml down dopo il quale tutti i dati e il database verranno eliminati. Ed eseguilo di nuovo, con la codifica aggiornata: docker-compose -f docker-compose-test.uml up Il database è pronto. Lanciamo l'applicazione aggiornata e diamo un'occhiata. Lo esaminerò rapidamente e ti mostrerò il risultato: "Progetto Java dalla A alla Z": aggiunta la possibilità di iscriversi a un gruppo di articoli.  Parte 3 - 7e ora abbiamo ottenuto esattamente quello che volevamo. Ora, questa sembra la verità.

Fine

Ora penso che possiamo completare questo passaggio. È stato fatto molto, davvero molto. Aggiorniamo la versione dell'applicazione a 0.5.0-SNAPSHOT e RELEASE_NOTES.
# Note di rilascio ## 0.5.0-SNAPSHOT * JRTB-5: aggiunta la possibilità di iscriversi al gruppo * JRTB-6: aggiunta la possibilità di ottenere un elenco di iscrizioni ai gruppi.
Quindi tutto è come al solito: creiamo un nuovo commit con tutte le modifiche. La cosa principale è aggiungere una descrizione delle due attività completate durante questa fase a scopo di reporting. Quindi ecco il commento:
STEP_6 JRTB-5: aggiunta possibilità di iscriversi al gruppo JRTB-6: aggiunta possibilità di vedere l'elenco degli iscritti al gruppo.
Ciò ha comportato la modifica di 47 file... È un grande cambiamento. Anche se non puoi dirlo dalla descrizione della funzionalità. Dopotutto, per comprendere appieno, è necessario sapere che è necessario scrivere un client Java per l'API, aggiornando essenzialmente l'intera applicazione. Ecco come funziona, lavorando sul server: c'è molto lavoro, ma la visibilità dal lato client è piccola...)) Amici, tradizionalmente vi offro un modo per mostrare interesse per il mio lavoro: iscrivetevi a GitHub account , unisciti al canale Telegram e scrivi una domanda sull'articolo, se qualcosa non è chiaro! Ecco un collegamento alla richiesta pull con le modifiche per questo STEP_6 . Grazie a tutti per aver letto. Altro in arrivo: parliamo dell'eliminazione di un abbonamento, della disattivazione di un profilo e altro ancora. Non cambiare))

Un elenco di tutti i materiali della serie si trova all'inizio di questo articolo.

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