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

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

เผยแพร่ในกลุ่ม
ฉันชื่อวลาดิเมียร์ ฉันอายุ 43 ปี และถ้าคุณผู้อ่านอายุเกิน 40 ปีแล้วล่ะก็ หลังจากอายุ 40 ปีคุณก็สามารถเป็นโปรแกรมเมอร์ได้ถ้าชอบ งานของฉันไม่เกี่ยวกับการเขียนโปรแกรมเลย ฉันเป็นผู้จัดการโครงการในสาขาระบบอัตโนมัติและทั้งหมดนั้น แต่ฉันวางแผนที่จะเปลี่ยนอาชีพของฉัน โอ้ เทรนด์ใหม่เหล่านี้... เปลี่ยนสาขากิจกรรมของคุณทุกๆ 5-7 ปี ดังนั้น : โปรเจ็กต์นี้กลายเป็นโปรเจ็กต์ที่ค่อนข้างใหญ่ เลยต้องละเว้นบางจุดหรือพูดคุยสั้นๆ ด้วยความหวังว่าผู้อ่านจะรู้จัก Google อินเทอร์เน็ตเต็มไปด้วยสิ่งพิมพ์ของบอทโทรเลขที่ทำงานเกี่ยวกับหลักการของการสำรวจความคิดเห็นแบบยาว และมีน้อยมากที่ใช้หลักการ Webhook ได้ มันคืออะไร? การโพลแบบยาว - หมายความว่าแอปพลิเคชันของคุณจะสำรวจเซิร์ฟเวอร์โทรเลขเพื่อหาข้อความที่ความถี่หนึ่งอย่างช้าๆ Webhook - หมายถึงเซิร์ฟเวอร์โทรเลขจะเปลี่ยนเส้นทางข้อความไปยังเซิร์ฟเวอร์ที่คุณระบุทันที ในกรณีของเรา ได้รับความอนุเคราะห์จากบริการ Heroku แน่นอนคุณสามารถอ่านเพิ่มเติมเกี่ยวกับทั้งหมดนี้และเกี่ยวกับบอทโดยทั่วไปได้ที่เว็บไซต์ Telegram - https://tlgrm.ru/docs/bots/api อินเทอร์เฟซของบอทมีลักษณะดังนี้: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 1 ฉันถือว่าแอปพลิเคชันนี้เป็นการฝึกอบรมอย่างแม่นยำ โครงการด้วยเหตุผลที่ว่าเมื่อเขียนฉันเรียนรู้ข้อมูลจากบอทนี้มากกว่าตอนฝึกอบรม คุณต้องการเรียนรู้การเขียนโปรแกรมหรือไม่? เริ่มเขียนโค้ด!!! แต่! จะไม่มีคำแนะนำโดยละเอียดเกี่ยวกับวิธีการอัปโหลดแอปพลิเคชันไปยัง GitHub หรือวิธีสร้างฐานข้อมูล มีสิ่งนี้มากมายบนอินเทอร์เน็ตและมีการอธิบายอย่างละเอียด นอกจากนี้ มันจะเป็นการอ่านที่ยาวมาก แอพพลิเคชั่นจะทำงานดังนี้ ใส่คำอธิบายงาน, ใส่วันที่และเวลาของงาน, เลือกความถี่ (ทำได้ครั้งเดียว, ตั้งเตือนได้ทุกวันตามเวลาที่กำหนด, ตั้งได้ครั้งเดียว) เดือนละครั้งหรือปีละครั้ง) สามารถเพิ่มการแจ้งเตือนรูปแบบต่างๆ ได้ไม่รู้จบ ฉันมีไอเดียมากมาย ถัดไป ข้อมูลที่ป้อนจะถูกบันทึกลงในฐานข้อมูล (ใช้งานฟรีบน Heroku ได้ฟรี 10,000 แถว) จากนั้นเมื่อเริ่มต้นวันใหม่เวลา 0:00 น. ตามเวลาเซิร์ฟเวอร์ Spring จะดึงข้อมูลเหตุการณ์ทั้งหมดจากฐานข้อมูลตามเกณฑ์ ที่ควรยิงในวันนั้นและส่งไปปฏิบัติการตามเวลาที่กำหนด ความสนใจ!!! ส่วนนี้ของโปรแกรมเป็นการทดลอง! มีการดำเนินการที่เรียบง่ายและเป็นจริงมากขึ้น! สิ่งนี้ทำขึ้นโดยเฉพาะเพื่อดูว่าคลาสเรียนทำงานอย่างไร! คุณสามารถสัมผัสบอทที่ใช้งานได้ด้วยมือของคุณเองโดยพิมพ์ @calendar_event_bot ลงในรถเข็น แต่อย่าพึ่งเชื่อใจมัน เพราะฉันยังคงสนุกกับมันอยู่ รหัส - https://github.com/papoff8295/webHookBotForHabr โดยพื้นฐานแล้ว ในการเปิดตัวของคุณเอง คุณต้องทำตามขั้นตอนต่อไปนี้: • ลงทะเบียนกับ@BotFatherไม่ยาก รับโทเค็นและชื่อ • แยกโครงการบน github • ลงทะเบียน บนเฮโรกุสร้างแอปพลิเคชัน (เราจะดำเนินการทีละขั้นตอน) ปรับใช้จากพื้นที่เก็บข้อมูลของคุณ • สร้างฐานข้อมูลบน Heroku • แทนที่ฟิลด์ที่เกี่ยวข้องในพื้นที่เก็บข้อมูลด้วยฟิลด์ของคุณเอง (โทเค็น ชื่อของตารางในเอนทิตี webHookPath ชื่อผู้ใช้ รหัสผ่าน และเส้นทางไปยังฐานข้อมูล ซึ่งทั้งหมดนี้จะถูกแยกวิเคราะห์) • ทำให้ Heroku ทำงานได้ 24/ 7 โดยใช้https:/ /uptimerobot.com/ โครงสร้างสุดท้ายของโครงการมีดังนี้: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 2 เริ่มต้นด้วยการสร้างโครงการในhttps://start.spring.ioเลือกการพึ่งพาที่เราต้องการดังแสดงในรูป: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 3เลือกของเราเอง ชื่อโครงการแล้วคลิกสร้าง ถัดไปคุณจะได้รับแจ้งให้บันทึกโครงการลงในดิสก์ของคุณ สิ่งที่เหลืออยู่คือการเปิด ไฟล์pom.xm l จากสภาพแวดล้อมการพัฒนาของคุณ มีโครงการที่เสร็จแล้วอยู่ตรงหน้าคุณ ตอนนี้เราเพียงแค่ต้องเพิ่มห้องสมุดหลักของเรา ฉันใช้ไลบรารีจากhttps://github.com/rubenlags/TelegramBots โดยทั่วไปแล้วคุณอาจสับสนและทำไม่ได้ ท้ายที่สุดแล้ว ประเด็นทั้งหมดของงานคือการต่อ URL แบบนี้: https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io ลองดูกันสักหน่อย : https://api.telegram.org – เซิร์ฟเวอร์โทรเลข bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/ - หลังคำว่า bot เป็นโทเค็นลับที่คุณได้รับเมื่อลงทะเบียนบอท setWebhook?url=https://e9c658b548aa.ngrok.io – ชื่อของวิธีการและพารามิเตอร์ ในกรณีนี้ เราติดตั้งเซิร์ฟเวอร์ webhook ของคุณ ข้อความทั้งหมดจะถูกส่งไปยังเซิร์ฟเวอร์นั้น โดยทั่วไป ฉันตัดสินใจว่าโปรเจ็กต์นี้ไม่เล็กเกินไปสำหรับการเผยแพร่ แต่เมื่อใช้งานด้วยตนเอง โดยทั่วไปแล้วจะไม่สามารถอ่านได้ ดังนั้นลักษณะสุดท้ายของ ไฟล์ pomคือ:
<!--?xml version="1.0" encoding="UTF-8"?-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelversion>4.0.0</modelversion>
   <parent>
      <groupid>org.springframework.boot</groupid>
      <artifactid>spring-boot-starter-parent</artifactid>
      <version>2.5.0</version>
      <relativepath> <!-- lookup parent from repository -->
   </relativepath></parent>
   <groupid>ru.popov</groupid>
   <artifactid>telegrambot</artifactid>
   <version>0.0.1-SNAPSHOT</version>
   <name>telegrambot</name>
   <description>Demo project for Spring Boot</description>
   <properties>
      <java.version>1.8</java.version>
   </properties>
   <dependencies>
      <dependency>
         <groupid>org.springframework.boot</groupid>
         <artifactid>spring-boot-starter-web</artifactid>
      </dependency>

      <dependency>
         <groupid>org.springframework.boot</groupid>
         <artifactid>spring-boot-starter-data-jpa</artifactid>
      </dependency>

      <dependency>
         <groupid>org.springframework.boot</groupid>
         <artifactid>spring-boot-starter-test</artifactid>
         <scope>test</scope>
      </dependency>

      <!-- https://mvnrepository.com/artifact/org.telegram/telegrambots-spring-boot-starter -->
      <dependency>
         <groupid>org.telegram</groupid>
         <artifactid>telegrambots-spring-boot-starter</artifactid>
         <version>5.2.0</version>
      </dependency>

      <dependency>
         <groupid>org.projectlombok</groupid>
         <artifactid>lombok</artifactid>
         <version>1.18.16</version>
      </dependency>

      <dependency>
         <groupid>org.postgresql</groupid>
         <artifactid>postgresql</artifactid>
         <scope>runtime</scope>
      </dependency>

   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-maven-plugin</artifactid>
         </plugin>
      </plugins>
   </build>

