हम टेलीग्राम में बॉट के लिए बुनियादी कार्यक्षमता विकसित करना जारी रखते हैं। पिछले हिस्सों में, हमने इस बिंदु पर चर्चा की कि संदेश प्राप्त करने, प्रसंस्करण और भेजने पर बॉट के काम को विभाजित किया जाना चाहिए। आइए हमारे बॉट को मल्टीथ्रेडेड और एसिंक्रोनस बनाने के लिए मूल जावा कोर टूल्स का उपयोग करें। हम एक ऐसे कार्य के साथ आएंगे, जिसे संसाधित करने में बहुत समय लगता है। आइए देखें कि तार में कमांड कैसे काम करते हैं और उन्हें कैसे संसाधित करने की आवश्यकता है।
यह जावा में टेलीग्राम के लिए प्रोग्रामिंग बॉट्स पर लेख के पहले भाग की निरंतरता है
टेलीग्राम बॉट के लिए बुनियादी कार्यक्षमता बनाने के लिए निर्देश देता है। (भाग 1)जिनके लिए यह आगे दिलचस्प है, आपका स्वागत है ...
मुझे तुरंत यह कहना होगा कि इस भाग में एक बार में बहुत कुछ जोड़ा गया था और चुपचाप हम उन सभी कार्यक्षमता का विश्लेषण करेंगे जिन्होंने बॉट को मल्टीथ्रेड करने में सक्षम होने की अनुमति दी थी और इसकी आवश्यकता क्यों है।
हमेशा की तरह मुख्य से:
आप इस लेख के लिए सभी तैयार किए गए कोड को
पार्ट 2-हैंडलर्स शाखा में गिट रिपॉजिटरी में पा सकते हैं।
कोड पूरी तरह से काम कर रहा है, यह बॉट (प्राधिकरण और टोकन) के प्राधिकरण के लिए डेटा को बदलने, बदलने और App.class वर्ग में मुख्य विधि को चलाने के लिए पर्याप्त है।
कृपया ध्यान दें कि यह वर्ग बॉट के लिए एक अधिसूचना भेजता है जब बॉट शुरू होता है कि बॉट शुरू हो गया है। बॉट एडमिन आईडी App.class वर्ग में भी निर्दिष्ट है और यदि आप इसे नहीं बदलते हैं, तो आपका बॉट मुझे संदेश भेजने की कोशिश करेगा :)और आगे के बिंदुओं पर हम उन परिवर्तनों का विश्लेषण करेंगे जो पहले भाग के जारी होने के बाद सामने आए थे।
कमांड प्रोसेसिंग
शुरू करने के लिए, आइए इस अवधारणा से निपटते हैं कि टेलीग्राम बॉट के साथ संचार के लिए एक टीम सामान्य रूप से क्या है। बॉट की सेटिंग्स के आधार पर, यह या तो किसी भी प्रारूप के किसी भी संदेश को देख सकता है या केवल विशेष रूप से डिज़ाइन किए गए आदेशों को देख सकता है। क्या अंतर है और
जहाँ आप इन संदेश विकल्पों को पूरा कर सकते हैं।
- सादा पाठ, नियमित संदेश।
इस रूप में, बॉट संदेश प्राप्त करता है जब वे उसे पीएम में लिखते हैं। और फिर भी, यदि बॉट की सेटिंग में समूहों में गोपनीयता मोड बंद हो जाता है, तो बॉट सभी संदेशों को पूरी तरह से देखना शुरू कर देता है। यदि यह सेटिंग सक्षम है, जब समूह में जोड़ा जाता है, तो बॉट केवल इसे संबोधित आदेशों को देखता है। वे कैसे दिखते हैं - दूसरा पैराग्राफ देखें - विशेष रूप से डिजाइन की गई टीमें
इस तरह के आदेश हमेशा एक स्लैश के साथ शुरू होते हैं: /
उसके बाद टीम ही आती है। कमांड का पाठ रिक्त स्थान के बिना होना चाहिए। एक उदाहरण:
/ शुरू
इस आदेश के साथ, कोई भी उपयोगकर्ता हमेशा आपके बॉट के साथ संचार शुरू करता है। इसलिए, अच्छे फॉर्म के नियमों के अनुसार, इस आदेश की प्रतिक्रिया निर्धारित की जानी चाहिए।

