היי שוב. זהו המאמר האחרון מתוך 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 על ידי הוספת פקודה חדשה אליו:
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 .
- מתוך הרשימה המוצעת של מזהי קבוצות, אנו מוסיפים כמה לתמהיל.
- אנו מפעילים את הפקודה /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 למטה ולאחר מכן כל הנתונים ומסד הנתונים נמחקים. והפעל אותו שוב, עם הקידוד המעודכן: 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 קבצים שהשתנו... זה שינוי גדול. למרות שאתה לא יכול לדעת מהתיאור של הפונקציונליות. אחרי הכל, כדי להבין את מלוא העומק, אתה צריך לדעת שאתה צריך לכתוב לקוח Java עבור ה-API, בעצם עדכון היישום כולו. ככה זה, עבודה על שרת - יש הרבה עבודה, אבל הנראות מצד הלקוח קטנה...)) חברים, אני מציע לכם באופן מסורתי דרך לגלות עניין בעבודה שלי - הירשמו ל- github חשבון , הצטרף לערוץ הטלגרם וכתוב שאלה על המאמר, אם משהו לא ברור! הנה קישור לבקשת המשיכה עם שינויים עבור STEP_6 זה . תודה לכולם על הקריאה. עוד יבואו - בואו נדבר על מחיקת מנוי, ביטול פרופיל ועוד. אל תחליף))
GO TO FULL VERSION