</project>
ทุกอย่างพร้อมที่จะเขียนบอทของเราแล้ว มาสร้าง คลาสTelegramBotกัน ฉันจะไม่เขียนชื่อโฟลเดอร์ คุณสามารถดูได้ในโครงสร้างโปรเจ็กต์ด้านบน
@Getter
@Setter
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TelegramBot extends SpringWebhookBot {
    String botPath;
    String botUsername;
    String botToken;

    private TelegramFacade telegramFacade;

    public TelegramBot(TelegramFacade telegramFacade, DefaultBotOptions options, SetWebhook setWebhook) {
        super(options, setWebhook);
        this.telegramFacade = telegramFacade;
    }
    public TelegramBot(TelegramFacade telegramFacade, SetWebhook setWebhook) {
        super(setWebhook);
        this.telegramFacade = telegramFacade;
    }

    @Override
    public BotApiMethod<!--?--> onWebhookUpdateReceived(Update update) {
        return telegramFacade.handleUpdate(update);
    }
}
คลาสขยายSpringWebhookBot จากไลบรารีโทรเลข ของเรา และเราจำเป็นต้องใช้เพียงวิธีเดียวเท่านั้นonWebhookUpdateReceived ยอมรับJSON ที่แยกวิเคราะห์ เป็นวัตถุอัปเดตและส่งคืนสิ่งที่เซิร์ฟเวอร์โทรเลขต้องการ "ได้ยิน" จากเรา เรามีคำอธิบายประกอบจาก ห้องสมุด ลอมบอก ที่ นี่ ลอมบอก – ทำให้ชีวิตของโปรแกรมเมอร์ง่ายขึ้น!! นั่นคือ เราไม่จำเป็นต้องกำหนด getters และ setters ใหม่ ลอมบอกทำสิ่งนี้ให้เรา และเราไม่จำเป็นต้องเขียนตัวระบุระดับการเข้าถึงด้วย ไม่ควรเขียนอีกต่อไปว่าสิ่งนี้เสร็จสิ้นโดยคำอธิบายประกอบ@Getter, @Setter, @FieldDefaults ฟิลด์botPathหมายถึงที่อยู่ webhook ของเรา ซึ่งเราจะได้รับจาก Heroku ในภายหลัง ช่องbotUsernameหมายถึงชื่อของบอทของเรา ซึ่งเราจะได้รับเมื่อลงทะเบียนบอทของเราใน Telegram ช่องbotTokenคือโทเค็นของเรา ซึ่งเราจะได้รับเมื่อลงทะเบียนบอทของเราใน Telegram ฟิลด์telegramFacadeเป็นคลาสของเราที่การประมวลผลข้อความจะเกิดขึ้น เราจะกลับมาดูในภายหลัง ปล่อยให้เป็นสีแดงในตอนนี้ ตอนนี้ถึงเวลาที่เราจะติดต่อ@BotFatherและรับ botToken และ botUsername ที่เป็นที่ต้องการ บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 4แค่เขียนถึงเขาทางโทรเลขแล้วเขาจะบอกคุณทุกอย่าง เราเขียนข้อมูลลงใน application.properties ของเรา ในที่สุดก็จะมีลักษณะดังนี้:
server#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/d2um126le5notq?ssl=true&sslmode=require&sslfactory=org.postgresql.ssl.NonValidatingFactory
#spring.datasource.username=ulmbeywyhvsxa
#spring.datasource.password=4c7646c69dbbgeacb98fa96e8daa6d9b1bl4894e67f3f3ddd6a27fe7b0537fd
การกำหนดค่านี้ได้รับการกำหนดค่าให้ทำงานกับฐานข้อมูลท้องถิ่น หลังจากนั้นเราจะทำการเปลี่ยนแปลงที่จำเป็นในภายหลัง แทนที่botTokenและชื่อผู้ใช้ด้วยชื่อผู้ใช้ของคุณเอง การใช้ข้อมูลจาก application.properties โดยตรงในแอปพลิเคชันนั้นไม่ดี มาสร้าง bean หรือคลาส wrapper จากข้อมูลนี้กันดีกว่า
@Component
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)

