JavaRush /Java Blog /Random-TK /Telegram bot - Java-da webHook arkaly ýatlatma ýa-da Goog...

Telegram bot - Java-da webHook arkaly ýatlatma ýa-da Google senenamasyna ýok diýiň! 2-nji bölüm

Toparda çap edildi
Taslamanyň ikinji bölümi - ine, birinjisine baglanyşyk : Şeýlelik bilen BotState synpy : Botumyzyň belli bir wagtda nämä garaşylýandygyna düşünmek üçin, mysal üçin, ýatlatmany pozmak üçin zerur nämüçindir botymyza sanlaryň girizilendigini we iberilendigini habar beriň, sanawdan ýatlatma şahsyýeti hökmünde garalmaly we pozulmaly. Şol sebäpden, "Öçürmek" düwmesine basanyňyzdan soň , BotState.ENTERNUMBEREVENT ýagdaýyna girýär , bu bot ýagdaýlary bilen ýörite döredilen Enum synpy.
public enum BotState {
    ENTERDESCRIPTION,//the bot will wait for the description to be entered.
    START,
    MYEVENTS, //the bot show to user list events.
    ENTERNUMBEREVENT,//the bot will wait for the number of event to be entered.
    ENTERDATE, //the bot will wait for the date to be entered
    CREATE, //the bot run created event
    ENTERNUMBERFOREDIT, //the bot will wait for the number of event to be entered
    EDITDATE, //the bot will wait for the date to be entered
    EDITDESCRIPTION,//the bot will wait for the description to be entered
    EDITFREQ,//the bot will wait callbackquery
    ALLUSERS, // show all users
    ALLEVENTS, //show all events
    ENTERNUMBERUSER,//the bot will wait for the number of user to be entered.
    ENTERTIME,//the bot will wait for the hour to be entered.
    ONEVENT // state toggle
}
Indi bolsa sanlary girizeris - “ Sanawdan ýatlatma belgisini giriziň .” Girenlerinden soň gaýtadan işlemek üçin islenýän usula geçerler. Ine, biziň döwlet wyklýuçatelimiz:
public class BotStateCash {
    private final Map<long, botstate=""> botStateMap = new HashMap<>();

    public void saveBotState(long userId, BotState botState) {
        botStateMap.put(userId, botState);
    }
}

</long,>
Ulanyjy şahsyýeti we ýagdaýy bilen yzygiderli karta. Int adminId meýdançasy meniň üçin) Soňra, “HandUpdate” usulynyň logikasy munuň nähili habardygyny barlar? Jaň etmek ýa-da diňe tekst? Eger bu adaty tekst bolsa, onda esasy menýu düwmelerini gaýtadan işleýän “HandInputMessage” usulyna geçýäris we eger basylan bolsa, islenýän ýagdaýy kesgitläris, ýöne basylmasa we bu nätanyş tekst bolsa, onda biz ýagdaýy keşden düzüň, eger ol ýok bolsa, başlangyç ýagdaýyny belläris. Soňra tekst, gerekli ýagdaý bilen tutawaç usulyny gaýtadan işlemäge başlaýar. Indi botyň ýagdaýyna baglylykda habarlary gaýtadan işlemek üçin jogapkär “MessageHandler” synpynyň logikasyny hödürleýäris :
public class MessageHandler {

    private final UserDAO userDAO;
    private final MenuService menuService;
    private final EventHandler eventHandler;
    private final BotStateCash botStateCash;
    private final EventCash eventCash;

    public MessageHandler(UserDAO userDAO, MenuService menuService, EventHandler eventHandler, BotStateCash botStateCash, EventCash eventCash) {
        this.userDAO = userDAO;
        this.menuService = menuService;
        this.eventHandler = eventHandler;
        this.botStateCash = botStateCash;
        this.eventCash = eventCash;
    }