आपके बॉट के साथ काम करने के तरीके को जानने वाले सभी आदेश, आपके बॉट की सेटिंग्स में कौशल की सूची में जोड़ना उचित है। यह सब @BotFather के साथ टेलीग्राम में किया जाता है।
/ MyBots कमांड को कॉल करके, अपना बॉट चुनें और फिर "एडिट बॉट" बटन
आपको एक विंडो मिलेगी जहां बॉट के सभी पैरामीटर दिखाए जाएंगे और फिर आप इसके पूरे इंटरफ़ेस को कॉन्फ़िगर कर सकते हैं और संकेत कर सकते हैं कि आपके बॉट किस कमांड के साथ काम कर सकते हैं।

वे इस प्रारूप में सेट हैं:

और उसके बाद, जब आप अपने बॉट में एक कमांड दर्ज करना शुरू करते हैं, तो यह सूचीबद्ध कमांड की सूची के साथ मदद दिखाएगा:

और एक और अति सूक्ष्म अंतर है। एक समूह में कई बॉट्स हो सकते हैं, और यदि उनके पास सामान्य कमांड हैं (और सामान्य कमांड अनिवार्य होंगे, तो अधिकांश बॉट्स में एक ही शुरुआत और मदद लागू की जाती है), फिर एक हिस्सा खुद कमांड में जोड़ा जाएगा, जिसमें बताया जाएगा कि यह कमांड किस बॉट से संबंधित है। और कमांड पूरी तरह से इस तरह दिखेगा:
/ start @ test_habr_bot
और अब, इन सभी बारीकियों को जानते हुए, आप के साथ एक ऐसा प्रसंस्करण विकल्प बनाते हैं, जो कि स्लैश से शुरू होने वाली आज्ञाओं को समझना चाहिए और यह जानना कि भेद कैसे करना है कि कमांड विशेष रूप से आपके बॉट या किसी अन्य को संबोधित है या नहीं।
एक पैकेज बनाएं जिसमें कमांड को संसाधित करने के लिए जिम्मेदार कक्षाएं होंगी।
पैकेज com.example.telegrambot.commandकमांड क्लास में, हम उन सभी कमांड को सूचीबद्ध करते हैं जिन्हें हमारे बॉट को समझने में सक्षम होना चाहिए।
public enum Command { NONE, NOTFORME, NOTIFY, START, HELP, ID }
जैसा कि आपने पहले देखा, मैंने @BotFather पर बताया कि बॉट मैं 4 टीमों को समझने में सक्षम होना चाहिए। ये मानक शुरुआत और मदद होगी। हम एक उपयोगी एक - id जोड़ते हैं। और एक और, सूचित करें, जिसके बारे में मैं थोड़ी देर बाद बात करूंगा। और दो टीमें NONE और NOTFORME, जो हमें बताएंगी कि टेक्स्ट मैसेज या तो कमांड नहीं है, या यह कमांड हमारे बॉट के लिए नहीं है।
एक और सहायक वर्ग
ParsedCommand जोड़ें import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class ParsedCommand { Command command = Command.NONE; String text=""; }
इसका मुख्य उद्देश्य इस वर्ग की वस्तुओं में पार्सिंग पाठ के परिणाम को संग्रहीत करना है। इसमें केवल टीम ही शामिल होगी और टीम के बाद आने वाले सभी पाठ।
और हम एक अलग वर्ग लिखेंगे जो टीमों को हमारे पास भेज देगा।
पारसर वर्ग
import javafx.util.Pair; import org.apache.log4j.Logger; public class Parser { private static final Logger log = Logger.getLogger(Parser.class); private final String PREFIX_FOR_COMMAND = "/"; private final String DELIMITER_COMMAND_BOTNAME = "@"; private String botName; public Parser(String botName) { this.botName = botName; } public ParsedCommand getParsedCommand(String text) { String trimText = ""; if (text != null) trimText = text.trim(); ParsedCommand result = new ParsedCommand(Command.NONE, trimText); if ("".equals(trimText)) return result; Pair<String, String> commandAndText = getDelimitedCommandFromText(trimText); if (isCommand(commandAndText.getKey())) { if (isCommandForMe(commandAndText.getKey())) { String commandForParse = cutCommandFromFullText(commandAndText.getKey()); Command commandFromText = getCommandFromText(commandForParse); result.setText(commandAndText.getValue()); result.setCommand(commandFromText); } else { result.setCommand(Command.NOTFORME); result.setText(commandAndText.getValue()); } } return result; } private String cutCommandFromFullText(String text) { return text.contains(DELIMITER_COMMAND_BOTNAME) ? text.substring(1, text.indexOf(DELIMITER_COMMAND_BOTNAME)) : text.substring(1); } private Command getCommandFromText(String text) { String upperCaseText = text.toUpperCase().trim(); Command command = Command.NONE; try { command = Command.valueOf(upperCaseText); } catch (IllegalArgumentException e) { log.debug("Can't parse command: " + text); } return command; } private Pair<String, String> getDelimitedCommandFromText(String trimText) { Pair<String, String> commandText; if (trimText.contains(" ")) { int indexOfSpace = trimText.indexOf(" "); commandText = new Pair<>(trimText.substring(0, indexOfSpace), trimText.substring(indexOfSpace + 1)); } else commandText = new Pair<>(trimText, ""); return commandText; } private boolean isCommandForMe(String command) { if (command.contains(DELIMITER_COMMAND_BOTNAME)) { String botNameForEqual = command.substring(command.indexOf(DELIMITER_COMMAND_BOTNAME) + 1); return botName.equals(botNameForEqual); } return true; } private boolean isCommand(String text) { return text.startsWith(PREFIX_FOR_COMMAND); } }
संक्षेप में। पार्सर को इनिशियलाइज़ करते समय, हमें कंस्ट्रक्टर में अपने बॉट का नाम पास करना चाहिए ताकि पार्सर अजनबियों से अपनी आज्ञाओं को अलग कर सके।
ठीक है, तो हम सिर्फ सार्वजनिक पद्धति कहते हैं
public ParsedCommand getParsedCommand(String text)
जिसके लिए हम तर्कों में संदेश पाठ को पास करते हैं, और उसे हमें एक आदेश और संदेश पाठ आज्ञा के बाद वापस करना चाहिए।
आप देख सकते हैं कि
परीक्षण कक्षा में पार्सर कैसे काम करता है।
अलग से मक्खियों, अलग से कटलेट
अब हमें अपने बॉट को अलग से संदेश प्राप्त करने, प्रक्रिया करने और प्रतिक्रियाएं भेजने के लिए सिखाने की जरूरत है। परीक्षण और त्रुटि की एक श्रृंखला के बाद, मैं आवेदन के इस तर्क पर आया।
मुख्य वर्ग
बॉट आवेदन के मुख्य धागे में काम करेगा और केवल इस तथ्य के साथ व्यस्त होगा कि यह सभी प्राप्त संदेशों को एक विशेष कतार में रखेगा और उन संदेशों के लिए एक कंटेनर भी होगा जो हम उपयोगकर्ता को प्रतिक्रिया में भेजने की योजना बनाते हैं।
इस वर्ग में परिवर्तन बहुत मामूली हैं। हमने दो कतारें जोड़ीं:
public final Queue<Object> sendQueue = new ConcurrentLinkedQueue<>(); public final Queue<Object> receiveQueue = new ConcurrentLinkedQueue<>();
और फ़ंक्शन कोड को
सार्वजनिक रूप से फिर से
लिखना रद्द करें onUpdateReceived (अपडेट अपडेट करें) @Override public void onUpdateReceived(Update update) { log.debug("Receive new Update. updateID: " + update.getUpdateId()); receiveQueue.add(update); }
ऐसा क्यों? फिर से मैंने विभिन्न विकल्पों की कोशिश की। और मल्टीथ्रेडिंग की मुख्य समस्या साझा डेटा के साथ काम कर रही है। और सबसे ज्यादा मुझे यह पसंद आया कि बहु-सूत्री कतारों का क्रियान्वयन किस तरह से होता है?
और जैसा कि आप देख सकते हैं, दोनों कतारों में हम ऑब्जेक्ट डेटा प्रकारों को संग्रहीत करेंगे। यह भविष्य के लिए एक और बुकमार्क है। इस प्रकार, हम प्राप्त संदेशों के प्रकार से संलग्न नहीं हैं। आने वाली कतार में, हम न केवल अद्यतन प्रकार की वस्तुओं को जोड़ सकते हैं, बल्कि कुछ अन्य वस्तुओं को भी जो हमें चाहिए।
भेजने के लिए कतार के साथ एक ही बात। चूंकि हम विभिन्न प्रकार के संदेश भेज सकते हैं और उनके पास एक सामान्य अभिभावक नहीं है - हम एक सामान्य डेटा प्रकार - ऑब्जेक्ट का भी उपयोग करते हैं।
यदि आप इस रूप में बॉट चलाते हैं, तो यह काम करेगा, लेकिन कुछ भी नहीं करेगा। वह लॉग में सभी प्राप्त संदेशों को रिकॉर्ड करेगा और कतार में रखेगा।
इसलिए, हमें किसी प्रकार के धागे की जरूरत है जो कतार से प्राप्त संदेशों को लेने और उन पर कुछ कार्य करने और अपने कार्य के परिणामों को
sendQueue कतार में डालने का ध्यान
रखता है ।
आइए एक अलग पैकेज बनाएं:
सेवा और इसमें हमारे पास केवल 2 वर्ग होंगे:
MessageReciever - संदेश हैंडलर प्राप्त किया
MessageSender उपयोगकर्ता को भेजने के लिए संदेश कतार हैंडलर है।
हम उनके काम पर थोड़ा कम विचार करेंगे, लेकिन अभी के लिए, हम अपने शुरुआती कक्षा
ऐप में उनके उपयोग का वर्णन करेंगे
हमारे बॉट से जुड़े होने के बाद, हम अलग-अलग थ्रेड में अपने हैंडलर शुरू करते हैं:
MessageReciever messageReciever = new MessageReciever(test_habr_bot); MessageSender messageSender = new MessageSender(test_habr_bot); test_habr_bot.botConnect(); Thread receiver = new Thread(messageReciever); receiver.setDaemon(true); receiver.setName("MsgReciever"); receiver.setPriority(PRIORITY_FOR_RECEIVER); receiver.start(); Thread sender = new Thread(messageSender); sender.setDaemon(true); sender.setName("MsgSender"); sender.setPriority(PRIORITY_FOR_SENDER); sender.start();
दोनों थ्रेड्स के लिए, हम डेमन मोड निर्दिष्ट करते हैं। थ्रेड्स के काम करने के लिए यह आवश्यक है जब तक कि मुख्य धागा चल रहा हो और जैसे ही वह अपना काम बंद कर देता है, तब तक खुद को समाप्त कर लेता है।
हम पहले आने वाले संदेश हैंडलर से निपटना पसंद नहीं करेंगे - आइए
मैसेजेंडर वर्ग के संचालन को देखें।
आइए एक नज़र डालते हैं कि वह क्या कर सकता है और क्या करता है:
खैर, अब
MessageReciever वर्ग
के काम को
देखते हैंमैसेजसेंडर की तरह, उसे मल्टीथ्रेड किया जाना चाहिए, कंस्ट्रक्टर में क्लास बॉट का एक ऑब्जेक्ट प्राप्त होता है, जिसमें उसे एक अनंत लूप में संदेश प्राप्त होंगे, उन्हें प्रोसेस करें और उसे अपने काम के परिणाम भेजने के लिए कतार में लगायें।
यहां हम पहले निर्मित कमांड पार्सर का उपयोग करते हैं। और फिर हम अपनी टीमों के लिए विभिन्न प्रकार के हैंडलर का उपयोग करने की क्षमता जोड़ते हैं और उनमें से कुछ को हम बहु-थ्रेडेड बना देंगे।
कार्य चक्र बहुत सरल है:
@Override public void run() { log.info("[STARTED] MsgReciever. Bot class: " + bot); while (true) { for (Object object = bot.receiveQueue.poll(); object != null; object = bot.receiveQueue.poll()) { log.debug("New object for analyze in queue " + object.toString()); analyze(object); } try { Thread.sleep(WAIT_FOR_NEW_MESSAGE_DELAY); } catch (InterruptedException e) { log.error("Catch interrupt. Exit", e); return; } } }
कतार की जाँच करें। अगर कुछ है, तो विश्लेषक को चलाएं:
private void analyze(Object object)
अगर कुछ नहीं है, तो हम इंतजार कर रहे हैं।
विश्लेषक वस्तु के प्रकार की जाँच करता है। यदि वह जानता है कि उसके साथ कैसे काम करना है, तो वह अगला विश्लेषक शुरू करता है। यदि आप नहीं कर सकते - शपथ :)
ऐसा क्यों? फिर से, यह भविष्य के लिए एक बुकमार्क है और, मुझे आशा है, मैं इसे लेखों की इस श्रृंखला के अगले भागों में प्रकट करूंगा। इस तरह के कार्यान्वयन से हमें बॉट के लिए अपने स्वयं के कार्य बनाने, मेलिंग सूची, दिन के कार्य करने की अनुमति मिलेगी। इसके लिए, रिसीवर को न केवल प्रकार की वस्तुओं को अपडेट करने में सक्षम होना चाहिए, बल्कि हमारे कुछ भी। लेकिन उस पर अधिक बाद में :)
आइए हम अद्यतन प्रकार के लिए विश्लेषक पर अधिक विस्तार से विचार करें:
private void analyzeForUpdateType(Update update) { Long chatId = update.getMessage().getChatId(); String inputText = update.getMessage().getText(); ParsedCommand parsedCommand = parser.getParsedCommand(inputText); AbstractHandler handlerForCommand = getHandlerForCommand(parsedCommand.getCommand()); String operationResult = handlerForCommand.operate(chatId.toString(), parsedCommand, update); if (!"".equals(operationResult)) { SendMessage message = new SendMessage(); message.setChatId(chatId); message.setText(operationResult); bot.sendQueue.add(message); } }
यह चैट आईडी को परिभाषित करता है। संदेश पाठ हो जाता है। पार्सर का उपयोग करना, यह निर्धारित करता है कि क्या संदेश एक कमांड है और यह निर्धारित करता है कि इस कमांड को किस हैंडलर से संसाधित किया जाना चाहिए। यह कमांड को प्रोसेस करना शुरू कर देता है और अगर कमांड का प्रोसेसिंग कुछ गैर-रिक्त पाठ देता है - तो यह उपयोगकर्ता को भेजने के लिए एक संदेश बनाता है और इसे कतार में रखता है।
और फिर आपके पास एक सवाल होना चाहिए: "किस तरह का हैंडलर?"। उसके बारे में पहले कोई बात नहीं हुई थी, और कोड में उसका उल्लेख नहीं किया गया था। बिलकुल ठीक। अब हम इस कार्यक्षमता का विश्लेषण करेंगे।
ऐसा करने के लिए, एक अलग पैकेज बनाएं, जो हमारे सभी हैंडलर को स्टोर करेगा। इसे
हैंडलर कहेंआइए एक सार वर्ग
AbstractHandler बनाएं
import com.example.telegrambot.bot.Bot; import com.example.telegrambot.command.ParsedCommand; import org.telegram.telegrambots.api.objects.Update; public abstract class AbstractHandler { Bot bot; AbstractHandler(Bot bot) { this.bot = bot; } public abstract String operate(String chatId, ParsedCommand parsedCommand, Update update); }
उसके पास एक बुनियादी कंस्ट्रक्टर होगा जिसमें हम उस बॉट ऑब्जेक्ट के साथ गुजरते हैं जिसमें उसे बातचीत करने की आवश्यकता होगी। और
संचालित करने के
लिए एक सार फ़ंक्शन घोषित किया जाता है, जिसके कार्यान्वयन को हमें अपनी कक्षा के वारिसों में पंजीकृत करना होगा।
और तुरंत हम सबसे सरल हैंडलर लागू करेंगे जो कुछ भी नहीं करेगा और हम इसका उपयोग तब करेंगे जब हम समझ नहीं पाएंगे कि हमें किस प्रकार की कमांड दी गई थी और बॉट से कोई प्रतिक्रिया की आवश्यकता नहीं है।
DefaultHandler.java import com.example.telegrambot.bot.Bot; import com.example.telegrambot.command.ParsedCommand; import org.apache.log4j.Logger; import org.telegram.telegrambots.api.objects.Update; public class DefaultHandler extends AbstractHandler { private static final Logger log = Logger.getLogger(DefaultHandler.class); public DefaultHandler(Bot bot) { super(bot); } @Override public String operate(String chatId, ParsedCommand parsedCommand, Update update) { return ""; } }
हम इसे कैसे लागू करेंगे और इसके काम के परिणाम हमें कहाँ मिलेंगे - हम थोड़ी देर बाद इसका विश्लेषण करेंगे।
अगली पंक्ति में
सिस्टमहैंडलर हैवह बुनियादी आज्ञाओं से निपटेगा, जैसे कि शुरुआत, मदद, और हम उसे आईडी कमांड निष्पादित करने का निर्देश भी देंगे
इसका आधार इस तरह दिखता है:
import com.example.telegrambot.bot.Bot; import com.example.telegrambot.command.Command; import com.example.telegrambot.command.ParsedCommand; import org.apache.log4j.Logger; import org.telegram.telegrambots.api.methods.send.SendMessage; import org.telegram.telegrambots.api.objects.Update; public class SystemHandler extends AbstractHandler { private static final Logger log = Logger.getLogger(SystemHandler.class); private final String END_LINE = "\n"; public SystemHandler(Bot bot) { super(bot); } @Override public String operate(String chatId, ParsedCommand parsedCommand, Update update) { Command command = parsedCommand.getCommand(); switch (command) { case START: bot.sendQueue.add(getMessageStart(chatId)); break; case HELP: bot.sendQueue.add(getMessageHelp(chatId)); break; case ID: return "Your telegramID: " + update.getMessage().getFrom().getId(); } return ""; }
आप देख सकते हैं कि कोड में स्टार्ट और हेल्प कमांड की प्रतिक्रिया कैसे बनती है :)
हम पाठ संदेश बनाते हैं और उन्हें भेजने के लिए एक कतार में रखते हैं। इस पर हैंडलर का काम रुक जाता है। ये संदेश कौन और कैसे भेजेगा - उसे इसकी कोई परवाह नहीं है।
और याद रखें, मैंने थोड़ा ऊपर उल्लेख किया है कि हैंडलर के परिणामस्वरूप, यह कुछ पाठ डेटा लौटाता है। और यदि यह रेखा खाली नहीं है, तो हमें उपयोगकर्ता को यह पाठ भेजना होगा। यह ठीक वैसी कार्यक्षमता है जिसका उपयोग हमने आईडी कमांड को काम करते समय किया था:
case ID: return "Your telegramID: " + update.getMessage().getFrom().getId();
हैंडलर उपयोगकर्ता आईडी के साथ उस व्यक्ति को पाठ लौटाएगा जिसने इसे कॉल किया था और पहले से ही संदेश भेजने के लिए उत्पन्न हो जाएगा, जो फिर कतार में जाएगा।
और लेख की शुरुआत में, मैंने उल्लेख किया कि हम इस विकल्प को एक उपयोगकर्ता के संदेश को संसाधित करने के लिए लागू कर रहे हैं जिसे काम करने के लिए समय की आवश्यकता है। और इसलिए कि यह हमारे संचालकों के साथ हस्तक्षेप नहीं करता है, हम इसे एक अलग स्ट्रीम में आवंटित करेंगे और इसे बाकी को विचलित किए बिना अपने व्यवसाय के बारे में जाने देंगे।
इस तरह के "हैवीवेट" धागे के रूप में, मैं अधिसूचित कमांड के साथ आया था। उसके काम का सिद्धांत यही है।
बॉट को फॉर्म की एक कमांड भेजकर:
/ 300 सूचित करेंबॉट को आपको सूचित करना चाहिए कि टीम समझ गई और 300 सेकंड के बाद यह आपको कुछ सूचना भेजेगा कि 300 सेकंड बीत चुके हैं। इस टीम का व्यावहारिक उपयोग भी हो सकता है :)
उदाहरण के लिए, आप आग पर पकौड़ी डालते हैं और आपको 5 मिनट के बाद उन्हें निकालने की आवश्यकता होती है। बॉट यह पूरी तरह से करेगा और चैट में आपके लिए एक सूचना फेंक देगा कि समय समाप्त हो गया है।
या अधिक गंभीर कार्य लें। आप एक महत्वपूर्ण बैठक में जाते हैं और आप जानते हैं कि किसी के साथ संवाद करते समय आपको बातचीत को बाधित करने की आवश्यकता होगी। इसके लिए, वे आमतौर पर दोस्तों को या तो कॉल करने या एक संदेश लिखने के लिए कहते हैं, जो लंबे समय तक बातचीत से विचलित न करने और कुछ कार्रवाई करने का एक उद्देश्य होगा। लेकिन जब आपके पास बॉट है तो दोस्तों को क्यों परेशान करें? अग्रिम में उसे एक कार्य पूछने और समय का संकेत देने के बाद, आपको टेलीग्राम में आवश्यक अधिसूचना प्राप्त होगी। लेकिन यह सभी गीत हैं। कार्य और इस आदेश का आविष्कार केवल आपको यह दिखाने के लिए किया गया था कि किसी अलग स्ट्रीम में कैसे आवंटित किया जाए जिसका काम बहुत लंबा समय ले सकता है।
तो,
NotifyHandler :
import com.example.telegrambot.ability.Notify; import com.example.telegrambot.bot.Bot; import com.example.telegrambot.command.ParsedCommand; import org.apache.log4j.Logger; import org.telegram.telegrambots.api.objects.Update; public class NotifyHandler extends AbstractHandler { private static final Logger log = Logger.getLogger(NotifyHandler.class); private final int MILLISEC_IN_SEC = 1000; private String WRONG_INPUT_MESSAGE = "Wrong input. Time must be specified as an integer greater than 0"; public NotifyHandler(Bot bot) { super(bot); } @Override public String operate(String chatId, ParsedCommand parsedCommand, Update update) { String text = parsedCommand.getText(); if ("".equals(text)) return "You must specify the delay time. Like this:\n" + "/notify 30"; long timeInSec; try { timeInSec = Long.parseLong(text.trim()); } catch (NumberFormatException e) { return WRONG_INPUT_MESSAGE; } if (timeInSec > 0) { Thread thread = new Thread(new Notify(bot, chatId, timeInSec * MILLISEC_IN_SEC)); thread.start(); } else return WRONG_INPUT_MESSAGE; return ""; } }
हम यह जांचते हैं कि पाठ में हमें देरी का समय दिया गया था या नहीं। यदि नहीं, तो हम शपथ लेते हैं। यदि हां, तो हम एक नया सूत्र शुरू करते हैं, जहां हम अपने निर्देशों पर परिचयात्मक पास करते हैं। यह कार्य एक अलग
अधिसूचित वर्ग द्वारा संभाला जाएगा।
कार्यक्षमता अत्यंत सरल है। वह संकेतित सेकंड की संख्या को सोता है। लेकिन उसकी नींद की प्रक्रिया में, आपका बॉट किसी भी अन्य संदेश प्राप्त करने, आपके साथ संवाद करने और अतिरिक्त अतिरिक्त सूचनाएं लॉन्च करने में सक्षम है। और यह सब एक दूसरे से अलग काम करता है।
और कॉलिंग हैंडलर के साथ इस पूरे झुंड को तार्किक रूप से पूरा करने के लिए, चलिए हमारे
MessageReciever क्लास में वापस जाते हैं और देखते हैं कि हम समझते हैं कि हमें किस हैंडलर की ज़रूरत है और हम उन्हें कैसे चलाते हैं।
आवश्यक हैंडलर हमें कमांड द्वारा वापस कर दिया जाता है
private AbstractHandler getHandlerForCommand(Command command) { if (command == null) { log.warn("Null command accepted. This is not good scenario."); return new DefaultHandler(bot); } switch (command) { case START: case HELP: case ID: SystemHandler systemHandler = new SystemHandler(bot); log.info("Handler for command[" + command.toString() + "] is: " + systemHandler); return systemHandler; case NOTIFY: NotifyHandler notifyHandler = new NotifyHandler(bot); log.info("Handler for command[" + command.toString() + "] is: " + notifyHandler); return notifyHandler; default: log.info("Handler for command[" + command.toString() + "] not Set. Return DefaultHandler"); return new DefaultHandler(bot); } }
अब, यदि आप कुछ और कमांड जोड़ना चाहते हैं, तो आपको निम्नलिखित कार्य करने होंगे:
- कमांड क्लास में कमांड सिंटैक्स जोड़ें।
- रिसीवर में, getHandlerForCommand फ़ंक्शन में , निर्दिष्ट करें कि इस कमांड को संसाधित करने के लिए कौन जिम्मेदार होगा।
- और वास्तव में इस हैंडलर को लिखें।
मैं पहले से कहूंगा कि नई टीमों को जोड़ने की प्रक्रिया को सरल बनाया जा सकता है। जिम्मेदार संचालकों को तुरंत आदेशों की सूची के साथ कक्षा में पंजीकृत किया जा सकता है। लेकिन मुझे डर है कि कोड समझना आसान नहीं है। पाठ बहुत लंबा है। लेकिन मैं उसे टुकड़ों में नहीं हरा सकता। तीन बुनियादी बॉट फ़ंक्शन यहां वर्णित हैं, जो केवल एक साथ काम करते हैं और व्यक्तिगत रूप से उनके बारे में बात करना सही नहीं है।
हम निम्नलिखित भागों में किस बारे में बात करेंगे?
हमें यह समझने की जरूरत है कि विभिन्न प्रकार के संदेशों को कैसे बनाया जाए। कीबोर्ड और बटन के साथ कैसे काम करें। अपने पुराने पोस्ट को कैसे संपादित करें। कॉलबैक के साथ कैसे काम करें। कुछ क्रियाएं करने के लिए बॉट को कार्य कैसे दिया जाता है। बॉट के साथ इंटरेक्टिव मैसेज कैसे बनाएं और भी बहुत कुछ। आगे के सभी भाग आपके और आपकी गतिविधि पर निर्भर हैं।
टिप्पणियों में मैं आपकी प्रतिक्रिया और निर्देशों के लिए तत्पर हूं, जिन्हें हम प्राथमिकता के रूप में मानेंगे।
बेझिझक सवाल पूछें। यदि लेख में कुछ इंगित नहीं किया गया है या किसी बिंदु पर यह स्पष्ट नहीं है - इसके बारे में मुझे लिखें। मैं निश्चित रूप से विवादास्पद मुद्दों को सही, संपादित या स्पष्ट करूंगा।
खुशी में कार्यक्रम और शक्ति और सुंदर कोड आपके साथ आ सकते हैं :)
py.sy.
लेख के इस भाग में लिखा गया बॉट काम करता है। आप उसे यहाँ पीड़ा दे सकते हैं:
@test_habr_botआप मेरे योजनाकार को भी
परेशान कर सकते हैं:
@EventCheckPlanner_Botऔर
चेकी फिल्म प्रशंसक :
@FilmFanAmateurBot ।