public class TelegramBotConfig {
    @Value("${telegrambot.webHookPath}")
    String webHookPath;
    @Value("${telegrambot.userName}")
    String userName;
    @Value("${telegrambot.botToken}")
    String botToken;
ที่นี่คำอธิบายประกอบ @Value จะเริ่มต้นบรรทัดที่เกี่ยวข้องจากไฟล์ application.properties ซึ่ง Spring รู้ตามค่าเริ่มต้น และคำอธิบายประกอบ @Component จะสร้าง Bean ให้เราเมื่อแอปพลิเคชันเริ่มทำงาน ตอนนี้เรามาดูไฟล์คอนฟิกูเรชันของ Spring:
@Configuration
public class AppConfig {
    private final TelegramBotConfig botConfig;

    public AppConfig(TelegramBotConfig botConfig) {
        this.botConfig = botConfig;
    }

    @Bean
    public SetWebhook setWebhookInstance() {
        return SetWebhook.builder().url(botConfig.getWebHookPath()).build();
    }

    @Bean
    public TelegramBot springWebhookBot(SetWebhook setWebhook, TelegramFacade telegramFacade) {
        TelegramBot bot = new TelegramBot(telegramFacade, setWebhook);
        bot.setBotToken(botConfig.getBotToken());
        bot.setBotUsername(botConfig.getUserName());
        bot.setBotPath(botConfig.getWebHookPath());

        return bot;
    }
}
ไม่มีเวทย์มนตร์ที่นี่ เมื่อเริ่มต้น Spring จะสร้างวัตถุ SetWebhook และ TelegramBot ให้เรา ตอนนี้เรามาสร้างจุดเริ่มต้นสำหรับข้อความของเรา:
@RestController
public class WebhookController {