    public BotApiMethod<!--?--> handle(Message message, BotState botState) {
        long userId = message.getFrom().getId();
        long chatId = message.getChatId();
        SendMessage sendMessage = new SendMessage();
        sendMessage.setChatId(String.valueOf(chatId));
        //if new user
        if (!userDAO.isExist(userId)) {
            return eventHandler.saveNewUser(message, userId, sendMessage);
        }
        //save state in to cache
        botStateCash.saveBotState(userId, botState);
        //if state =...
        switch (botState.name()) {
            case ("START"):
                return menuService.getMainMenuMessage(message.getChatId(),
                        "Воспользуйтесь главным меню", userId);
            case ("ENTERTIME"):
                //set time zone user. for correct sent event
                return eventHandler.enterLocalTimeUser(message);
            case ("MYEVENTS"):
                //list events of user
                return eventHandler.myEventHandler(userId);
            case ("ENTERNUMBEREVENT"):
                //remove event
                return eventHandler.removeEventHandler(message, userId);
            case ("ENTERDESCRIPTION"):
                //enter description for create event
                return eventHandler.enterDescriptionHandler(message, userId);
            case ("ENTERDATE"):
                //enter date for create event
                return eventHandler.enterDateHandler(message, userId);
            case ("CREATE"):
                //start create event, set state to next step
                botStateCash.saveBotState(userId, BotState.ENTERDESCRIPTION);
                //set new event to cache
                eventCash.saveEventCash(userId, new Event());
                sendMessage.setText("Введите описание события");
                return sendMessage;
            case ("ENTERNUMBERFOREDIT"):
                //show to user selected event
                return eventHandler.editHandler(message, userId);
            case ("EDITDESCRIPTION"):
                //save new description in database
                return eventHandler.editDescription(message);
            case ("EDITDATE"):
                //save new date in database
                return eventHandler.editDate(message);
            case ("ALLEVENTS"):
                //only admin
                return eventHandler.allEvents(userId);
            case ("ALLUSERS"):
                //only admin
                return eventHandler.allUsers(userId);
            case ("ONEVENT"):
                // on/off notification
                return eventHandler.onEvent(message);
            case ("ENTERNUMBERUSER"):
                //only admin
                return eventHandler.removeUserHandler(message, userId);
            default:
                throw new IllegalStateException("Unexpected value: " + botState);
        }
    }
}
Tutuş usulynda, alnan habaryň ýagdaýyny barlaýarys we hadysany dolandyryjy - EventHandler synpyna iberýäris . Bu ýerde menýuService we EventCash atly iki sany täze synpymyz bar . Menýu hyzmaty - bu ýerde ähli menýularymyzy döredýäris. “EventCash” - “BotStateCash” -a meňzeş , girişden soň wakamyzyň böleklerini ýatda saklar we giriş gutarandan soň wakany maglumatlar bazasynda saklarys.
@Service
@Setter
@Getter
// used to save entered event data per session
public class EventCash {

    private final Map<long, event=""> eventMap = new HashMap<>();

    public void saveEventCash(long userId, Event event) {
        eventMap.put(userId, event);
    }
}
</long,>
Bolýar. bir waka döredenimizde, keş -ventCash.saveEventCash (userId, täze waka ()) keşinde täze Waka obýekti döredilýär; Soňra wakanyň beýanyny girizýäris we keş görnüşine goşýarys:
Event event = eventCash.getEventMap().get(userId);
event.setDescription(description);
//save to cache
eventCash.saveEventCash(userId, event);
Soňra belgini giriziň:
Event event = eventCash.getEventMap().get(userId);
event.setDate(date);
//save data to cache
eventCash.saveEventCash(userId, event);
“CallbackQueryHandler” synpy “MessageHandler” -e meňzeýär , diňe şol ýerdäki jaň habarlaryny işleýäris. Wakalar bilen işlemegiň logikasyny doly seljermegiň manysy ýok - EventHandler , eýýäm gaty köp harp bar, koddaky usullaryň we düşündirişleriň atlaryndan belli. Ony doly tekstde goýmagyň manysyny göremok, 300-den gowrak setir bar. Ine, Github -da klasa baglanyşyk . Menýulary döredýän “MenuService” synpy üçin hem edil şonuň ýaly . Olar hakda jikme-jik telegram kitaphanasynyň öndürijisiniň web sahypasynda okap bilersiňiz - https://github.com/rubenlagus/TelegramBots/blob/master/TelegramBots.wiki/FAQ.md Ora-da Telegram salgylanma kitabynda - https: // tlgrm.ru/docs/bots / api Indi iň ýakymly bölegi galdy. “EventService” habarlaryny dolandyrmak üçin synp :
@EnableScheduling
@Service
public class EventService {
    private final EventDAO eventDAO;
    private final EventCashDAO eventCashDAO;

