你好,我們又見面了。這是 STEP_6 的最後一篇文章,我們將討論在其中討論為JRTB-6任務添加功能。在前面的兩篇文章(第 1 部分、第 2 部分)中,我們已經準備好了您所需的幾乎所有內容。這部分是過程的高潮。對於所有從一開始就讀過本系列文章的人,我們深表敬意。這意味著您有足夠的動力去找到一份好工作。現在讓我們言歸正傳吧。
我們實作 JRTB-6
這次我們將從電報機器人一側執行任務,因為更新資料庫的工作已全部完成,資料庫實體已配置並準備好工作。讓我們為CommandName新增一個新值- LIST_GROUP_SUB:LIST_GROUP_SUB("/listGroupSub");
讓我們建立一個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);
}
}
這裡一切都盡可能簡單 - 我們使用現有的 chat_id 來獲取用戶,並且他對群組的所有訂閱都將收集在他的物件中。我們在第二部分中對此進行了設定。再次,我添加了//todo,這樣我就不會忘記添加對操作期間可能出現的異常的處理。下一步是透過向 CommandContainer 新增指令來更新 CommandContainer :
put(LIST_GROUP_SUB.getCommandName(), new GroupSubListCommand(sendBotMessageService, telegramUserService))
基本上就是這樣:現在您需要編寫更多測試,更新/help命令(添加新命令的描述)並透過 Telegram 測試新功能。讓我們為ListGroupSubCommand寫一個測試。由於命令的邏輯並不典型,因此我們將編寫一個測試,而不是像之前那樣 綁定到AbstractCommandTest類別:
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;
}
}
讓我們更新 /help 指令
在我們的例子中,/help命令充當使用機器人的文檔,因此我們必須記住更新它,以便用戶可以使用它。我們新增了兩個命令,所以讓我們更新即將出現的文字: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());
我還更新了機器人回應的文字:我這樣做是為了始終與用戶使用名字,否則就會有「你」和「你」......現在至少可以創建機器人工作中的某種聯繫。
測試更新後的機器人
我們在本地啟動我們的機器人並執行以下操作:- 我們執行/start命令以確保測試案例中的用戶已添加到資料庫中。
- 我們執行/help命令 - 我們檢查一切是否正常,如我們所願。
- 接下來我們執行/addGroupSub指令。
- 從建議的群組 ID 清單中,我們新增了幾個群組 ID。
- 我們執行/listGroupSub命令以確保群組已註冊給使用者。
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
在這些更新之後,您需要刪除資料庫中的所有資料並重新開始。擦除非常簡單:您需要執行指令: docker-compose -f docker-compose-test.yml down ,然後所有資料和資料庫都會被刪除。並使用更新的編碼再次運行它: docker-compose -f docker-compose-test.uml up 資料庫已準備就緒。讓我們啟動更新的應用程式並看一下。我將快速瀏覽一遍並向您展示結果:現在我們得到了我們想要的結果。現在這看起來像是事實。
結尾
現在我想我們可以完成這一步了。已經做了很多,真的很多。讓我們將應用程式版本更新為0.5.0-SNAPSHOT和 RELEASE_NOTES。
# 發行說明 ## 0.5.0-SNAPSHOT * JRTB-5:新增了群組訂閱功能 * JRTB-6:新增了取得群組訂閱清單的功能。
然後一切都像往常一樣:我們建立一個包含所有變更的新提交。主要是添加此步驟中完成的兩項任務的描述以用於報告目的。所以這是評論:
STEP_6 JRTB-5:新增了訂閱群組的功能 JRTB-6:新增了查看群組訂閱清單的功能。
這導致了 47 個文件的更改...這是一個很大的變化。雖然你無法從功能描述中看出。畢竟,要了解完整的深度,您需要知道您需要為 API 編寫 Java 用戶端,本質上是更新整個應用程式。事情就是這樣,在伺服器上工作 - 有很多工作,但客戶端的可見性很小...)) 朋友,我傳統上為您提供一種對我的工作表現出興趣的方法 - 訂閱github帳戶,加入電報頻道並寫下有關文章的問題,如果有不清楚的地方! 以下是拉取請求的鏈接,其中包含此STEP_6的更改。感謝大家的閱讀。更多內容即將推出 - 讓我們討論一下刪除訂閱、停用設定檔等等。不要切換))
GO TO FULL VERSION