    private final TelegramBot telegramBot;

    public WebhookController(TelegramBot telegramBot) {
        this.telegramBot = telegramBot;
    }

// point for message
    @PostMapping("/")
    public BotApiMethod<!--?--> onUpdateReceived(@RequestBody Update update) {
        return telegramBot.onWebhookUpdateReceived(update);
    }

    @GetMapping
    public ResponseEntity get() {
        return ResponseEntity.ok().build();
    }
}
เซิร์ฟเวอร์ Telegram ส่งข้อความในรูปแบบ JSON ไปยังที่อยู่ webhook ที่ลงทะเบียนไว้โดยใช้วิธี POST ตัวควบคุมของเราจะรับข้อความเหล่านั้นและส่งไปยังไลบรารีโทรเลขในรูปแบบของวัตถุอัปเดต ฉันทำวิธี get แบบนั้น) ตอนนี้เราแค่ต้องใช้ตรรกะบางอย่างสำหรับการประมวลผลข้อความและการตอบกลับใน คลาส TelegramFacadeฉันจะให้โค้ดสั้น ๆ เพื่อให้คุณสามารถเปิดแอปพลิเคชันแล้วไปตามทางของคุณเองหรือเปลี่ยนไปปรับใช้ บน Heroku มันจะเป็นเวอร์ชันเต็ม:
@Component
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TelegramFacade {

    public BotApiMethod<!--?--> handleUpdate(Update update) {

        if (update.hasCallbackQuery()) {
            CallbackQuery callbackQuery = update.getCallbackQuery();
            return null;
        } else {

            Message message = update.getMessage();
            SendMessage sendMessage = new SendMessage();
            sendMessage.setChatId(String.valueOf(message.getChatId()));
            if (message.hasText()) {
                sendMessage.setText("Hello world");
                return sendMessage;
            }
        }
        return null;
    }

}
วิธีนี้จะตอบสนองต่อ Hello world! ในการเปิดตัวแอปพลิเคชันของเรา เราเพียงแค่ต้องแน่ใจว่าเราสามารถทดสอบแอปพลิเคชันของเราได้โดยตรงจาก IDEA ในการดำเนินการนี้ เราจำเป็นต้องดาวน์โหลดยูทิลิตี้ ngrok https://ngrok.com/download ยูทิลิตี้นี้เป็นบรรทัดคำสั่งที่ให้ที่อยู่ชั่วคราวแก่เราเป็นเวลา 2 ชั่วโมงและเปลี่ยนเส้นทางข้อความทั้งหมดไปยังพอร์ตที่ระบุของเซิร์ฟเวอร์ท้องถิ่น เราเปิดตัวและเขียน ngrok http 5000ในบรรทัด(หรือคุณสามารถระบุพอร์ตของคุณได้): บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 5เราได้รับผลลัพธ์: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 6https://23b1a54ccbbd.ngrok.io - นี่คือที่อยู่ webhook ของเรา ดังที่คุณอาจสังเกตเห็นในไฟล์คุณสมบัติที่เราเขียน server.port=5000 เมื่อเริ่มต้นเซิร์ฟเวอร์ Tomcat ไฟล์นั้นจะครอบครองพอร์ต 5000 ตรวจสอบให้แน่ใจว่าฟิลด์เหล่านี้เหมือนกัน อย่าลืมว่าที่อยู่นั้นให้ไว้เป็นเวลาสองชั่วโมง บนบรรทัดคำสั่ง ข้อมูลนี้จะถูกตรวจสอบโดยฟิลด์ Session Expires เมื่อหมดเวลา คุณจะต้องได้รับที่อยู่อีกครั้งและทำตามขั้นตอนการลงทะเบียนทางโทรเลข ตอนนี้เราใช้บรรทัด https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io และด้วยการเคลื่อนไหวของมือที่คล่องแคล่วเราจะแทนที่โทเค็นด้วยของเรา, url ของเรา, วาง บรรทัดผลลัพธ์ลงในเบราว์เซอร์แล้วคลิก Enter คุณควรได้รับผลลัพธ์ดังต่อ บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 7ไปนี้: เพียงเท่านี้ คุณก็สามารถรันแอปพลิเคชันได้แล้ว: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 8ตรวจสอบว่าคลาสของคุณที่มี เมธอด หลักเป็นดังนี้:
@SpringBootApplication
public class TelegramBotApplication {

   public static void main(String[] args) {
      SpringApplication.run(TelegramBotApplication.class, args);
   }
}
หากคุณทำทุกอย่างถูกต้อง ตอน นี้ บอทของคุณจะตอบสนองต่อข้อความที่มีวลี “ สวัสดีชาวโลก” จากนั้นคุณก็ไปตามทางของคุณเองได้ หากคุณอยู่กับฉันและสนใจที่จะทำตามขั้นตอนทั้งหมด เรามาเริ่มเขียนเอนทิตีสำหรับฐานข้อมูลและสร้างฐานข้อมูลกันดีกว่า เริ่มจากฐานข้อมูลกันก่อน ดังที่ฉันได้กล่าวไปแล้ว ฉันคิดว่าคุณมีทักษะขั้นต่ำในการทำงานกับฐานข้อมูลอยู่แล้ว และคุณได้ ติดตั้งฐานข้อมูล postgreSQL ในเครื่องแล้ว หากไม่มี ให้ทำตามเส้นทางนี้ https://www.postgresql.org/download/ ในไฟล์ application.properties ให้แทนที่ข้อมูลเข้าสู่ระบบฐานข้อมูลและรหัสผ่านของคุณเอง ใน IDEA มีแท็บฐานข้อมูลทางด้านขวา คุณต้องคลิกที่+/Data source/ PostgreSQL ด้วยเหตุนี้ เมื่อคุณคลิกที่ทดสอบการเชื่อมต่อคุณควรได้รับผลลัพธ์ที่น่าพอใจ: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 9ตอนนี้คุณสามารถสร้างฐานข้อมูลพร้อมตารางได้โดยตรงจากสภาพแวดล้อมการพัฒนา หรือคุณสามารถใช้ อินเทอร์เฟซเว็บ pgadminซึ่งอยู่ในเมนูเริ่ม เราจะต้องมี 3 ตาราง:
CREATE TABLE users
(
    id               INTEGER PRIMARY KEY UNIQUE NOT NULL,
    name             VARCHAR,
    time_zone        INTEGER DEFAULT 0,
    on_off           BOOLEAN DEFAULT true
);

