JavaRush /Блоги Java /Random-TG /Биёед намунаи фармонро барои кор бо бот амалӣ кунем. (Қис...
Roman Beekeeper
Сатҳи

Биёед намунаи фармонро барои кор бо бот амалӣ кунем. (Қисми 1) - "Лоиҳаи Java аз А то Я"

Дар гурӯҳ нашр шудааст
Салом ба хама, дустони азиз. Имрӯз мо як қолабро (шаблон намуна аст, дар контексти мо ин ҳамон чизест) тарҳи Фармонро барои эҳтиёҷоти худ амалӣ хоҳем кард. Бо истифода аз ин қолаб, мо бо коркарди фармонҳои боти худ бароҳат ва дуруст кор хоҳем кард. "Лоиҳаи Java аз A то Я": Амалисозии намунаи фармон барои кор бо бот.  Қисми 1 - 1
Дӯстон, ба шумо лоиҳаи Javarush Telegram Bot маъқул аст ? Танбал нашавед: ба он ситора диҳед . Бо ин роҳ маълум мешавад, ки ӯ ҷолиб аст ва инкишоф додани ӯ гуворотар хоҳад буд!
Барои оғоз, хуб мебуд, ки дар бораи он чӣ гуна намуна аст - Фармон. Аммо агар ин корро кунам, мақола хеле калон ва душвор хоҳад буд. Аз ин рӯ, ман маводҳоро барои омӯзиши мустақилона интихоб кардам:
  1. Ин мақолаи ман аз 4 сол пеш аст. Ман онро дар синни хурдсолӣ навишта будам, бинобар ин онро сахт доварӣ накунед.
  2. Видеои як шведи хеле эҳсосотӣ ва интерактивӣ дар YouTube. Ман онро хеле тавсия медиҳам. Ӯ зебо сухан мегӯяд, забони англисӣ равшан ва фаҳмо аст. Ва дар маҷмӯъ, ӯ дар бораи дигар намунаҳои тарроҳӣ видео дорад.
  3. Дар шарҳҳои мақолаи ман, касе Nullptr35 ин видеоро тавсия додааст .
Ин бояд кофӣ бошад, ки худро ба мавзӯъ ғарқ кунед ва дар як саҳифа бо ман бошед. Хуб, онҳое, ки бо ин намунаи тарроҳӣ ошно ҳастанд, метавонанд бехатар гузаред ва идома диҳанд.

Мо JRTB-3 менависем

Ҳама чиз мисли пештара аст:
  1. Мо фorали асосиро навсозӣ мекунем.
  2. Дар асоси шохаи асосии навшуда, мо JRTB-3-и навро эҷод мекунем .
  3. Биёед намунаро амалӣ кунем.
  4. Мо як ӯҳдадории нав эҷод мекунем, ки кори анҷомшударо тавсиф мекунад.
  5. Мо дархости ҷалб эҷод мекунем, онро тафтиш мекунем ва агар ҳама чиз хуб бошад, мо кори худро якҷоя мекунем.
Ман нуктаҳои 1-2-ро нишон намедиҳам: Ман онҳоро дар мақолаҳои қаблӣ хеле бодиққат тавсиф кардам, аз ин рӯ биёед мустақиман ба татбиқи қолаб равем. Чаро ин қолаб барои мо мувофиқ аст? Бале, зеро ҳар дафъае, ки мо фармонро иҷро мекунем, мо ба усули onUpdateReceived(Update update) мегузарем ва вобаста ба фармон мо мантиқи гуногунро иҷро мекунем. Бе ин намуна, мо як қатор изҳороти if-else if-ро дорем. Чизе монанди ин:
if (message.startsWith("/start")) {
   doStartCommand();
} else if(message.startsWith("/stop")) {
   doStopCommand();
} else if(message.startsWith("/addUser")) {
   doAddUserCommand();
}
...
else if(message.startsWith("/makeMeHappy")) {
   doMakeMeHappyCommand();
}
Гузашта аз ин, дар он ҷое, ки эллипс вуҷуд дорад, шояд даҳҳо дастаҳои дигар вуҷуд дошта бошанд. Ва чӣ гуна бояд ин корро муқаррарӣ кард? Чӣ тавр бояд дастгирӣ кард? Мушкил ва душвор. Ин маънои онро дорад, ки ин вариант ба мо мувофиқ нест. Он бояд чунин бошад:
if (message.startsWith(COMMAND_PREFIX)) {
   String commandIdentifier = message.split(" ")[0].toLowerCase();
   commandContainer.getCommand(commandIdentifier, userName).execute(update);
} else {
   commandContainer.getCommand(NO.getCommand(), userName).execute(update);
}
Ҳамааш ҳамин! Ва новобаста аз он ки мо чӣ қадар фармонҳоро илова мекунем, ин қисмати code бетағйир мемонад. Ӯ чӣ кор мекунад? Аввалин агар боварӣ ҳосил кунад, ки паём бо префикси фармони "/" оғоз мешавад. Агар ин тавр бошад, пас мо сатри то фосилаи аввалро интихоб мекунем ва дар CommandContainer фармони мувофиқро меҷӯем; баробари пайдо кардани он, мо фармонро иҷро мекунем. Ва ин ҳама аст...) Агар шумо хоҳиш ва вақт дошта бошед, шумо метавонед кор бо дастаҳоро, аввал дар як синф якбора, бо як қатор шартҳо ва ҳама чизҳо ва баъд бо истифода аз қолаб амалӣ кунед. Шумо фарқиятро хоҳед дид. Чӣ зебоӣ хоҳад буд! Аввалан, биёед дар паҳлӯи бастаи бот бастаеро созем, ки он фармон номида мешавад . "Лоиҳаи Java аз A то Я": Амалисозии намунаи фармон барои кор бо бот.  Қисми 1 - 2Ва аллакай дар ин баста ҳама синфҳое мавҷуданд, ки ба иҷрои фармон марбутанд. Барои кор бо фармонҳо ба мо як интерфейс лозим аст. Барои ин, биёед онро эҷод кунем:
package com.github.javarushcommunity.jrtb.command;

import org.telegram.telegrambots.meta.api.objects.Update;

/**
* Command interface for handling telegram-bot commands.
*/
public interface Command {

   /**
    * Main method, which is executing command logic.
    *
    * @param update provided {@link Update} object with all the needed data for command.
    */
   void execute(Update update);
}
Дар ин лаҳза, ба мо лозим нест, ки амалиёти баръакси фармонро амалӣ кунем, аз ин рӯ мо ин усулро (иҷро накардан) мегузаронем. Дар усули иҷро, an objectи Навсозӣ ҳамчун далел меояд - маҳз ҳамон чизест, ки ба усули асосии мо дар бот меояд. Ин an object дорои ҳама чизест, ки барои коркарди фармон лозим аст. Минбаъд, мо рақамеро илова мекунем, ки арзишҳои фармонро нигоҳ медорад (оғоз, қатъ ва ғайра). Чаро ба мо ин лозим аст? То ки мо барои номҳои даста танҳо як манбаи ҳақиқат дорем. Мо инчунин онро дар бастаи фармонҳои худ эҷод мекунем . Биёед онро CommandName меномем :
package com.github.javarushcommunity.jrtb.command;

/**
* Enumeration for {@link Command}'s.
*/
public enum CommandName {

   START("/start"),
   STOP("/stop");

   private final String commandName;

   CommandName(String commandName) {
       this.commandName = commandName;
   }

   public String getCommandName() {
       return commandName;
   }

}
Мо инчунин ба хидмате ниёз дорем, ки тавассути бот паём фиристад. Барои ин, мо дар паҳлӯи бастаи фармон як бастаи хидматро эҷод мекунем , ки ба он ҳамаи хидматҳои заруриро илова мекунем. Дар ин ҷо ба он таваҷҷӯҳ кардан лозим аст, ки ман дар ин маврид калимаи хидматро дар назар дорам. Агар мо барномаро баррасӣ кунем, он аксар вақт ба якчанд қабатҳо тақсим мешавад: қабат барои кор бо нуқтаҳои ниҳоӣ - контроллерҳо, қабати мантиқи тиҷоратӣ - хидматҳо ва қабат барои кор бо пойгоҳи додаҳо - репозиторий. Аз ин рӯ, дар ҳолати мо, хидмат синфест, ки як навъ мантиқи тиҷоратиро амалӣ мекунад. Чӣ тавр дуруст сохтани хидмат? Аввалан, барои он интерфейс ва татбиқ эҷод кунед. Татбиқро бо истифода аз шарҳи `@Service` ба контексти замимаи барномаи SpringBoot-и мо илова кунед ва агар лозим бошад, онро бо истифода аз шарҳи `@Autowired` пурзӯр кунед. Аз ин рӯ, мо интерфейси SendBotMessageService-ро эҷод мекунем (дар номгузорӣ онҳо одатан Хизматро дар охири ном илова мекунанд):
package com.github.javarushcommunity.jrtb.service;

