JavaRush /จาวาบล็อก /Random-TH /บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิ...
Vladimir Popov
ระดับ

บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google! ส่วนที่ 2

เผยแพร่ในกลุ่ม
ส่วนที่สองของโครงการ - นี่คือลิงก์ไปยังส่วนแรก: ดังนั้น คลาส BotState : เพื่อให้บอทของเราเข้าใจสิ่งที่คาดหวัง ณ จุดใดจุดหนึ่ง เช่น การลบการแจ้งเตือน เราจำเป็นต้อง แจ้งให้บอทของเราทราบว่าหมายเลขที่ป้อนและส่งตอนนี้ควรถือเป็นรหัสเตือนความจำจากรายการและควรลบออก ดังนั้น หลังจากคลิกที่ ปุ่ม "ลบ"บอทจะเข้าสู่ สถานะ BotState.ENTERNUMBEREVENTนี่คือคลาส Enum ที่สร้างขึ้นเป็นพิเศษพร้อมสถานะบอท
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
}
และตอนนี้เราคาดว่าจะป้อนตัวเลข - “ ป้อนหมายเลขเตือนความจำจากรายการ ” หลังจากกรอกแล้วจะเข้าสู่วิธีการประมวลผลที่ต้องการ นี่คือสวิตช์สถานะของเรา:
public class BotStateCash {
    private final Map<long, botstate=""> botStateMap = new HashMap<>();

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

</long,>
แผนที่ปกติพร้อม ID ผู้ใช้และสถานะ ช่องint adminIdมีไว้สำหรับฉัน) ต่อไป ตรรกะของ เมธอด handleUpdateจะตรวจสอบว่าข้อความนี้เป็นข้อความประเภทใด Callbackqueryหรือเพียงแค่ส่งข้อความ? หากนี่เป็นข้อความปกติ เราจะไปที่ เมธอด handleInputMessageโดยที่เราประมวลผลปุ่มเมนูหลัก และหากปุ่มเหล่านั้นถูกคลิก เราก็จะตั้งค่าสถานะที่ต้องการ แต่ถ้าพวกเขาไม่ได้คลิกและนี่เป็นข้อความที่ไม่คุ้นเคย เราก็จะตั้งค่าสถานะนั้น ตั้งค่าสถานะจากแคช หากไม่มีเราจะตั้งค่าสถานะเริ่มต้น จากนั้นข้อความจะเข้าสู่การประมวลผลวิธีจัดการตามสถานะที่เราต้องการ ตอนนี้เรานำเสนอตรรกะของ คลาส MessageHandlerซึ่งมีหน้าที่ในการประมวลผลข้อความขึ้นอยู่กับสถานะของบอท:
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);
        }
    }
}
ในเมธอด handle เราจะตรวจสอบสถานะของข้อความที่เราได้รับและส่งไปยังตัวจัดการเหตุการณ์ - คลาส EventHandler เรามีคลาสใหม่สองคลาสMenuService และ EventCash MenuService – ที่นี่เราสร้างเมนูทั้งหมดของเรา EventCash - คล้ายกับBotStateCashโดยจะบันทึกบางส่วนของกิจกรรมของเราหลังจากป้อนข้อมูล และเมื่อป้อนข้อมูลเสร็จสิ้น เราจะบันทึกกิจกรรมในฐานข้อมูล
@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,>
นั่นคือ เมื่อเราสร้างเหตุการณ์ ออบเจ็กต์เหตุการณ์ใหม่จะถูกสร้างขึ้นในแคช -eventCash.saveEventCash(userId, new Event()); จากนั้นเราป้อนคำอธิบายของเหตุการณ์และเพิ่มลงในแคช:
Event event = eventCash.getEventMap().get(userId);
event.setDescription(description);
//save to cache
eventCash.saveEventCash(userId, event);
จากนั้นป้อนหมายเลข:
Event event = eventCash.getEventMap().get(userId);
event.setDate(date);
//save data to cache
eventCash.saveEventCash(userId, event);
คลาส CallbackQueryHandler คล้ายกับMessageHandlerมีเพียงเราเท่านั้นที่ประมวลผลข้อความ callbackquery ที่นั่น ไม่มีเหตุผล ที่จะวิเคราะห์ตรรกะของการทำงานกับเหตุการณ์อย่างสมบูรณ์ - EventHandlerมีตัวอักษรมากเกินไปอยู่แล้วชัดเจนจากชื่อของวิธีการและความคิดเห็นในโค้ด และผมไม่เห็นประเด็นที่ต้องจัดเป็นข้อความให้หมดเลย มีมากกว่า 300 บรรทัด นี่คือลิงค์ไปยังชั้นเรียนบนGithub เช่นเดียวกับ คลาส MenuServiceที่เราสร้างเมนูของเรา คุณสามารถอ่านรายละเอียดเกี่ยวกับพวกเขาได้บนเว็บไซต์ของผู้ผลิตห้องสมุดโทรเลข - https://github.com/rubenlags/TelegramBots/blob/master/TelegramBots.wiki/FAQ.md หรือในหนังสืออ้างอิง Telegram - https:// tlgrm.ru/docs/bots /api ตอนนี้เราเหลือส่วนที่อร่อยที่สุดแล้ว นี่คือคลาสสำหรับจัดการ ข้อความ EventService :
@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 – เปิดใช้งานการทำงานตามกำหนดเวลาใน Spring @Scheduled(cron = "0 0 0 * * *") – เรากำหนดค่าวิธีการให้ทำงานเวลา 0:00 น. ทุกวัน Calendar.setTime(new Date()); - ตั้งเวลาเซิร์ฟเวอร์ เราได้รับรายการเตือนความจำสำหรับวันนี้ ผ่านทางความมหัศจรรย์ของลำธารและแลมบ์ดา เราผ่านรายการที่ได้รับตั้งเวลาส่งที่ถูกต้องCalendarUserTimeและ... นี่คือที่ฉันตัดสินใจหลบและเปิดกระบวนการล่าช้าตามเวลา คลาส Timeใน java รับผิดชอบสิ่งนี้ ตัวจับเวลาใหม่ (). กำหนดการ ( SimpleTask ใหม่ (sendEvent), ปฏิทิน UserTime.getTime ()); เพื่อที่เราจะต้องสร้างกระทู้:
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);
    }
}
และการใช้งานTimerTask
public class SimpleTask extends TimerTask {
    private final SendEvent sendEvent;

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