CREATE TABLE user_events
(
    user_id INTEGER ,
    time timestamp ,
    description varchar ,
    event_id serial,
    event_freq varchar default 'TIME',
    FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
);

CREATE TABLE event_cash
(
    time timestamp ,
    description varchar ,
    user_id INTEGER ,
    id serial
);
ฉันแนะนำให้สร้างสคริปต์นี้แยกกัน เราจะต้องสร้างฐานข้อมูลบน Heroku เพื่อไม่ให้เขียนซ้ำสองครั้ง มาเดินเล่นกันหน่อย ฉันจะบอกทันทีว่าเราต้องการเพียง ตารางevent_cashเพื่อทำงานกับ Heroku เนื่องจากข้อมูลเฉพาะและความปรารถนาอันแรงกล้าของฉันที่จะทำงานกับ คลาส Timeมันจะไม่มีประโยชน์ในเวอร์ชันท้องถิ่น ใน ตาราง ผู้ใช้เราจะบันทึกIDของบัญชีผู้ใช้โทรเลข ชื่อของเขาซึ่งอาจไม่มีอยู่ เขตเวลาของผู้ใช้จะถูกคำนวณสำหรับการส่งการแจ้งเตือนที่ถูกต้อง รวมถึงสถานะเปิด/ปิดของการส่งการแจ้งเตือน เราจะบันทึกID ผู้ใช้ เวลาแจ้งเตือน คำอธิบาย ใน ตาราง user_eventsสร้างIDสำหรับกิจกรรมโดยอัตโนมัติ และตั้งค่าความถี่ของการแจ้งเตือน ตารางevent_cashจะบันทึกการแจ้งเตือนก่อนที่จะส่ง และหากส่งแล้ว ก็จะลบออกจากตาราง ตารางพร้อมแล้ว มาเพิ่มเอนทิตีกันดีกว่า
@Entity
@Table(name = "user_events")
@Getter
@Setter
public class Event {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column( name = "event_id", columnDefinition = "serial")
    private int eventId;

    @Column(name = "time")
    @NotNull(message = "Need date!")
    private Date date;

    @Column(name = "description")
    @Size(min = 4, max = 200, message = "Description must be between 0 and 200 chars!")
    private String description;

    @Column(name = "event_freq", columnDefinition = "TIME")
    @Enumerated(EnumType.STRING)
    private EventFreq freq;

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="user_id")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private User user;

    public Event() {
    }

    public Event(int eventId,
                 @NotNull(message = "Need date!") Date date,
                 @Size(min = 4, max = 200, message = "Description must be between 0 and 200 chars!")
                         String description,
                 EventFreq freq, User user) {
        this.eventId = eventId;
        this.date = date;
        this.description = description;
        this.freq = freq;
        this.user = user;
    }
}
@Entity
@Table(name = "users")
@Getter
@Setter
public class User {

    @Id
    @Column(name = "id")
    private long id;

    @Column(name = "name")
    private String name;

    @Column(name = "time_zone", columnDefinition = "default 0")
    //sets the broadcast time of events for your time zone
    private int timeZone;

    @OneToMany(mappedBy="user")
    private List<event> events;

    @Column(name = "on_off")
    // on/off send event
    private boolean on;

    public User() {
    }
}

</event>
@Entity
@Table(name = "event_cash")
@Getter
@Setter
//serves to save unhandled events after rebooting heroku
public class EventCashEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column( name = "id", columnDefinition = "serial")
    private long id;

    @Column(name = "time")
    private Date date;

    @Column(name = "description")
    private String description;

    @Column(name = "user_id")
    private long userId;

    public EventCashEntity() {
    }

    public static EventCashEntity eventTo(Date date, String description, long userId) {
        EventCashEntity eventCashEntity = new EventCashEntity();
        eventCashEntity.setDate(date);
        eventCashEntity.setDescription(description);
        eventCashEntity.setUserId(userId);
        return eventCashEntity;
    }
}
มาดูประเด็นหลักกันสักหน่อย @Entity – ทำเครื่องหมายคลาสสำหรับ dada jpa ของเราว่าคลาสนี้เป็นเอนทิตีสำหรับฐานข้อมูล เช่น เมื่อดึงข้อมูลจากฐานข้อมูล มันจะถูกนำเสนอแก่เราในรูปแบบของออบเจ็กต์เหตุการณ์ ผู้ใช้ และ EventCashEntity @Table – เราพูดชื่อตารางของเราในฐานข้อมูล เพื่อให้แน่ใจว่าชื่อตารางไม่ได้ขีดเส้นใต้ด้วยสีแดง เราจำเป็นต้องยอมรับตัวเลือกการแก้ไขข้อผิดพลาดที่เสนอใน IDEA แล้วคลิกกำหนดแหล่งข้อมูล และเลือกฐานของเราที่นั่น @id และ @GeneratedValue - ใช้โดย Spring เพื่อสร้างฐานข้อมูลหากไม่มีอยู่ @Columnใช้เพื่อระบุชื่อของเขตข้อมูลในตารางหากไม่ตรงกัน แต่กฎของโค้ดที่ดีขอแนะนำให้คุณเขียนสิ่งนี้เสมอ ทัศนคติของ OneToMany - ฉันขอแนะนำให้ใช้เวลาและค้นหาว่ามันคืออะไรที่นี่ https://en.wikibooks.org/wiki/Java_Persistence ฉันไม่สามารถอธิบายให้ชัดเจนกว่านี้ได้ แค่เชื่อฉัน ฉันขอบอกว่าในกรณีนี้ คำอธิบายประกอบ @OneToManyบอกว่าผู้ใช้หนึ่งคนสามารถมีกิจกรรมได้มากมาย และพวกเขาจะจัดเตรียมไว้ให้เราในรูปแบบของรายการ ตอนนี้เราจำเป็นต้องได้รับข้อมูลจากตาราง ใน ไลบรารี SRING DATA JPAทุกอย่างถูกเขียนสำหรับเราแล้ว เราเพียงแค่ต้องสร้างอินเทอร์เฟซสำหรับแต่ละตารางและขยายจาก JpaRepository
public interface EventRepository extends JpaRepository<event, long=""> {
    Event findByEventId(long id);
}
public interface UserRepository extends JpaRepository<user, long=""> {

    User findById(long id);
}
public interface EventCashRepository extends JpaRepository<eventcashentity, long=""> {
    EventCashEntity findById(long id);
}

</eventcashentity,></user,></event,>
ตรรกะหลักสำหรับการทำงานกับฐานข้อมูลจะถูกถ่ายโอนไปยังบริการที่เรียกว่าData Access Object (DAO):
@Service
public class UserDAO {

    private final UserRepository userRepository;

    @Autowired
    public UserDAO(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User findByUserId(long id) {
        return userRepository.findById(id);
    }

    public List<user> findAllUsers() {
        return userRepository.findAll();
    }

    public void removeUser(User user) {
        userRepository.delete(user);
    }


    public void save(User user) {
        userRepository.save(user);
    }

    public boolean isExist(long id) {
        User user = findByUserId(id);
        return user != null;
    }
}
@Service
public class EventDAO {

    private final UserRepository userRepository;
    private final EventRepository eventRepository;

    @Autowired
    public EventDAO(UserRepository userRepository, EventRepository eventRepository) {
        this.userRepository = userRepository;
        this.eventRepository = eventRepository;
    }

    public List<event> findByUserId(long userId) {
        User user = userRepository.findById(userId);
        return user.getEvents();
    }
    public List<event> findAllEvent() {
       return eventRepository.findAll();
    }

    public Event findByEventId(long eventId) {
        return eventRepository.findByEventId(eventId);
    }

    public void remove(Event event) {
        eventRepository.delete(event);
    }

    public void save(Event event) {
        eventRepository.save(event);
    }
}

</event></event></user>
@Service
//handles events not dispatched after reboot heroku
public class EventCashDAO {

    private EventCashRepository eventCashRepository;

    @Autowired
    public void setEventCashRepository(EventCashRepository eventCashRepository) {
        this.eventCashRepository = eventCashRepository;
    }

    public List<eventcashentity> findAllEventCash() {
        return eventCashRepository.findAll();
    }

    public void save(EventCashEntity eventCashEntity) {
        eventCashRepository.save(eventCashEntity);
    }

