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.
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:- Eseguiamo il comando /start per essere sicuri che l'utente nel test case sia stato aggiunto al database.
- Eseguiamo il comando /help : controlliamo che tutto sia ok, come volevamo.
- Successivamente eseguiamo il comando /addGroupSub .
- Dall'elenco proposto di ID di gruppo, ne aggiungiamo diversi al mix.
- Eseguiamo il comando /listGroupSub per assicurarci che i gruppi siano registrati per l'utente.
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: e 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))
GO TO FULL VERSION