    @Autowired
    public EventService(EventDAO eventDAO, EventCashDAO eventCashDAO) {
        this.eventDAO = eventDAO;
        this.eventCashDAO = eventCashDAO;
    }

    //start service in 0:00 every day
    @Scheduled(cron = "0 0 0 * * *")
    // @Scheduled(fixedRateString = "${eventservice.period}")
    private void eventService() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int month = calendar.get(Calendar.MONTH);
        int year = calendar.get(Calendar.YEAR);

        //get event list is now date
        List<event> list = eventDAO.findAllEvent().stream().filter(event -> {
            if (event.getUser().isOn()) {
                EventFreq eventFreq = event.getFreq();

                //set user event time
                Calendar calendarUserTime = getDateUserTimeZone(event);

                int day1 = calendarUserTime.get(Calendar.DAY_OF_MONTH);
                int month1 = calendarUserTime.get(Calendar.MONTH);
                int year1 = calendarUserTime.get(Calendar.YEAR);
                switch (eventFreq.name()) {
                    case "TIME": //if one time - remove event
                        if (day == day1 && month == month1 && year == year1) {
                            eventDAO.remove(event);
                            return true;
                        }
                    case "EVERYDAY":
                        return true;
                    case "MONTH":
                        if (day == day1) return true;
                    case "YEAR":
                        if (day == day1 && month == month1) return true;
                    default: return false;
                }
            } else return false;
        }).collect(Collectors.toList());

        for (Event event : list) {
            //set user event time
            Calendar calendarUserTime = getDateUserTimeZone(event);
            int hour1 = calendarUserTime.get(Calendar.HOUR_OF_DAY);
            calendarUserTime.set(year, month, day, hour1, 0, 0);

            String description = event.getDescription();
            String userId = String.valueOf(event.getUser().getId());

            //save the event to the database in case the server reboots.
            EventCashEntity eventCashEntity = EventCashEntity.eventTo(calendarUserTime.getTime(), event.getDescription(), event.getUser().getId());
            eventCashDAO.save(eventCashEntity);

            //create a thread for the upcoming event with the launch at a specific time
            SendEvent sendEvent = new SendEvent();
            sendEvent.setSendMessage(new SendMessage(userId, description));
            sendEvent.setEventCashId(eventCashEntity.getId());

            new Timer().schedule(new SimpleTask(sendEvent), calendarUserTime.getTime());
        }
    }

    private Calendar getDateUserTimeZone(Event event) {
        Calendar calendarUserTime = Calendar.getInstance();
        calendarUserTime.setTime(event.getDate());
        int timeZone = event.getUser().getTimeZone();

        //set correct event time with user timezone
        calendarUserTime.add(Calendar.HOUR_OF_DAY, -timeZone);
        return calendarUserTime;
    }
}

</event>
@EnableScheduling - Baharda meýilleşdirilen işe mümkinçilik beriň. @Scheduled (cron = "0 0 0 * * *") - her gün senenama.setTime (täze Sene ()) 0: 00-da işlemegiň usulyny düzýäris ; - serwer wagtyny belläň. Häzirki wagtda akymlaryň we lambda jadysynyň üsti bilen ýatlatmalaryň sanawyny alýarys. Alnan sanawdan geçýäris, dogry iberilýän wagt senenamasynyUserTime we ... Ine, şu ýerde gijikdirilen amallary taşlamagy we başlamagy makul bildim. Java-daky Wagt synpy munuň üçin jogapkärdir . täze Timer (). tertibi (täze SimpleTask (sendEvent), senenamaUserTime.getTime ()); Munuň üçin bir sapak döretmeli:
public class SendEvent extends Thread {


    private long eventCashId;
    private SendMessage sendMessage;

    public SendEvent() {
    }