    @Override
    public void run() {
        sendEvent.start();
    }
}
ใช่ฉันเข้าใจดีว่าคุณสามารถผ่านฐานข้อมูลทุก ๆ 20 นาทีและส่งข้อความ แต่ฉันเขียนทุกอย่างเกี่ยวกับเรื่องนี้ตั้งแต่เริ่มต้น)) ที่นี่เรายังพบกับความทุกข์ยากของ Heroku No. 1 สำหรับแผนแบบฟรี คุณจะได้รับไดโนจำนวน 550 ตัว ซึ่งเท่ากับชั่วโมงการทำงานของแอปพลิเคชันของคุณต่อเดือน นี่ไม่เพียงพอสำหรับการทำงานของแอปพลิเคชันทั้งเดือน แต่ถ้าคุณเชื่อมโยงการ์ด คุณจะได้รับดิโนอีก 450 ตัวซึ่งเพียงพอสำหรับดวงตาของคุณ หากคุณกังวลเกี่ยวกับบัตร คุณสามารถเชื่อมโยงบัตรเปล่าได้ แต่ตรวจสอบให้แน่ใจว่ามี $0.6... นี่คือจำนวนเงินในการยืนยัน เพียงแต่ต้องอยู่ในบัญชี ไม่มีค่าใช้จ่ายแอบแฝง เว้นแต่คุณจะเปลี่ยนอัตราภาษีด้วยตนเอง ในแผนบริการแบบฟรีมีปัญหาเล็กๆ อีกปัญหาหนึ่ง เรียกว่าหมายเลข 1a. พวกเขารีบูตเซิร์ฟเวอร์อย่างต่อเนื่องหรือเพียงแค่ส่งคำสั่งเพื่อรีสตาร์ทแอปพลิเคชัน โดยทั่วไปแล้วจะรีบูตทุกวันที่ไหนสักแห่งในเวลาเที่ยงคืนของมอสโกและในบางครั้ง ในเวลาอื่น จากนี้กระบวนการทั้งหมดของเราในหน่วยความจำจะถูกลบ เพื่อแก้ไขปัญหานี้ ฉันจึงสร้างตาราง EventCash ขึ้นมา ก่อนที่จะส่ง กิจกรรมจะถูกบันทึกในตารางแยกต่างหาก:
EventCashEntity eventCashEntity = EventCashEntity.eventTo(calendarUserTime.getTime(), event.getDescription(), event.getUser().getId());
eventCashDAO.save(eventCashEntity);
และหลังจากส่งแล้ว ข้อมูลต่อไปนี้จะถูกลบ:
@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เป็นคลาสพิเศษสำหรับรับบริบทได้ทันที:
@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;
    }
}
เพื่อตรวจสอบเหตุการณ์ที่ยังไม่ได้ประมวลผล ฉันได้สร้างบริการพิเศษที่มีเมธอดที่ทำเครื่องหมายว่า@PostConstructซึ่งจะทำงานหลังจากแต่ละแอปพลิเคชันเริ่มทำงาน จะเลือกเหตุการณ์ที่ยังไม่ได้ประมวลผลทั้งหมดจากฐานข้อมูลและส่งกลับไปยังหน่วยความจำ นี่คือ 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>
แอปพลิเคชันของเราพร้อมแล้ว และถึงเวลาที่เราจะได้รับที่อยู่ Heroku สำหรับแอปพลิเคชันและฐานข้อมูล ใบสมัครของคุณจะต้องเผยแพร่บน Github!!! ไปที่ Heroku.com คลิกสร้างแอปใหม่ป้อนชื่อแอปพลิเคชันของคุณ เลือกยุโรป สร้างแอป เพียงเท่านี้สถานที่สำหรับการสมัครก็พร้อมแล้ว หากคุณคลิกเปิดแอป เบราว์เซอร์จะนำคุณไปยังที่อยู่ของแอปพลิเคชันของคุณ นี่คือที่อยู่ webhook ของคุณ - https://your_name.herokuapp.com/ ลงทะเบียนในโทรเลข และใน การตั้งค่าของ application.propertyให้เปลี่ยนtelegrambot webHookPath=https: //telegrambotsimpl.herokuapp.com/ ไปยัง server.port=5000ของคุณ สามารถลบหรือใส่ความคิดเห็นได้ ตอนนี้เรามาเชื่อมต่อฐานข้อมูลกัน ไปที่ แท็บ ทรัพยากรบน Heroku คลิก: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  ส่วนที่ 2: - 1 ค้นหาHeroku Postgres ที่นั่น คลิกติดตั้ง : คุณจะถูกเปลี่ยนเส้นทางไปยังหน้าบัญชีฐานข้อมูลของคุณ ค้นหาได้ในการตั้งค่า/ บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  ส่วนที่ 2: - 2 จะมีข้อมูลที่จำเป็นทั้งหมดจากฐานข้อมูลของคุณ ในapplication.propertiesตอนนี้ทุกอย่างควรเป็นดังนี้:
#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
แทนที่ข้อมูลจากบัญชีของคุณด้วยข้อมูลของคุณ: ในฟิลด์ jdbc:postgresql:ec2-54-247-158-179.eu-west-1.compute.amazonaws.com:5432/d2um26le5notq?ssl=true&sslmode=require&sslfactory=org postgresql.ssl .NonValidatingFactory จะต้องแทนที่ด้วยตัวหนาด้วยข้อมูลที่เกี่ยวข้องจากบัญชี (โฮสต์, ฐานข้อมูล) ช่องชื่อผู้ใช้และรหัสผ่านนั้นเดาได้ไม่ยาก ตอนนี้เราต้องสร้างตารางในฐานข้อมูล ฉันทำสิ่งนี้จาก IDEA สคริปต์ของเราจะมีประโยชน์สำหรับการสร้างฐานข้อมูล เราเพิ่มฐานข้อมูลตามที่เขียนไว้ด้านบน: เรานำ บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  ส่วนที่ 2: - 3 ฟิลด์Host, User, Password, Databaseจากบัญชี ฟิลด์URlคือฟิลด์ spring.datasource.url ของเราจนถึงเครื่องหมายคำถาม ไปที่ แท็บ ขั้นสูงมันควรจะเป็นดังนี้: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  ส่วนที่ 2: - 4 หากคุณทำทุกอย่างถูกต้องแล้วหลังจากคลิกแบบทดสอบแล้วจะมีเครื่องหมายถูกสีเขียว คลิกตกลง คลิกขวาที่ฐานข้อมูลของเรา และเลือกJump to Query Console คัดลอกสคริปต์ของเราที่นั่นแล้วคลิกดำเนินการ ควรสร้างฐานข้อมูล ให้คุณใช้งานได้ฟรี 10,000 บรรทัด! ทุกอย่างพร้อมสำหรับการปรับใช้ ไปที่แอปพลิเคชันของเราบน Heroku ในส่วนปรับใช้ เลือกส่วน Github ที่นั่น: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  ส่วนที่ 2: - 5 เชื่อมโยงพื้นที่เก็บข้อมูลของคุณกับ Heroku ตอนนี้กิ่งก้านของคุณจะปรากฏให้เห็น อย่าลืมส่งการเปลี่ยนแปลงล่าสุดของคุณไปที่ .properties ด้าน ล่างเลือกสาขาที่จะดาวน์โหลด และคลิกปรับใช้สาขา หากทุกอย่างถูกต้อง คุณจะได้รับแจ้งว่าแอปพลิเคชันได้รับการปรับใช้เรียบร้อยแล้ว อย่าลืมเปิดใช้งานการปรับใช้อัตโนมัติจาก .. เพื่อให้แอปพลิเคชันของคุณเริ่มทำงานโดยอัตโนมัติ อย่างไรก็ตาม เมื่อคุณกดการเปลี่ยนแปลงไปที่ GitHub Heroku จะรีสตาร์ทแอปพลิเคชันโดยอัตโนมัติ โปรดใช้ความระมัดระวังในเรื่องนี้ สร้างกระทู้แยกต่างหากสำหรับการกลั่นแกล้ง และใช้กระทู้หลักสำหรับแอปพลิเคชันที่ใช้งานได้เท่านั้น ตอนนี้ราคาถูก #2! นี่เป็นข้อเสียที่รู้จักกันดีของแผนฟรีสำหรับ Heroku หากไม่มีข้อความเข้าแอปพลิเคชันจะเข้าสู่โหมดสแตนด์บายและหลังจากได้รับข้อความแล้วจะใช้เวลานานในการเริ่มต้นซึ่งไม่น่าพอใจ มีวิธีแก้ไขง่ายๆ สำหรับสิ่งนี้ - https://uptimerobot.com/ และไม่ อุปกรณ์ปิงของ Google จะไม่ช่วย ฉันไม่รู้ด้วยซ้ำว่าข้อมูลนี้มาจากไหน ฉันค้นหาคำถามนี้ใน Google และเป็นเวลาประมาณ 10 ปีแล้วที่หัวข้อนี้ใช้งานไม่ได้อย่างแน่นอน ถ้ามันได้ผลเลย แอปพลิเคชันนี้จะส่งคำขอ HEAD ไปยังที่อยู่ที่คุณระบุตามเวลาที่คุณตั้งไว้ และหากไม่ตอบสนอง ก็จะส่งข้อความทางอีเมล คุณจะเข้าใจได้ไม่ยาก ปุ่มมีไม่มากพอที่จะสับสน)) ยินดีด้วย!! หากฉันไม่ลืมสิ่งใดและคุณใส่ใจ แสดงว่าคุณก็มีแอปพลิเคชันของคุณเองที่ทำงานได้ฟรีและไม่เคยขัดข้อง โอกาสในการกลั่นแกล้งและการทดลองเปิดอยู่ตรงหน้าคุณ ยังไงก็พร้อมตอบทุกคำถามและทุกคำวิจารณ์! รหัส: https://github.com/papoff8295/webHookBotForHabr วัสดุที่ใช้: https://tlgrm.ru/docs/bots/api - เกี่ยวกับบอท https://en.wikibooks.org/wiki/Java_Persistence - เกี่ยวกับความสัมพันธ์ในฐานข้อมูล https://stackoverflow.com/questions/11432498/how-to-call-a-thread-to-run-on-special-time-in-java - คลาสเวลาและ TimerTask https://www.youtube.com/ watch?v=CUDgSbaYGx4 – วิธีโพสต์โค้ดบน Github https://github.com/rubenlags/TelegramBots - ไลบรารีโทรเลขและข้อมูลที่เป็นประโยชน์มากมายเกี่ยวกับมัน
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION