JavaRush /Блоги Java /Random-TG /Мо обуна ба мақолаҳоро аз гурӯҳ хориҷ мекунем - "Лоиҳаи J...
Roman Beekeeper
Сатҳи

Мо обуна ба мақолаҳоро аз гурӯҳ хориҷ мекунем - "Лоиҳаи Java аз A то Я"

Дар гурӯҳ нашр шудааст
Салом ба ҳама, дӯстони азизи ман, муҳандисони калони ояндаи нармафзор. Мо таҳияи боти телеграммаро идома медиҳем. Дар ин қадами лоиҳаи мо мо се вазифаеро баррасӣ хоҳем кард, ки нисбат ба арзиши барнома арзиши намоёнтар доранд. Мо бояд чӣ гуна нест кардани обуна ба мақолаҳои навро аз гурӯҳи мушаххас омӯзем: барои хомӯш кардани бот фармони /stop ва барои фаъол кардани он фармони /start -ро истифода баред . Гузашта аз ин, ҳама дархостҳо ва навсозиҳо танҳо ба корбарони фаъоли бот дахл доранд. Мисли маъмул, мо шохаи асосиро навсозӣ мекунем , то ҳама тағиротҳоро ба даст орем ва як нав эҷод кунем: STEP_7_JRTB-7. Дар ин қисм, мо дар бораи нест кардани обуна сӯҳбат мекунем ва 5 варианти рӯйдодҳоро баррасӣ мекунем - ин ҷолиб хоҳад буд.

JRTB-7: хориҷ кардани обуна ба мақолаҳои нав аз гурӯҳ

Маълум аст, ки ҳама корбарон мехоҳанд, ки обунаи худро тоза кунанд, то дар бораи мақолаҳои нав огоҳӣ нагиранд. Мантиқи он ба мантиқи илова кардани обуна хеле монанд хоҳад буд. Агар мо танҳо як фармон фиристем, дар ҷавоб мо рӯйхати гурӯҳҳо ва ID-ҳои онҳоро мегирем, ки корбар аллакай ба онҳо обуна шудааст, то мо фаҳмем, ки маҳз чӣ бояд ҳазф карда шавад. Ва агар корбар ID-и гурӯҳро ҳамроҳи даста фиристад, мо обунаро нест мекунем. Аз ин рӯ, биёед ин фармонро аз ҷониби боти телеграмма таҳия кунем.
  1. Биёед номи фармони навро илова кунем - /deleteGroupSub ва дар CommandName - сатр:

    DELETE_GROUP_SUB("/deleteGroupSub")

  2. Баъд, биёед фармони 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));
       }
    }

Барои ин ба мо лозим омад, ки боз ду усули кор бо an objectи GroupSub - аз базаи маълумот гирифтан бо ID ва захира кардани худи an object илова кунем. Ҳамаи ин усулҳо танҳо усулҳои репозиторийии тайёрро меноманд. Ман ба шумо дар бораи нест кардани обуна ба шумо алоҳида мегӯям. Дар схемаи пойгоҳи додаҳо ин ҷадвалест, ки барои раванди бисёр ба бисёр масъул аст ва барои нест кардани ин муносибат шумо бояд сабти онро нест кунед. Ин аст, агар мо фаҳмиши умумиро дар бораи пойгоҳи додаҳо истифода барем. Аммо мо маълумоти Spring-ро истифода мебарем ва дар ҳолати нобаёнӣ Hibernate мавҷуд аст, ки ин корро ба таври дигар иҷро карда метавонад. Мо an objectи GroupSub-ро мегирем, ки ҳамаи корбарони бо он алоқаманд ба он ҷалб карда мешаванд. Аз ин маҷмӯаи корбарон мо онеро, ки ба мо лозим аст, хориҷ мекунем ва groupSub-ро дубора дар базаи маълумот захира мекунем, аммо бидуни ин корбар. Ҳамин тавр Spring Data мефаҳмад, ки мо чӣ мехостем ва сабтро нест мекунем. "Лоиҳаи Java аз А то Я": Хориҷ кардани обуна ба мақолаҳо аз гурӯҳ - 1"Лоиҳаи Java аз А то Я": Хориҷ кардани обуна ба мақолаҳо аз гурӯҳ - 2Барои зуд хориҷ кардани корбар, ман шарҳи EqualsAndHashCode-ро барои TelegramUser илова кардам, ба истиснои рӯйхати GroupSub, то ҳеҷ мушкиле пеш наояд. Ва усули хориҷкуниро дар ҷамъоварии корбарон бо корбаре, ки ба мо лозим аст, номид. Ин барои TelegramUser чунин аст:
@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;
}
Дар натиҷа, ҳама чиз ҳамон тавре ки мо мехостем, сурат гирифт. Дар як даста якчанд рӯйдодҳои имконпазир мавҷуданд, бинобар ин навиштани санҷиши хуб барои ҳар яки онҳо як идеяи олӣ аст. Дар бораи санчишхо сухан меронам: хангоми навиштани онхо дар мантик камбудй пайдо карда, пеш аз ба истехсолот баровардани он ислох кардам. Агар озмоиш намебуд, маълум нест, ки он то чӣ андоза зуд ошкор мешуд. 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);
   }
}
Дар ин ҷо, ҳар як санҷиш сенарияи алоҳидаро тафтиш мекунад ва ба шумо хотиррасон мекунам, ки танҳо панҷтои онҳо мавҷуданд:
  • вақте ки шумо танҳо фармони /deleteGroupSub- ро гузаштед ва обунаҳои гурӯҳӣ вуҷуд надоранд;
  • вақте ки шумо танҳо фармони /deleteGroupSub- ро гузаштед ва ба гурӯҳҳо обунаҳо мавҷуданд;
  • вақте ки ID-и гурӯҳи беэътибор гузаронида шуд, масалан, /deleteGroupSub abc ;
  • сенарияе, ки дар он ҳама чиз тавре ки интизор мерафт, дуруст нест карда мешавад;
  • сенарияе, ки ID-и гурӯҳ дуруст аст, аммо чунин гурӯҳ дар пойгоҳи додаҳо нест.
Тавре ки шумо мебинед, ҳамаи ин сенарияҳо бояд бо санҷишҳо фаро гирифта шаванд. Ҳангоми навиштан ман фаҳмидам, ки барои навиштани санҷишҳои беҳтар, бояд курсҳои санҷиширо гузаронам. Ман фикр мекунам, ки ин барои дуруст ҷустуҷӯ кардани вариантҳои гуногун кӯмак хоҳад кард. Ин дуруст аст, фикрҳо барои оянда. Баъдан, шумо бояд ба фармони /help тавсиф илова кунед , ки шумо ҳоло метавонед обунаро нест кунед. Биёед онро дар бахши кор бо абонементҳо ҷойгир кунем. "Лоиҳаи Java аз А то Я": Хориҷ кардани обуна ба мақолаҳо аз гурӯҳ - 3Албатта, барои кор кардани ин фармон, шумо бояд оғозкунии онро ба CommandContainer илова кунед :
.put(DELETE_GROUP_SUB.getCommandName(),
       new DeleteGroupSubCommand(sendBotMessageService, groupSubService, telegramUserService))
Акнун шумо метавонед функсияро дар боти санҷишӣ санҷед. Мо пойгоҳи додаи худро бо истифода аз docker-compose-test.yml оғоз мекунем: docker-compose -f docker-compose-test.yml up Ва SpringBoot-ро тавассути IDEA оғоз мекунем. Ман мукотибаро бо бот комилан тоза мекунам ва аз нав оғоз мекунам. Ман тамоми вариантҳоеро, ки ҳангоми кор бо ин даста пайдо мешаванд, меомӯзам. "Лоиҳаи Java аз А то Я": Хориҷ кардани обуна ба мақолаҳо аз гурӯҳ - 4Тавре ки шумо аз скриншот мебинед, ҳама вариантҳо гузаштанд ва муваффақ шуданд.
Рафикон! Оё шумо мехоҳед фавран бидонед, ки рамзи нав барои лоиҳа кай бароварда мешавад? Мақолаи нав кай мебарояд? Телеграм каналимга аъзо бўлинг . Дар он ҷо ман мақолаҳо, фикрҳо ва таҳияи сарчашмаҳои кушодаи худро якҷоя ҷамъ мекунам.
Мо versionи лоиҳаи худро ба 0.6.0-SNAPSHOT навсозӣ мекунем.
## 0.6.0-SNAPSHOT * JRTB-7: қобorяти нест кардани обунаи гурӯҳро илова кард.
Рамз кор мекунад, барои он санҷишҳо навишта шудаанд: вақти он расидааст, ки вазифаро ба анбор тела диҳед ва дархости кашиданро эҷод кунед."Лоиҳаи Java аз А то Я": Хориҷ кардани обуна ба мақолаҳо аз гурӯҳ - 5

Ба ҷои хотима додан

Мо муддати тӯлонӣ ба тахтаи лоиҳаи худ нигоҳ накардаем, аммо тағйироти калон ба амал омаданд: "Лоиҳаи Java аз A то Я": Хориҷ кардани обуна ба мақолаҳо аз гурӯҳ - 6Ҳамагӣ 5 вазифа боқӣ мондааст. Яъне ману шумо аллакай дар охири роҳ ҳастем. Каме монда. Бахусус қайд кардан ҷолиб аст, ки ин силсила мақолаҳо аз нимаи моҳи сентябр, яъне 7 моҳ идома доранд!!! Вақте ки ман ин идеяро пайдо кардам, ман интизор набудам, ки ин қадар тӯлонӣ мегирад. Дар айни замон, ман аз натиҷа хеле қаноатмандам! Дӯстон, агар маълум набошад, ки дар мақола чӣ рӯй медиҳад, дар шарҳҳо саволҳо диҳед. Ҳамин тавр ман медонам, ки чизе бояд беҳтар тавсиф карда шавад ва чизе ба шарҳи иловагӣ ниёз дорад. Хуб, чун маъмул, лайк - обуна шавед - занг занед, ба лоиҳаи мо ситора диҳед , шарҳҳо нависед ва ба мақола баҳо диҳед! Ташаккур ба ҳама. То қисми оянда. Мо ба зудӣ дар бораи чӣ гуна илова кардани ғайрифаъолкунӣ ва фаъолсозии бот тавассути фармонҳои /stop & /start ва чӣ гуна беҳтар истифода бурдани онҳо сӯҳбат хоҳем кард. То дидор!

Рӯйхати ҳамаи маводҳои силсила дар аввали ин мақола аст.

Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION