@Override
public void onUpdateReceived(Update update) {
UpdatesReceiver.handleUpdates(update);
}
ки ман ба коркардкунанда мегузарам (синфи худи UpdatesReceiver):
public static void handleUpdates(Update update) {
...
if (update.hasMessage() && update.getMessage().hasText()){
log.info("[Update (id {}) типа \"Текстовое сообщение\"]", update.getUpdateId());
new TextMessageHandler(update, replyGenerator).handleTextMessage();
}
else if (update.hasCallbackQuery()) {
//логгирование
new CallbackQueryHandler(update, replyGenerator).handleCallBackQuery();
}
else {
//логгирование
replyGenerator.sendTextMessage(update.getMessage().getChatId(), "Я могу принимать только текстовые messages!");
}
}
UpdatesReceiver як коркардкунандаи марказӣ мебошад, ки вобаста ба намуди навсозӣ назоратро ба дигар коркардкунандаи махсус интиқол медиҳад: TextMessageHandler ё CallbackQueryHandler, ки ман ба созандагони онҳо навсозӣ дар поёни занҷир мегузарам. Ҳангоми кор бо бот навсозӣ муҳимтарин чиз аст ва онро гум кардан мумкин нест, зеро бо ёрии маълумоти дар навсозӣ ҳифзшуда мо мефаҳмем, ки кадом корбар ва ба кадом чат посух бояд фиристода шавад. Барои тавлиди посухҳо ба корбар, ман як синфи алоҳида навиштам. Он метавонад паёми матнии муқаррарӣ, паём бо клавиатураи дохилӣ, паём бо тасвир ва паём бо клавиатураи ҷавоб фиристад. Клавиатураи сатрӣ чунин менамояд: Он тугмаҳоеро муайян мекунад, ки бо пахш кардани онҳо корбар занги бозпасро ба server мефиристад, ки онро тақрибан ба мисли паёмҳои муқаррарӣ коркард кардан мумкин аст. Барои "нигоҳ доштани" он ба шумо коркардкунандаи шахсии худ лозим аст. Мо барои ҳар як тугма амал таъин мекунем, ки баъд ба an objectи Навсозӣ навишта мешавад. Онхое. барои тугмаи "Арзиш" мо тавсифи "/нарх"-ро барои занги бозпас муқаррар мекунем, ки мо онро баъдтар аз навсозӣ гирифта метавонем. Минбаъд, дар синфи алоҳида, ман аллакай ин зангро коркард карда метавонам:
public void handleCallBackQuery() {
String call_data = update.getCallbackQuery().getData();
long message_id = update.getCallbackQuery().getMessage().getMessageId();
long chat_id = update.getCallbackQuery().getMessage().getChatId();
switch (call_date){
case "/price" :
//тут что-то сделать
break;
...
Клавиатураи Ҷавоб чунин менамояд: Ва аслан он чопкунии корбарро иваз мекунад. Бо пахш кардани тугмаи "Китобхона" ба бот паёми "Китобхона"-ро зуд мефиристад. Барои ҳар як намуди клавиатура ман синфи шахсии худро навиштам, ки намунаи Builder: inline and reply . Дар натиҷа, шумо метавонед вобаста ба талаботи худ клавиатураи дилхоҳро асосан "кашед". Ин хеле қулай аст, зеро клавиатураҳо метавонанд гуногун бошанд, аммо принсип бетағйир боқӣ мемонад. Ин аст усули интуитивӣ барои фиристодани паём бо клавиатураи дохилӣ:
public synchronized void sendInlineKeyboardMessage(long chat_id, String gameTitle) {
SendMessage keyboard = InlineKeyboardMarkupBuilder.create(chat_id)
.setText("Вы может узнать следующую информацию об игре " + gameTitle)
.row()
.button("Стоимость " + "\uD83D\uDCB0", "/price " + gameTitle)
.button("Обновлено " + "\uD83D\uDDD3", "/updated " + gameTitle)
.button("Версия " + "\uD83D\uDEE0", "/version " + gameTitle)
.endRow()
.row()
.button("Требования " + "\uD83D\uDCF5", "/requirements " + gameTitle)
.button("Покупки " + "\uD83D\uDED2", "/iap " + gameTitle)
.button("Размер " + "\uD83D\uDD0E", "/size " + gameTitle)
.endRow()
.row()
.button("Получить всю информацию об игре" + "\uD83D\uDD79", "/all " + gameTitle)
.endRow()
.row()
.button("Скрыть клавиатуру", "close")
.endRow()
.build();
try {
execute(keyboard);
} catch (TelegramApiException e) {
log.error("[Не удалось отправить сообщение с -inline- клавиатурой]: {}", e.getMessage());
}
}
Барои ба бот додани функсияҳои қатъӣ, фармонҳои махсус бо истифода аз аломати слэш ихтироъ карда шуданд: /library, /help, /game ва ғайра. Дар акси ҳол, мо бояд ҳар гуна партоверо, ки корбар навишта метавонад, коркард кунем. Дар асл, ин аст он чизе ки MessageHandler барои навишта шудааст:
if (message.equals(ChatCommands.START.getDescription())) {
replyGenerator.sendTextMessage(chat_id, new StartMessageHandler().reply());
replyGenerator.sendReplyKeyboardMessage(chat_id);
}
else if (message.equals(ChatCommands.HELP.getDescription())
|| message.equalsIgnoreCase("Помощь")) {
replyGenerator.sendTextMessage(chat_id, new HelpMessageHandler().reply());
}
...
Ҳамин тариқ, вобаста аз кадом фармоне, ки шумо ба бот мефиристед, коркарди махсус ба кор дохил карда мешавад. Биёед, дуртар рафта, ба кори парзер ва китобхона назар андозем. Агар шумо ба бот истинод ба бозӣ дар мағозаи Google Play фиристед, коркардкунандаи махсус ба таври худкор кор мекунад . Дар посух, корбар маълумотро дар бораи бозӣ дар шакли зерин мегирад: Ҳамзамон, усуле даъват карда мешавад, ки кӯшиш мекунад бозӣ ба китобхонаи бот илова карда шавад (аввал ба харитаи маҳаллӣ, баъд ба -> файли json ). Агар бозӣ аллакай дар китобхона бошад, пас санҷиш гузаронида мешавад (ба мисли ҳашмапи муқаррарӣ) ва агар маълумоти саҳроӣ (масалан, рақами version тағир дода шуда бошад), бозӣ дар китобхона дубора навишта мешавад. Агар ягон тағирот ошкор нашавад, ҳеҷ гуна сабтҳо ворид карда намешаванд. Агар дар китобхона умуман бозӣ набошад, он аввал ба харитаи маҳаллӣ навишта мешавад (an object ба монанди tyk ) ва баъд ба файли json навишта мешавад, зеро агар барнома дар server ба таври ғайричашмдошт баста шавад, маълумот гум шудааст, аммо онро ҳамеша бо истифода аз файл хондан мумкин аст. Дар асл, вақте ки барнома оғоз меёбад, китобхона ҳамеша бори аввал аз файли блоки статикӣ бор карда мешавад:
static {
TypeFactory typeFactory = mapper.getTypeFactory();
MapType mapType = typeFactory.constructMapType(ConcurrentSkipListMap.class, String.class, GooglePlayGame.class);
try {
Path path = Paths.get(LIBRARY_PATH);
if (!Files.exists(path)) {
Files.createDirectories(path.getParent());
Files.createFile(path);
log.info("[Файл библиотеки создан]");
}
else {
ConcurrentMap<string, googleplaygame=""> temporary = mapper.readValue(new File(LIBRARY_PATH), mapType);
games.putAll(temporary);
log.info("[Количество игр в загруженной библиотеке] = " + games.size());
}
}
catch (IOException e) {
log.error("[Ошибка при чтении/записи file] {}", e.getMessage());
}
}
Дар ин ҷо шумо иловатан бояд маълумотро аз файл ба харитаи муваққатӣ хонед, ки баъдан ба харитаи мукаммал “нусхабардорӣ” карда мешавад, то дар ҷустуҷӯи бозӣ дар файл ҳассосияти ҳарфҳо нигоҳ дошта шавад (бо навиштани tITan QuEST, бот то ҳол пайдо мекунад бозии Titan Quest дар китобхона). Боз як роҳи ҳалли дигар пайдо кардан ғайриимкон буд, инҳо хусусиятҳои сериализатсия бо истифода аз Ҷексон мебошанд. Ҳамин тавр, бо ҳар як дархост барои истинод, бозӣ ба китобхона илова карда мешавад, агар имконпазир бошад ва китобхона ба ин васила васеъ мешавад. Маълумоти иловагӣ дар бораи бозии мушаххасро бо истифода аз фармони /libraryGame_Name гирифтан мумкин аст. Шумо метавонед ҳам як параметри мушаххасро (масалан, versionи ҷорӣ) ва ҳам ҳама параметрҳоро дар як вақт пайдо кунед. Ин бо истифода аз клавиатураи сатрӣ, ки қаблан баррасӣ шуда буд, амалӣ карда мешавад. Дар давоми кор ман инчунин малакаҳои дар ин ҷо ҳосилшударо ҳангоми ҳалли мушкилот татбиқ мекардам. Масалан, рӯйхати номҳои бозиҳои тасодуфӣ, ки дар китобхона ҷойгиранд (ин хосият бо истифода аз фармони /library дастрас аст):
private String getRandomTitles(){
if (LibraryService.getLibrary().size() < 10){
return String.join("\n", LibraryService.getLibrary().keySet());
}
List<string> keys = new ArrayList<>(LibraryService.getLibrary().keySet());
Collections.shuffle(keys);
List<string> randomKeys = keys.subList(0, 10);
return String.join("\n", randomKeys);
}
Чӣ тавр бот пайвандҳоро коркард мекунад? Он онҳоро месанҷад, то бубинад, ки оё онҳо ба Google Play тааллуқ доранд (хост, протокол, порт):
private static class GooglePlayCorrectURL {
private static final String VALID_HOST = "play.google.com";
private static final String VALID_PROTOCOL = "https";
private static final int VALID_PORT = -1;
private static boolean isLinkValid(URI link) {
return (isHostExist(link) && isProtocolExist(link) && link.getPort() == VALID_PORT);
}
private static boolean isProtocolExist(URI link) {
if (link.getScheme() != null) {
return link.getScheme().equals(VALID_PROTOCOL);
}
else {
return false;
}
}
private static boolean isHostExist(URI link) {
if (link.getHost() != null) {
return link.getHost().equals(VALID_HOST);
}
else {
return false;
}
}
Агар ҳама чиз дар тартиб бошад, пас бот тавассути истинод бо истифода аз китобхонаи Jsoup пайваст мешавад, ки ба шумо имкон медиҳад, ки codeи HTMLи саҳифаро гиред, ки бояд таҳлил ва таҳлor минбаъда аст. Шумо наметавонед ботро бо истиноди нодуруст ё зараровар фиреб диҳед.
if (GooglePlayCorrectURL.isLinkValid(link)){
if (!link.getPath().contains("apps")){
throw new InvalidGooglePlayLinkException("К сожалению, бот работает исключительно с играми. Введите другую ссылку.");
}
URL = forceToRusLocalization(URL);
document = Jsoup.connect(URL).get();
}
else {
throw new NotGooglePlayLinkException();
}
...
Дар ин ҷо мо маҷбур шудем, ки мушкилотро бо танзимоти минтақавӣ ҳал кунем. Бот ба мағозаи Google Play аз serverе, ки дар Аврупо ҷойгир аст, пайваст мешавад, аз ин рӯ саҳифа дар мағозаи Google Play бо забони мувофиқ кушода мешавад. Ман маҷбур шудам асобачае нависам, ки маҷбуран ба versionи русии саҳифа “баҳисобгирӣ” мекунад (дар ниҳоят, лоиҳа ба аудиторияи мо нигаронида шуда буд). Барои ин, дар охири истинод ба шумо лозим аст, ки бодиққат параметри hl: &hl=ru дар дархости GET ба serverи Google Play илова кунед .
private String forceToRusLocalization(String URL) {
if (URL.endsWith("&hl=ru")){
return URL;
}
else {
if (URL.contains("&hl=")){
URL = URL.replace(
URL.substring(URL.length()-"&hl=ru".length()), "&hl=ru");
}
else {
URL += "&hl=ru";
}
}
return URL;
}
Пас аз пайвасти бомуваффақият, мо ҳуҷҷати HTML-ро барои таҳлил ва таҳлил омода мегирем, аммо ин аз доираи ин мақола берун аст. Рамзи таҳлилгар дар ин ҷост . Худи таҳлилгар маълумоти заруриро дарёфт мекунад ва бо бозӣ an objectе месозад, ки баъдтар дар ҳолати зарурӣ ба китобхона илова карда мешавад. <h2>Барои ҷамъбаст</h2>Бот якчанд фармонҳоро дастгирӣ мекунад, ки дорои функсияҳои муайян мебошанд. Он аз корбар паёмҳоро қабул мекунад ва онҳоро бо фармонҳои худ мувофиқ мекунад. Агар ин пайванд ё фармони /game + link бошад, он истинодро месанҷад, то бубинад, ки он ба Google Play тааллуқ дорад. Агар истинод дуруст бошад, он тавассути Jsoup пайваст мешавад ва ҳуҷҷати HTML-ро қабул мекунад. Ин ҳуҷҷат дар асоси таҳлилгари хаттӣ таҳлил карда мешавад. Маълумоти зарурӣ дар бораи бозӣ аз ҳуҷҷат гирифта мешавад ва сипас an objectи бозӣ бо ин маълумот пур карда мешавад. Баъдан, an objectи бозӣ дар анбори маҳаллӣ ҷойгир карда мешавад (агар бозӣ ҳанӯз вуҷуд надошта бошад) ва фавран ба файл навишта мешавад, то аз талафоти маълумот пешгирӣ карда шавад. Бозие, ки дар китобхона сабт шудааст (номи бозӣ калиди харита аст, an objectи бозӣ арзиши харита аст) бо истифода аз фармони /library Game_name дастрас кардан мумкин аст. Агар бозии зикршуда дар китобхонаи бот пайдо шавад, ба корбар клавиатураи сатрӣ баргардонида мешавад, ки бо он ӯ метавонад дар бораи бозӣ маълумот гирад. Агар бозӣ ёфт нашавад, шумо бояд дуруст навиштани номро боварӣ ҳосил кунед (он бояд пурра ба номи бозӣ дар мағозаи Google Play мувофиқат кунад, ба истиснои ҳолат) ё тавассути фиристодани бот бозӣ ба китобхона илова кунед. пайванд ба бозӣ. Ман ботро дар heroku ҷойгир кардам ва барои онҳое, ки дар оянда боти худро навиштан ва онро ройгон дар heroku ҷойгир кардан мехоҳанд, ман якчанд тавсияҳоро барои ҳалли мушкилоте, ки шумо дучор шудаед, медиҳам (зеро ман худам бо онҳо дучор шудаам). Мутаассифона, аз сабаби табиати Ҳероку, китобхонаи бот ҳамеша дар ҳар 24 соат як маротиба "аз нав танзим карда мешавад". Нақшаи ман нигоҳ доштани файлҳоро дар serverҳои Heroku дастгирӣ намекунад, аз ин рӯ он танҳо файли бозии маро аз Github мегирад. Якчанд роҳҳо вуҷуд доштанд: пойгоҳи додаҳоро истифода баред ё serverи дигареро ҷустуҷӯ кунед, ки ин файлро бо бозӣ нигоҳ дорад. Ман қарор додам, ки ҳоло коре накунам, зеро аслан бот он қадар муфид нест. Ба ман ин лозим буд, ки таҷрибаи мукаммалро ба даст орам, ки аслан он чизест, ки ман ба даст овардам. Ҳамин тавр, тавсияҳо барои Heroku:
-
Агар шумо дар Русия зиндагӣ кунед, эҳтимол шумо бояд бо истифода аз VPN дар heroku сабти ном кунед.
-
Дар решаи лоиҳа ба шумо лозим аст, ки файлеро бидуни васеъшавӣ бо номи Procfile гузоред. Мундариҷаи он бояд чунин бошад: https://github.com/miroha/Telegram-Bot/blob/master/Procfile
-
Дар pom.xml, мувофиқи мисол сатрҳои зеринро илова кунед , ки дар теги mainClass роҳ ба синферо нишон медиҳад, ки усули асосиро дар бар мегирад: bot.BotApplication (агар синфи BotApplication дар ҷузвдони бот бошад).
-
Бо истифода аз фармонҳои бастаи mvn ва ғайра ягон лоиҳа насозед, Ҳероку ҳама чизро барои шумо ҷамъ мекунад.
-
Тавсия дода мешавад, ки ба лоиҳа gitignore илова кунед, масалан, ин:
# Log file *.log # Compiled resources target # Tests test # IDEA files .idea *.iml
-
Дарвоқеъ лоиҳаро ба github бор кунед ва пас анборро ба Ҳероку пайваст кунед (ё усулҳои дигарро истифода баред, агар хато накунам, 3-тои онҳо вуҷуд доранд).
-
Агар зеркашӣ бомуваффақият анҷом дода шуда бошад ("Сохтани муваффақ"), боварӣ ҳосил кунед, ки ба Танзимоти Dynos гузаред:
ва слайдерро иваз кунед ва сипас боварӣ ҳосил кунед, ки он дар ҳолати ON аст (аз сабаби он ки ман ин корро накардам, боти ман кор накард ва ман майнаамро чанд рӯз рахна кардам ва бисёр ҳаракатҳои нолозим кардам. ).
-
Аломати ботро дар Github пинҳон кунед. Барои ин ба шумо лозим аст, ки токенро аз тағирёбандаи муҳити зист гиред:
public class Bot extends TelegramLongPollingBot { private static final String BOT_TOKEN = System.getenv("TOKEN"); @Override public String getBotToken() { return BOT_TOKEN; } ... }
Ва он гоҳ пас аз ҷойгиркунии бот, ин тағирёбандаро дар панели Ҳероку дар ҷадвали Танзимот насб кунед (дар тарафи рости TOKEN майдони VALUE хоҳад буд, аломати боти худро дар он ҷо нусхабардорӣ кунед):
- як лоиҳаи пурраи корӣ, ки дар Java навишта шудааст, гирифт;
- бо API-и тарафи сеюм кор карданро ёд гирифт (Telegram Bot API);
- дар амал, ман ба сериализатсия амиқтар омӯхтам, бо JSON ва китобхонаи Ҷексон бисёр кор кардам (дар аввал ман GSON-ро истифода мекардам, аммо бо он мушкилот вуҷуд дошт);
- дар вакти кор бо файлхо махорати худро мустахкам намудам, бо Java NIO шинос шудам;
- бо файлҳои конфигуратсияи .xml кор карданро омӯхтам ва худамро ба сабти ном одат кардаам;
- такмor ихтисос дар муҳити рушд (IDEA);
- бо git кор карданро ёд гирифт ва арзиши gitignore-ро ёд гирифт;
- малакаҳо дар таҳлor саҳифаҳои веб (китобхонаи Jsoup);
- якчанд намунаҳои тарҳрезиро омӯхт ва истифода бурд;
- ҳиссиёт ва хоҳиши такмил додани code (рефакторинг);
- Ман омӯхтам, ки роҳҳои ҳалли онлайнро пайдо кунам ва аз додани саволҳое, ки ба онҳо ҷавоб наёфтам, шарм надорам.
GO TO FULL VERSION