/**
* Service for sending messages via telegram-bot.
*/
public interface SendBotMessageService {

   /**
    * Send message via telegram bot.
    *
    * @param chatId provided chatId in which messages would be sent.
    * @param message provided message to be sent.
    */
   void sendMessage(String chatId, String message);
}
Минбаъд, мо татбиқи онро эҷод мекунем:
package com.github.javarushcommunity.jrtb.service;

import com.github.javarushcommunity.jrtb.bot.JavarushTelegramBot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

/**
* Implementation of {@link SendBotMessageService} interface.
*/
@Service
public class SendBotMessageServiceImpl implements SendBotMessageService {

   private final JavarushTelegramBot javarushBot;

   @Autowired
   public SendBotMessageServiceImpl(JavarushTelegramBot javarushBot) {
       this.javarushBot = javarushBot;
   }

   @Override
   public void sendMessage(String chatId, String message) {
       SendMessage sendMessage = new SendMessage();
       sendMessage.setChatId(chatId);
       sendMessage.enableHtml(true);
       sendMessage.setText(message);

       try {
           javarushBot.execute(sendMessage);
       } catch (TelegramApiException e) {
           //todo add logging to the project.
           e.printStackTrace();
       }
   }
}
Ин аст, ки татбиқи он ба назар мерасад. Муҳимтарин ҷодугарӣ он аст, ки дизайнер дар куҷо офарида шудааст. Бо истифода аз шарҳи @Autowired дар конструктор, SpringBoot an objectи ин синфро дар контексти татбиқи худ ҷустуҷӯ мекунад. Ва ӯ аллакай дар он ҷост. Ин чунин кор мекунад: дар замимаи мо, дар ҳама ҷо мо метавонем ба бот дастрасӣ пайдо кунем ва коре кунем. Ва ин хадамот барои фиристодани паёмҳо масъул аст. Барои он ки мо ҳар дафъа дар ҳама ҷо чунин чизе нанависем:
SendMessage sendMessage = new SendMessage();
sendMessage.setChatId(chatId);
sendMessage.setText(message);

try {
   javarushBot.execute(sendMessage);
} catch (TelegramApiException e) {
   //todo add logging to the project.
   e.printStackTrace();
}
Мо ин мантиқро ба як синфи алоҳида интиқол додем ва дар ҳолати зарурӣ аз он истифода хоҳем кард. Ҳоло мо бояд се фармонро иҷро кунем: StartCommand, StopCommand ва UnknownCommand. Мо ба онҳо ниёз дорем, то мо чизе дошта бошем, ки контейнери худро барои фармонҳо пур кунем. Дар айни замон, матнҳо хушк ва иттилоотӣ хоҳанд буд; барои ин вазифа, ин чандон муҳим нест. Ҳамин тавр, StartCommand:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import org.telegram.telegrambots.meta.api.objects.Update;

/**
* Start {@link Command}.
*/
public class StartCommand implements Command {

   private final SendBotMessageService sendBotMessageService;

   public final static String START_MESSAGE = "Привет. Я Javarush Telegram Bot. Я помогу тебе быть в курсе последних " +
           "статей тех авторов, котрые тебе интересны. Я еще маленький и только учусь.";

   // Здесь не добавляем сервис через получение из Application Context.
   // Потому что если это сделать так, то будет циклическая зависимость, которая
   // ломает работу applications.
   public StartCommand(SendBotMessageService sendBotMessageService) {
       this.sendBotMessageService = sendBotMessageService;
   }