    public void delete(long id) {
        eventCashRepository.deleteById(id);
    }
}

</eventcashentity>
ในกรณีนี้ เราไม่มีการประมวลผลข้อมูล เราเพียงแค่ดึงข้อมูลจากตารางเท่านั้น เราทุกคนพร้อมที่จะจัดเตรียมโค้ดที่สมบูรณ์ของคลาส T elegramFacadeและเริ่มวิเคราะห์ตรรกะ
@Component
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TelegramFacade {

    final MessageHandler messageHandler;
    final CallbackQueryHandler callbackQueryHandler;
    final BotStateCash botStateCash;

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


    public TelegramFacade(MessageHandler messageHandler, CallbackQueryHandler callbackQueryHandler, BotStateCash botStateCash) {
        this.messageHandler = messageHandler;
        this.callbackQueryHandler = callbackQueryHandler;
        this.botStateCash = botStateCash;
    }

    public BotApiMethod<!--?--> handleUpdate(Update update) {

        if (update.hasCallbackQuery()) {
            CallbackQuery callbackQuery = update.getCallbackQuery();
            return callbackQueryHandler.processCallbackQuery(callbackQuery);
        } else {

            Message message = update.getMessage();
            if (message != null && message.hasText()) {
                return handleInputMessage(message);
            }
        }
        return null;
    }

    private BotApiMethod<!--?--> handleInputMessage(Message message) {
        BotState botState;
        String inputMsg = message.getText();
        //we process messages of the main menu and any other messages
        //set state
        switch (inputMsg) {
            case "/start":
                botState = BotState.START;
                break;
            case "Мои напоминания":
                botState = BotState.MYEVENTS;
                break;
            case "Создать напоминание":
                botState = BotState.CREATE;
                break;
            case "Отключить напоминания":
            case "Включить напоминания":
                botState = BotState.ONEVENT;
                break;
            case "All users":
                if (message.getFrom().getId() == adminId)
                botState = BotState.ALLUSERS;
                else botState = BotState.START;
                break;
            case "All events":
                if (message.getFrom().getId() == adminId)
                botState = BotState.ALLEVENTS;
                else botState = BotState.START;
                break;
            default:
                botState = botStateCash.getBotStateMap().get(message.getFrom().getId()) == null?
                        BotState.START: botStateCash.getBotStateMap().get(message.getFrom().getId());
        }
        //we pass the corresponding state to the handler
        //the corresponding method will be called
        return messageHandler.handle(message, botState);

    }
}
มาดูกันว่าฟิลด์ใดที่จำเป็นสำหรับ
final MessageHandler messageHandler;
    final CallbackQueryHandler callbackQueryHandler;
    final BotStateCash botStateCash;
หากเราทุกคนเขียนโค้ดในคลาสเดียว เราก็จะลงเอยด้วยผ้าเช็ดเท้าไปดวงจันทร์ ดังนั้นเราจึงกำหนดตรรกะสำหรับการทำงานกับข้อความตัวอักษรให้กับคลาส MessageHandler และกำหนดตรรกะสำหรับการทำงานกับข้อความ callbackquery ให้กับคลาสCallbackQueryHandler ถึงเวลาที่จะรู้ว่าallbackquery คืออะไร และมีเมนูประเภทใดบ้าง ในการดำเนินการนี้ ฉันจะให้รูปภาพอินเทอร์เฟซของบอทอีกรูปแก่คุณ: บอทโทรเลข - เตือนความจำผ่าน webHook ใน Java หรือปฏิเสธปฏิทิน Google!  - 10มีเมนูสองประเภท สิ่งที่แนบมาที่ด้านล่างของหน้าต่าง - เมนูหลักและสิ่งที่แนบมากับข้อความเช่นปุ่มสำหรับลบแก้ไขเปลี่ยนสายพาน เมื่อคุณคลิกที่ปุ่มเมนูหลัก ข้อความที่มีชื่อเดียวกันจะถูกส่งไป ตัวอย่างเช่น เมื่อคุณคลิก"การเตือนความจำของฉัน"ข้อความ"การแจ้งเตือนของฉัน"จะถูกส่งไป และเมื่อติดตั้งคีย์บอร์ด callbackquery ค่าเฉพาะจะถูกตั้งค่าสำหรับแต่ละปุ่ม และค่าของมันจะถูกส่งโดยไม่แสดงบนหน้าจอ ต่อไปเราจะมีฟิลด์BotStateCash นี่คือคลาสที่สร้างขึ้นเป็นพิเศษที่จะตรวจสอบสถานะของบอท และความสนใจ นี่เป็นองค์ประกอบที่ซับซ้อน คุณต้องเครียด เกินจำนวนอักขระซึ่งไม่ได้เขียนไว้ที่ใดเลย)) นี่คือลิงค์ไปยังส่วนที่สอง
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION