Halo kabeh, kanca-kanca sing daktresnani, Insinyur Perangkat Lunak Senior ing mangsa ngarep. Kita terus ngembangake bot telegram. Ing langkah proyek iki, kita bakal nimbang telung tugas sing duwe nilai luwih katon tinimbang nilai program. Kita kudu sinau carane mbusak langganan artikel anyar saka grup tartamtu: gunakake perintah / stop kanggo mateni bot, lan gunakake perintah / start kanggo ngaktifake. Kajaba iku, kabeh panjalukan lan nganyari mung ditrapake kanggo pangguna aktif bot. Kaya biasane, kita bakal nganyari cabang utama kanggo entuk kabeh owah-owahan lan nggawe sing anyar: STEP_7_JRTB-7. Ing bagean iki, kita bakal ngomong babagan mbusak langganan lan nimbang opsi 5 kanggo acara - bakal menarik.
Kita nganyari versi proyek kita menyang 0.6.0-SNAPSHOT Kita nganyari RELEASE_NOTES.md, nambahake katrangan babagan apa sing wis ditindakake ing versi anyar:
kaya - langganan - muni lonceng, menehi proyek kita lintang , nulis komentar lan menehi rating artikel! Matur nuwun kanggo kabeh. Nganti bagean sabanjure. Kita bakal ngomong babagan carane nambahake panonaktifan lan aktivasi bot liwat perintah / stop & / start lan cara paling apik nggunakake. Ketemu maneh!
JRTB-7: mbusak langganan artikel anyar saka grup
Cetha yen kabeh pangguna pengin bisa mbusak langganan supaya ora nampa kabar babagan artikel anyar. Logika bakal padha banget karo logika nambah langganan. Yen kita ngirim mung siji printah, nanggepi kita bakal nampa dhaptar grup lan ID sing pangguna wis langganan, supaya kita bisa ngerti apa persis sing kudu dibusak. Lan yen pangguna ngirim ID grup bebarengan karo tim, kita bakal mbusak langganan. Mula, ayo gawe perintah iki saka sisih bot telegram.-
Ayo nambah jeneng printah anyar - /deleteGroupSub , lan ing CommandName - baris:
DELETE_GROUP_SUB("/deleteGroupSub")
-
Sabanjure, ayo gawe perintah DeleteGroupSubCommand :
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.GroupSubService; import com.github.javarushcommunity.jrtb.service.SendBotMessageService; import com.github.javarushcommunity.jrtb.service.TelegramUserService; import org.springframework.util.CollectionUtils; import org.telegram.telegrambots.meta.api.objects.Update; import javax.ws.rs.NotFoundException; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import static com.github.javarushcommunity.jrtb.command.CommandName.DELETE_GROUP_SUB; import static com.github.javarushcommunity.jrtb.command.CommandUtils.getChatId; import static com.github.javarushcommunity.jrtb.command.CommandUtils.getMessage; import static java.lang.String.format; import static org.apache.commons.lang3.StringUtils.SPACE; import static org.apache.commons.lang3.StringUtils.isNumeric; /** * Delete Group subscription {@link Command}. */ public class DeleteGroupSubCommand implements Command { private final SendBotMessageService sendBotMessageService; private final TelegramUserService telegramUserService; private final GroupSubService groupSubService; public DeleteGroupSubCommand(SendBotMessageService sendBotMessageService, GroupSubService groupSubService, TelegramUserService telegramUserService) { this.sendBotMessageService = sendBotMessageService; this.groupSubService = groupSubService; this.telegramUserService = telegramUserService; } @Override public void execute(Update update) { if (getMessage(update).equalsIgnoreCase(DELETE_GROUP_SUB.getCommandName())) { sendGroupIdList(getChatId(update)); return; } String groupId = getMessage(update).split(SPACE)[1]; String chatId = getChatId(update); if (isNumeric(groupId)) { Optional<GroupSub> optionalGroupSub = groupSubService.findById(Integer.valueOf(groupId)); if (optionalGroupSub.isPresent()) { GroupSub groupSub = optionalGroupSub.get(); TelegramUser telegramUser = telegramUserService.findByChatId(chatId).orElseThrow(NotFoundException::new); groupSub.getUsers().remove(telegramUser); groupSubService.save(groupSub); sendBotMessageService.sendMessage(chatId, format("Удалил подписку на группу: %s", groupSub.getTitle())); } else { sendBotMessageService.sendMessage(chatId, "Не нашел такой группы =/"); } } else { sendBotMessageService.sendMessage(chatId, "неправильный формат ID группы.\n " + "ID должно быть целым положительным числом"); } } private void sendGroupIdList(String chatId) { String message; List<GroupSub> groupSubs = telegramUserService.findByChatId(chatId) .orElseThrow(NotFoundException::new) .getGroupSubs(); if (CollectionUtils.isEmpty(groupSubs)) { message = "Пока нет подписок на группы. Whatбы добавить подписку напиши /addGroupSub"; } else { message = "Whatбы удалить подписку на группу - передай комадну вместе с ID группы. \n" + "Например: /deleteGroupSub 16 \n\n" + "я подготовил список всех групп, на которые ты подписан) \n\n" + "Name группы - ID группы \n\n" + "%s"; } String userGroupSubData = groupSubs.stream() .map(group -> format("%s - %s \n", group.getTitle(), group.getId())) .collect(Collectors.joining()); sendBotMessageService.sendMessage(chatId, format(message, userGroupSubData)); } }
@Data
@Entity
@Table(name = "tg_user")
@EqualsAndHashCode(exclude = "groupSubs")
public class TelegramUser {
@Id
@Column(name = "chat_id")
private String chatId;
@Column(name = "active")
private boolean active;
@ManyToMany(mappedBy = "users", fetch = FetchType.EAGER)
private List<GroupSub> groupSubs;
}
Akibaté, kabeh njupuk mati kaya kita wanted. Ana sawetara acara sing bisa ditindakake ing tim, mula nulis tes sing apik kanggo saben-saben minangka ide sing apik. Ngomong babagan tes: nalika aku nulis, aku nemokake cacat ing logika lan mbenerake sadurunge dirilis menyang produksi. Yen ora ana tes, ora jelas sepira cepet bisa dideteksi. DeleteGroupSubCommandTest:
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.GroupSubService;
import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.github.javarushcommunity.jrtb.service.TelegramUserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.telegram.telegrambots.meta.api.objects.Update;
import java.util.ArrayList;
import java.util.Optional;
import static com.github.javarushcommunity.jrtb.command.AbstractCommandTest.prepareUpdate;
import static com.github.javarushcommunity.jrtb.command.CommandName.DELETE_GROUP_SUB;
import static java.util.Collections.singletonList;
@DisplayName("Unit-level testing for DeleteGroupSubCommand")
class DeleteGroupSubCommandTest {
private Command command;
private SendBotMessageService sendBotMessageService;
GroupSubService groupSubService;
TelegramUserService telegramUserService;
@BeforeEach
public void init() {
sendBotMessageService = Mockito.mock(SendBotMessageService.class);
groupSubService = Mockito.mock(GroupSubService.class);
telegramUserService = Mockito.mock(TelegramUserService.class);
command = new DeleteGroupSubCommand(sendBotMessageService, groupSubService, telegramUserService);
}
@Test
public void shouldProperlyReturnEmptySubscriptionList() {
//given
Long chatId = 23456L;
Update update = prepareUpdate(chatId, DELETE_GROUP_SUB.getCommandName());
Mockito.when(telegramUserService.findByChatId(String.valueOf(chatId)))
.thenReturn(Optional.of(new TelegramUser()));
String expectedMessage = "Пока нет подписок на группы. Whatбы добавить подписку напиши /addGroupSub";
//when
command.execute(update);
//then
Mockito.verify(sendBotMessageService).sendMessage(chatId.toString(), expectedMessage);
}
@Test
public void shouldProperlyReturnSubscriptionLit() {
//given
Long chatId = 23456L;
Update update = prepareUpdate(chatId, DELETE_GROUP_SUB.getCommandName());
TelegramUser telegramUser = new TelegramUser();
GroupSub gs1 = new GroupSub();
gs1.setId(123);
gs1.setTitle("GS1 Title");
telegramUser.setGroupSubs(singletonList(gs1));
Mockito.when(telegramUserService.findByChatId(String.valueOf(chatId)))
.thenReturn(Optional.of(telegramUser));
String expectedMessage = "Whatбы удалить подписку на группу - передай комадну вместе с ID группы. \n" +
"Например: /deleteGroupSub 16 \n\n" +
"я подготовил список всех групп, на которые ты подписан) \n\n" +
"Name группы - ID группы \n\n" +
"GS1 Title - 123 \n";
//when
command.execute(update);
//then
Mockito.verify(sendBotMessageService).sendMessage(chatId.toString(), expectedMessage);
}
@Test
public void shouldRejectByInvalidGroupId() {
//given
Long chatId = 23456L;
Update update = prepareUpdate(chatId, String.format("%s %s", DELETE_GROUP_SUB.getCommandName(), "groupSubId"));
TelegramUser telegramUser = new TelegramUser();
GroupSub gs1 = new GroupSub();
gs1.setId(123);
gs1.setTitle("GS1 Title");
telegramUser.setGroupSubs(singletonList(gs1));
Mockito.when(telegramUserService.findByChatId(String.valueOf(chatId)))
.thenReturn(Optional.of(telegramUser));
String expectedMessage = "неправильный формат ID группы.\n " +
"ID должно быть целым положительным числом";
//when
command.execute(update);
//then
Mockito.verify(sendBotMessageService).sendMessage(chatId.toString(), expectedMessage);
}
@Test
public void shouldProperlyDeleteByGroupId() {
//given
/// prepare update object
Long chatId = 23456L;
Integer groupId = 1234;
Update update = prepareUpdate(chatId, String.format("%s %s", DELETE_GROUP_SUB.getCommandName(), groupId));
GroupSub gs1 = new GroupSub();
gs1.setId(123);
gs1.setTitle("GS1 Title");
TelegramUser telegramUser = new TelegramUser();
telegramUser.setChatId(chatId.toString());
telegramUser.setGroupSubs(singletonList(gs1));
ArrayList<TelegramUser> users = new ArrayList<>();
users.add(telegramUser);
gs1.setUsers(users);
Mockito.when(groupSubService.findById(groupId)).thenReturn(Optional.of(gs1));
Mockito.when(telegramUserService.findByChatId(String.valueOf(chatId)))
.thenReturn(Optional.of(telegramUser));
String expectedMessage = "Удалил подписку на группу: GS1 Title";
//when
command.execute(update);
//then
users.remove(telegramUser);
Mockito.verify(groupSubService).save(gs1);
Mockito.verify(sendBotMessageService).sendMessage(chatId.toString(), expectedMessage);
}
@Test
public void shouldDoesNotExistByGroupId() {
//given
Long chatId = 23456L;
Integer groupId = 1234;
Update update = prepareUpdate(chatId, String.format("%s %s", DELETE_GROUP_SUB.getCommandName(), groupId));
Mockito.when(groupSubService.findById(groupId)).thenReturn(Optional.empty());
String expectedMessage = "Не нашел такой группы =/";
//when
command.execute(update);
//then
Mockito.verify(groupSubService).findById(groupId);
Mockito.verify(sendBotMessageService).sendMessage(chatId.toString(), expectedMessage);
}
}
Ing kene, saben tes mriksa skenario sing kapisah, lan aku ngelingake sampeyan, mung ana lima:
- nalika sampeyan mung ngliwati printah /deleteGroupSub lan ora ana langganan grup;
- nalika sampeyan mung ngliwati perintah /deleteGroupSub lan ana langganan grup;
- nalika ID grup sing ora bener diwarisake, contone, /deleteGroupSub abc ;
- skenario sing kabeh wis dibusak kanthi bener, kaya sing dikarepake;
- skenario nalika ID grup bener, nanging grup kuwi ora ing database.
.put(DELETE_GROUP_SUB.getCommandName(),
new DeleteGroupSubCommand(sendBotMessageService, groupSubService, telegramUserService))
Saiki sampeyan bisa nyoba fungsi ing bot test. Kita miwiti database nggunakake docker-compose-test.yml: docker-compose -f docker-compose-test.yml munggah Lan miwiti SpringBoot liwat IDEA. Aku bakal rampung mbusak Correspondence karo bot lan miwiti maneh. Aku bakal mbukak kabeh opsi sing bisa kedadeyan nalika nggarap tim iki. Minangka sampeyan bisa ndeleng saka gambar, kabeh opsi wis rampung lan sukses.
Kanca-kanca! Apa sampeyan pengin langsung ngerti nalika kode anyar kanggo proyek dirilis? Kapan artikel anyar metu? Gabung saluran Telegramku . Ing kana aku ngumpulake artikel, pikirane lan pangembangan open source bebarengan. |
## 0.6.0-SNAPSHOT * JRTB-7: nambahake kemampuan kanggo mbusak langganan grup.
Kode bisa digunakake, tes wis ditulis kanggo: wektune kanggo push tugas menyang gudang lan nggawe panjalukan narik.
GO TO FULL VERSION