   @Override
   public void execute(Update update) {
       sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), START_MESSAGE);
   }
}
Лутфан пеш аз таҳиякунанда шарҳҳоро бодиққат хонед. Вобастагии даврӣ ( вобастагии давравӣ ) метавонад аз сабаби меъморӣ ба амал ояд, ки он комилан дуруст нест. Дар ҳолати мо, мо боварӣ ҳосил мекунем, ки ҳама чиз кор мекунад ва дуруст аст. Ҳангоми сохтани фармон аллакай дар CommandContainer an objectи воқеӣ аз Контексти Ариза илова карда мешавад. Фармони қатъ:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import org.telegram.telegrambots.meta.api.objects.Update;

/**
* Stop {@link Command}.
*/
public class StopCommand implements Command {

   private final SendBotMessageService sendBotMessageService;

   public static final String STOP_MESSAGE = "Деактивировал все ваши подписки \uD83D\uDE1F.";

   public StopCommand(SendBotMessageService sendBotMessageService) {
       this.sendBotMessageService = sendBotMessageService;
   }

   @Override
   public void execute(Update update) {
       sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), STOP_MESSAGE);
   }
}
Ва Фармони номаълум. Чаро мо ба он ниёз дорем? Барои мо ин амри муҳимест, ки агар мо фармонеро, ки ба мо дода шудааст, наёбем, ҷавоб хоҳад дод. Мо инчунин ба NoCommand ва HelpCommand ниёз дорем.
  • NoCommand - барои вазъияте, ки паём умуман бо фармон оғоз нашавад, масъул хоҳад буд;
  • HelpCommand дастур барои корбар, як навъ ҳуҷҷатҳо хоҳад буд.
Биёед Фармони Help-ро илова кунем:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import org.telegram.telegrambots.meta.api.objects.Update;

import static com.github.javarushcommunity.jrtb.command.CommandName.*;

/**
* Help {@link Command}.
*/
public class HelpCommand implements Command {

   private final SendBotMessageService sendBotMessageService;

   public static final String HELP_MESSAGE = String.format("✨<b>Дотупные команды</b>✨\n\n"

                   + "<b>Начать\\закончить работу с ботом</b>\n"
                   + "%s - начать работу со мной\n"
                   + "%s - приостановить работу со мной\n\n"
                   + "%s - получить помощь в работе со мной\n",
           START.getCommandName(), STOP.getCommandName(), HELP.getCommandName());

   public HelpCommand(SendBotMessageService sendBotMessageService) {
       this.sendBotMessageService = sendBotMessageService;
   }

   @Override
   public void execute(Update update) {
       sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), HELP_MESSAGE);
   }
}
NoCommand:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import org.telegram.telegrambots.meta.api.objects.Update;

/**
* No {@link Command}.
*/
public class NoCommand implements Command {

   private final SendBotMessageService sendBotMessageService;

   public static final String NO_MESSAGE = "Я поддерживаю команды, начинающиеся со слеша(/).\n"
           + "Whatбы посмотреть список команд введите /help";

   public NoCommand(SendBotMessageService sendBotMessageService) {
       this.sendBotMessageService = sendBotMessageService;
   }

   @Override
   public void execute(Update update) {
       sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), NO_MESSAGE);
   }
}
Ва барои ин вазифа то ҳол Фармони номаълум мавҷуд аст:
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import org.telegram.telegrambots.meta.api.objects.Update;

/**
* Unknown {@link Command}.
*/
public class UnknownCommand implements Command {

   public static final String UNKNOWN_MESSAGE = "Не понимаю вас \uD83D\uDE1F, напишите /help чтобы узнать что я понимаю.";

   private final SendBotMessageService sendBotMessageService;

   public UnknownCommand(SendBotMessageService sendBotMessageService) {
       this.sendBotMessageService = sendBotMessageService;
   }

   @Override
   public void execute(Update update) {
       sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), UNKNOWN_MESSAGE);
   }
}
Минбаъд, биёед як контейнерро барои фармонҳои худ илова кунем. Он an objectҳои фармони моро нигоҳ медорад ва тибқи дархост мо интизорем, ки фармони лозимиро қабул кунем. Биёед онро CommandContainer меномем :
package com.github.javarushcommunity.jrtb.command;

import com.github.javarushcommunity.jrtb.service.SendBotMessageService;
import com.google.common.collect.ImmutableMap;

import static com.github.javarushcommunity.jrtb.command.CommandName.*;