    @SneakyThrows
    @Override
    public void run() {
        TelegramBot telegramBot = ApplicationContextProvider.getApplicationContext().getBean(TelegramBot.class);
        EventCashDAO eventCashDAO = ApplicationContextProvider.getApplicationContext().getBean(EventCashDAO.class);
        telegramBot.execute(sendMessage);
        //if event it worked, need to remove it from the database of unresolved events
        eventCashDAO.delete(eventCashId);
    }
}
we TimerTask- yň durmuşa geçirilmegi
public class SimpleTask extends TimerTask {
    private final SendEvent sendEvent;

    public SimpleTask(SendEvent sendEvent) {
        this.sendEvent = sendEvent;
    }

    @Override
    public void run() {
        sendEvent.start();
    }
}
Hawa, maglumatlar bazasyndan her 20 minutdan geçip, habar iberip biljekdigiňize men gowy düşünýärin, ýöne bu hakda hemme zady başda ýazypdym)) Bu ýerde 1-nji Heroku-nyň görgülerine-de duş gelýäris. Mugt meýilnamada size 550 dino berilýär, bu bolsa her aýda anketaňyzyň işleýiş sagatlary ýaly bir zat. Programmanyň doly işlemegi üçin bu ýeterlik däl, ýöne kartoçkany baglanyşdyrsaňyz, size ýene 450 dino berilýär, bu bolsa gözüňiz üçin ýeterlikdir. Kart barada alada edýän bolsaňyz, boş birini baglanyşdyryp bilersiňiz, ýöne $ 0.6 barlygyna göz ýetiriň ... Bu tassyklama mukdary, diňe hasapda bolmaly. Nyrhy özüňiz üýtgetmeseňiz, gizlin töleg ýok. Mugt meýilnamada ýene bir kiçijik mesele bar, oňa 1a diýeliň .. Serwerleri yzygiderli açýarlar ýa-da programmany täzeden açmak üçin buýruk iberýärler, umuman aýdylanda, her gün Moskwanyň ýary gijesinde bir ýerde täzeden açylýar we käwagt başga wagtlarda. Mundan, ýatdaky ähli amallarymyz pozulýar. Bu meseläni çözmek üçin “EventCash” tablisasyny tapdym. Ibermezden ozal wakalar aýratyn tablisada saklanýar:
EventCashEntity eventCashEntity = EventCashEntity.eventTo(calendarUserTime.getTime(), event.getDescription(), event.getUser().getId());
eventCashDAO.save(eventCashEntity);
Iberilenden soň aşakdakylar pozulýar:
@Override
public void run() {
    TelegramBot telegramBot = ApplicationContextProvider.getApplicationContext().getBean(TelegramBot.class);
    EventCashDAO eventCashDAO = ApplicationContextProvider.getApplicationContext().getBean(EventCashDAO.class);
    telegramBot.execute(sendMessage);
    //if event it worked, need to remove it from the database of unresolved events
    eventCashDAO.delete(eventCashId);
}
“ApplicationContextProvider” uçuşda kontekst almak üçin ýörite synpdyr:
@Component
//wrapper to receive Beans
public class ApplicationContextProvider implements ApplicationContextAware {

    private static ApplicationContext context;

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac)
            throws BeansException {
        context = ac;
    }
}
Işlenmedik wakalary barlamak üçin, @PostConstruct bellän usuly bolan ýörite hyzmat etdim - her programma başlanandan soň işleýär. Maglumatlar bazasyndan işlenmedik wakalaryň hemmesini alýar we ýada salýar. Ine, seniň üçin nejis Heroku!
@Component
public class SendEventFromCache {

    private final EventCashDAO eventCashDAO;
    private final TelegramBot telegramBot;

    @Value("${telegrambot.adminId}")
    private int admin_id;

    @Autowired
    public SendEventFromCache(EventCashDAO eventCashDAO, TelegramBot telegramBot) {
        this.eventCashDAO = eventCashDAO;
        this.telegramBot = telegramBot;
    }