/**
* Container of the {@link Command}s, which are using for handling telegram commands.
*/
public class CommandContainer {

   private final ImmutableMap<String, Command> commandMap;
   private final Command unknownCommand;

   public CommandContainer(SendBotMessageService sendBotMessageService) {

       commandMap = ImmutableMap.<string, command="">builder()
               .put(START.getCommandName(), new StartCommand(sendBotMessageService))
               .put(STOP.getCommandName(), new StopCommand(sendBotMessageService))
               .put(HELP.getCommandName(), new HelpCommand(sendBotMessageService))
               .put(NO.getCommandName(), new NoCommand(sendBotMessageService))
               .build();

       unknownCommand = new UnknownCommand(sendBotMessageService);
   }

   public Command retrieveCommand(String commandIdentifier) {
       return commandMap.getOrDefault(commandIdentifier, unknownCommand);
   }

}
Тавре ки шумо мебинед, ҳама чиз оддӣ буд. Мо харитаи тағирнопазир дорем, ки дорои калид дар шакли арзиши фармон ва арзиш дар шакли an objectи фармонии навъи Command. Дар созанда мо харитаи тағирнопазирро як маротиба пур мекунем ва ба он дар тамоми амалиёти барнома дастрасӣ пайдо мекунем. Усули асосӣ ва ягонаи кор бо контейнер retrieveCommand (String commandIdentifier) ​​мебошад . Фармоне бо номи UnknownCommand мавҷуд аст, ки барои ҳолатҳое, ки мо фармони мувофиқро ёфта наметавонем, масъул аст. Ҳоло мо омодаем контейнерро ба синфи боти худ татбиқ кунем - дар JavaRushTelegramBot: Ин аст он чизе ки синфи боти мо ҳоло ба назар мерасад:
package com.github.javarushcommunity.jrtb.bot;

import com.github.javarushcommunity.jrtb.command.CommandContainer;
import com.github.javarushcommunity.jrtb.service.SendBotMessageServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.objects.Update;

import static com.github.javarushcommunity.jrtb.command.CommandName.NO;

/**
* Telegram bot for Javarush Community from Javarush community.
*/
@Component
public class JavarushTelegramBot extends TelegramLongPollingBot {

   public static String COMMAND_PREFIX = "/";

   @Value("${bot.username}")
   private String username;

   @Value("${bot.token}")
   private String token;

   private final CommandContainer commandContainer;

   public JavarushTelegramBot() {
       this.commandContainer = new CommandContainer(new SendBotMessageServiceImpl(this));
   }

   @Override
   public void onUpdateReceived(Update update) {
       if (update.hasMessage() && update.getMessage().hasText()) {
           String message = update.getMessage().getText().trim();
           if (message.startsWith(COMMAND_PREFIX)) {
               String commandIdentifier = message.split(" ")[0].toLowerCase();

               commandContainer.retrieveCommand(commandIdentifier).execute(update);
           } else {
               commandContainer.retrieveCommand(NO.getCommandName()).execute(update);
           }
       }
   }

   @Override
   public String getBotUsername() {
       return username;
   }

   @Override
   public String getBotToken() {
       return token;
   }
}
Ва ин ҳама, тағирот дар code анҷом ёфт. Чӣ тавр ман инро тафтиш карда метавонам? Шумо бояд ботро оғоз кунед ва санҷед, ки ҳама чиз кор мекунад. Барои ин, ман токенро дар application.properties навсозӣ мекунам, токени дурустро насб мекунам ва барномаро дар синфи JavarushTelegramBotApplication оғоз мекунам: "Лоиҳаи Java аз A то Я": Амалисозии намунаи фармон барои кор бо бот.  Қисми 1 - 3Ҳоло мо бояд тафтиш кунем, ки фармонҳо мувофиқи интизорӣ кор мекунанд. Ман онро қадам ба қадам тафтиш мекунам:
  • StopCommand;
  • StartCommand;
  • Фармони Help;
  • NoCommand;
  • Фармони номаълум.
Ин аст он чизе ки рӯй дод: "Лоиҳаи Java аз A то Я": Амалисозии намунаи фармон барои кор бо бот.  Қисми 1 - 4Бот маҳз ҳамон тавре ки мо интизор будем, кор кард. Идома тавассути пайванд .

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

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