    @PostConstruct
    @SneakyThrows
    //after every restart app  - check unspent events
    private void afterStart() {
        List<eventcashentity> list = eventCashDAO.findAllEventCash();

        SendMessage sendMessage = new SendMessage();
        sendMessage.setChatId(String.valueOf(admin_id));
        sendMessage.setText("Произошла перезагрузка!");
        telegramBot.execute(sendMessage);

        if (!list.isEmpty()) {
            for (EventCashEntity eventCashEntity : list) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(eventCashEntity.getDate());
                SendEvent sendEvent = new SendEvent();
                sendEvent.setSendMessage(new SendMessage(String.valueOf(eventCashEntity.getUserId()), eventCashEntity.getDescription()));
                sendEvent.setEventCashId(eventCashEntity.getId());
                new Timer().schedule(new SimpleTask(sendEvent), calendar.getTime());
            }
        }
    }
}
</eventcashentity>
Arzamyz taýýar, programma we maglumat bazasy üçin Heroku salgysyny almagyň wagty geldi. Arzaňyz Github-da çap edilmeli !!! Heroku.com sahypasyna giriň Täze programma döretmek düwmesine basyň , programma adyňyzy giriziň, Europeewropany saýlaň, programma dörediň . Ine, anketa üçin ýer taýýar. Açyk programmany bassaňyz , brauzer sizi programmaňyzyň salgysyna ugrukdyrar, bu web sahypa salgyňyz - https://your_name.herokuapp.com/ Ony telegramma ýazyň we programma.propertie sazlamalarynda telegrambot üýtgedilýär . webHookPath = https: //telegrambotsimpl.herokuapp.com/ serweriňize.port = 5000 öçürilip ýa-da düşündiriş berilip bilner. Indi maglumat bazasyny birleşdireliň. Heroku-daky Resurslar goýmasyna giriň , basyň: Şol ýerde Heroku PostgresiniTelegram bot - Java-da webHook arkaly ýatlatma ýa-da Google senenamasyna ýok diýiň!  2-nji bölüm: - 1 tapyň , gurmak düwmesine basyň : Maglumatlar bazasynyň hasaby sahypasyna ugrukdyrylarsyňyz. Sazlamalardan tapyň / Maglumat bazasyndan ähli zerur maglumatlar bolar. Programma.properties -de indi hemme zat şeýle bolmaly: Telegram bot - Java-da webHook arkaly ýatlatma ýa-da Google senenamasyna ýok diýiň!  2-nji bölüm: - 2
#server.port=5000

telegrambot.userName=@calendar_event_bot
telegrambot.botToken=1731265488:AAFDjUSk3vu5SFfgdfh556gOOFmuml7SqEjwrmnEF5Ak
telegrambot.webHookPath=https://telegrambotsimpl.herokuapp.com/
#telegrambot.webHookPath=https://f5d6beeb7b93.ngrok.io


telegrambot.adminId=39376213

eventservice.period =600000

#spring.datasource.driver-class-name=org.postgresql.Driver
#spring.datasource.url=jdbc:postgresql://localhost:5432/telegramUsers
#spring.datasource.username=postgres
#spring.datasource.password=password

spring.datasource.url=jdbc:postgresql:ec2-54-247-158-179.eu-west-1.compute.amazonaws.com:5432/d2um26le5notq?ssl=true&sslmode=require&sslfactory=org.postgresql.ssl.NonValidatingFactory
spring.datasource.username=ulmbeymwyvsxa
spring.datasource.password=4c7646c69dbgeacbk98fa96e8daa6d9b1bl4894e67f3f3ddd6a27fe7b0537fd
Hasabyňyzdaky maglumatlary özüňiz bilen çalyşyň: jdbc: postgresql: ec2-54-247-158-179.eu-west-1.compute.amazonaws.com: 5432 / d2um26le5notq? Ssl = true & sslmode = zerur & sslfactory = org. postgresql.ssl .NonValidatingFactory hasabyň degişli maglumatlary (Host, Maglumat bazasy) bilen goýy bilen çalyşmaly. Ulanyjy adyny, parol meýdanlaryny çaklamak kyn däl. Indi maglumatlar bazasynda tablisalar döretmeli, muny IDEA-dan etdim. Scriptazgylarymyz maglumat bazasyny döretmek üçin peýdaly bolar. Maglumatlar bazasyny ýokarda ýazylyşy ýaly goşýarys: Hasapdan Telegram bot - Java-da webHook arkaly ýatlatma ýa-da Google senenamasyna ýok diýiň!  2-nji bölüm: - 3 Host , Ulanyjy, Parol, Maglumat bazasy meýdançasyny alýarys. URl meýdançasy, sorag belgisine çenli bahar.datasource.url meýdançamyzdyr. “Advanced” goýmasyna girýäris , ol şeýle bolmaly: Telegram bot - Java-da webHook arkaly ýatlatma ýa-da Google senenamasyna ýok diýiň!  2-nji bölüm: - 4 Eger hemme zady dogry eden bolsaňyz, synaga basanyňyzdan soň ýaşyl bellik bolar. OK basyň. Maglumat bazamyzda sag düwmä basyň we gözleg konsolyna geçiň . Scriptazgylarymyzy şol ýere göçüriň we ýerine ýetirmek düwmesine basyň . Maglumat bazasy döredilmeli. 10,000 setir mugt! Hemme zat ýerleşdirmäge taýýar. Heroku baradaky arzamy ýerleşdirmek bölüminde görüň. Şol ýerdäki Github bölümini saýlaň: Telegram bot - Java-da webHook arkaly ýatlatma ýa-da Google senenamasyna ýok diýiň!  2-nji bölüm: - 5 Ammaryňyzy Heroku bilen baglanyşdyryň. Indi şahalaryňyz görüner. Iň soňky üýtgeşmeleriňizi .properties-e geçirmegi ýatdan çykarmaň. Aşakda göçüriljek şahany saýlaň we ýerleşdirmek bölümini basyň . Hemme zat dogry ýerine ýetirilen bolsa, programmanyň üstünlikli ýerleşdirilendigi size habar berler. Awtomatiki ýerleşdirmeleri işletmegi ýatdan çykarmaň .. Programmaňyz awtomatiki başlar ýaly. Theeri gelende aýtsak, GitHub-a üýtgeşmeler girizeniňizde, Heroku programmany awtomatiki açar. Bu meselede seresap boluň, gorkuzmak üçin aýratyn sapak dörediň we esasy bölegini diňe iş programmasy üçin ulanyň. Indi arzanlyk # 2! Bu Heroku üçin mugt meýilnamanyň belli bir kemçiligi. Gelýän habarlar ýok bolsa, programma garaşma tertibine girýär we habar alandan soň başlamak üçin ep-esli wagt gerek bolar, bu ýakymly däl. Munuň üçin ýönekeý çözgüt bar - https://uptimerobot.com/ Nook, Google ping enjamlary kömek edip bilmez, bu maglumatyň nireden gelendigini hem bilemok, bu soraga göz aýladym we takmynan 10 ýyl bäri bu mowzuk düýbünden işlemedi. Bu programma, bellenen wagt üçin kesgitlän adresiňize HEAD haýyşlaryny iberer we jogap bermese e-poçta arkaly habar iberer. Muny anyklamak kyn bolmaz, bulaşdyrmak üçin düwmeler ýeterlik däl)) Gutlaýarys !! Hiç zady ýatdan çykarmadyk bolsam we üns beren bolsaňyz, mugt işleýän we hiç haçan ýykylmaýan öz programmaňyz bar. Gorkuzmak we synag etmek mümkinçiligi siziň öňüňizde açylýar. Her niçigem bolsa, soraglara jogap bermäge we islendik tankydy kabul etmäge taýyn! Kod: https://github.com/papoff8295/webHookBotForHabr Ulanylan materiallar: https://tlgrm.ru/docs/bots/api - botlar hakda. https://en.wikibooks.org/wiki/Java_Persistence - maglumat bazalaryndaky gatnaşyklar hakda. https://stackoverflow.com/questions/11432498/how-to-call-a-thread-to-run-on-specific-time-in-java - Wagt synpy we TimerTask https://www.youtube.com/ sagat? v = CUDgSbaYGx4 - Github-a nädip kod ibermeli https://github.com/rubenlagus/TelegramBots - telegram kitaphanasy we bu hakda köp peýdaly maglumatlar.
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION