JavaRush /Blog Java /Random-VI /Telegram bot - nhắc nhở qua webHook trong Java hoặc nói k...
Vladimir Popov
Mức độ

Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google! Phần 1

Xuất bản trong nhóm
Tên tôi là Vladimir. Tôi 43 tuổi. Và nếu bạn, độc giả, trên 40 tuổi, thì vâng, sau 40 tuổi bạn có thể trở thành lập trình viên nếu thích. Công việc của tôi không liên quan gì đến lập trình cả, tôi là người quản lý dự án trong lĩnh vực tự động hóa và tất cả những thứ đó. Nhưng tôi đang có ý định thay đổi nghề nghiệp. Ồ, những xu hướng mới này... thay đổi lĩnh vực hoạt động của bạn cứ sau 5 - 7 năm. Vì vậy : Dự án hóa ra khá lớn nên một số điểm sẽ phải lược bỏ hoặc nói sơ qua, mong người đọc biết cách Google. Internet có đầy đủ các ấn phẩm về các bot điện tín hoạt động theo nguyên tắc Bỏ phiếu dài. Và có rất ít hoạt động theo nguyên tắc Webhook. Nó là gì? Bỏ phiếu dài - điều này có nghĩa là chính ứng dụng của bạn sẽ thăm dò máy chủ telegram để tìm các tin nhắn ở một tần số nhất định, một cách chậm rãi. Webhook - có nghĩa là máy chủ telegram sẽ ngay lập tức chuyển hướng tin nhắn đến máy chủ mà bạn chỉ định. Trong trường hợp của chúng tôi, nhờ dịch vụ Heroku. Tất nhiên, bạn có thể đọc thêm về tất cả những điều này và về bot nói chung trên trang web Telegram - https://tlgrm.ru/docs/bots/api Giao diện bot trông như thế này: Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - 1 Tôi coi ứng dụng này chính xác là một khóa đào tạo project vì khi viết tôi học được nhiều thông tin từ bot này hơn là khi đào tạo. Bạn có muốn học lập trình không? Bắt đầu viết mã!!! Nhưng! Sẽ không có hướng dẫn chi tiết về cách tải ứng dụng lên github hoặc cách tạo cơ sở dữ liệu. Có rất nhiều điều này trên Internet và nó được mô tả rất chi tiết; hơn nữa, nó sẽ rất dài để đọc. Ứng dụng sẽ hoạt động như sau: Nhập mô tả sự kiện, nhập ngày giờ diễn ra sự kiện, chọn tần suất (bạn có thể thực hiện một lần, bạn có thể có lời nhắc mỗi ngày vào một thời điểm nhất định, bạn có thể có một lần một tháng vào một thời điểm nhất định hoặc mỗi năm một lần). Các biến thể của thông báo có thể được thêm vào vô tận, tôi có rất nhiều ý tưởng. Tiếp theo, dữ liệu đã nhập sẽ được lưu vào cơ sở dữ liệu (cũng được triển khai miễn phí trên Heroku, 10.000 hàng miễn phí) Sau đó, một lần vào đầu ngày lúc 0:00 giờ máy chủ, Spring lấy từ cơ sở dữ liệu tất cả các sự kiện dựa trên tiêu chí sẽ kích hoạt vào ngày hôm đó và gửi chúng đi thực thi vào thời gian đã chỉ định. CHÚ Ý!!! PHẦN NÀY CỦA CHƯƠNG TRÌNH LÀ THỬ NGHIỆM! CÓ MỘT PHƯƠNG PHÁP THỰC HIỆN ĐƠN GIẢN VÀ ĐÚNG HƠN! ĐIỀU NÀY ĐƯỢC LÀM CỤ THỂ ĐỂ XEM LỚP THỜI GIAN HOẠT ĐỘNG NHƯ THẾ NÀO! Bạn có thể tự tay chạm vào con bot đang hoạt động bằng cách nhập @calendar_event_bot vào giỏ hàng, nhưng đừng tin vào điều đó vì tôi vẫn đang giễu cợt nó. code - https://github.com/papoff8295/webHookBotForHabr Về cơ bản, để khởi chạy dự án của riêng mình, bạn cần thực hiện các bước sau: • Đăng ký với @BotFather , không khó, nhận token và tên • Fork dự án trên github • Đăng ký trên Heroku, tạo một ứng dụng (chúng ta sẽ thực hiện từng bước một), triển khai từ kho lưu trữ của bạn. • Tạo cơ sở dữ liệu trên Heroku • Thay thế các trường tương ứng trong kho bằng trường của riêng bạn (mã thông báo, tên bảng trong thực thể, webHookPath, tên người dùng, mật khẩu và đường dẫn đến cơ sở dữ liệu, tất cả sẽ được phân tích cú pháp) • Giúp Heroku hoạt động 24/24/ 7 sử dụng https:// /uptimerobot.com/ Cấu trúc cuối cùng của dự án như sau: Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - 2 Hãy bắt đầu bằng cách tạo một dự án trong https://start.spring.io Chọn các phần phụ thuộc mà chúng ta cần như trong hình: Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - 3Chọn của riêng chúng ta tên cho dự án và nhấp vào Tạo . Sau đó, bạn sẽ được nhắc lưu dự án vào đĩa của mình. Tất cả những gì còn lại là mở tệp pom.xm l từ môi trường phát triển của bạn. Có một dự án đã hoàn thành trước mắt bạn. Bây giờ chúng ta chỉ cần thêm thư viện chính của mình. Tôi đã sử dụng thư viện từ https://github.com/rubenlagus/TelegramBots Nói chung, bạn có thể bị nhầm lẫn và làm việc mà không có nó. Suy cho cùng, mục đích chung của công việc là nối một URL như thế này: https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io Hãy xem xét nó một chút : https://api.telegram.org – máy chủ điện tín. bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/ - sau chữ bot là token bí mật mà bạn nhận được khi đăng ký bot. setWebhook?url=https://e9c658b548aa.ngrok.io – tên của phương thức và các tham số của nó. Trong trường hợp này, chúng tôi cài đặt máy chủ webhook của bạn, tất cả tin nhắn sẽ được gửi đến nó. Nói chung, tôi quyết định rằng dự án không quá nhỏ để xuất bản, nhưng nếu triển khai thủ công thì nhìn chung sẽ không thể đọc được. Vì vậy, giao diện cuối cùng của tệp pom là:
<!--?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>
Mọi thứ đã sẵn sàng để viết bot của chúng tôi. Hãy tạo lớp TelegramBot . Tôi sẽ không viết tên các thư mục, bạn có thể xem chúng trong cấu trúc dự án ở trên.
@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);
    }
}
Lớp này mở rộng SpringWebhookBot từ thư viện telegram của chúng tôi và chúng tôi chỉ cần triển khai một phương thức, onWebhookUpdateReceived . Nó chấp nhận JSON được phân tích cú pháp dưới dạng đối tượng Cập nhật và trả về những gì máy chủ điện tín muốn “nghe” từ chúng tôi. Ở đây chúng tôi có chú thích từ thư viện Lombok . Lombok – giúp cuộc sống của lập trình viên dễ dàng hơn!! Vâng, đó là. chúng tôi không cần xác định lại getters và setters, Lombok thực hiện việc này cho chúng tôi và chúng tôi cũng không cần viết mã định danh cấp truy cập. Không còn đáng để viết rằng việc này được thực hiện bởi các chú thích @Getter, @Setter, @FieldDefaults Trường botPath có nghĩa là địa chỉ webhook của chúng tôi mà chúng tôi sẽ nhận được trên Heroku sau này. Trường botUsername có nghĩa là tên bot của chúng tôi mà chúng tôi sẽ nhận được khi đăng ký bot của mình trên Telegram. Trường botToken là mã thông báo của chúng tôi mà chúng tôi sẽ nhận được khi đăng ký bot của mình trên Telegram. Trường telegramFacade là lớp của chúng ta, nơi quá trình xử lý tin nhắn sẽ diễn ra, chúng ta sẽ quay lại nó sau, tạm thời hãy để nó có màu đỏ. Bây giờ là lúc chúng ta liên hệ với @BotFather và nhận được botToken và botUsername đáng mơ ước. Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - 4Chỉ cần viết thư cho anh ấy qua điện tín và anh ấy sẽ kể cho bạn mọi chuyện. Chúng tôi ghi dữ liệu vào application.properties của mình, cuối cùng nó sẽ trông như thế này:
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
Cấu hình này được cấu hình để hoạt động với cơ sở dữ liệu cục bộ; sau này chúng tôi sẽ thực hiện những thay đổi cần thiết. Thay thế botToken và tên người dùng bằng tên của riêng bạn. Sẽ không tốt nếu sử dụng dữ liệu từ application.properties trực tiếp trong ứng dụng. Hãy tạo một lớp đậu hoặc một lớp bao bọc từ dữ liệu này.
@Component
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)

public class TelegramBotConfig {
    @Value("${telegrambot.webHookPath}")
    String webHookPath;
    @Value("${telegrambot.userName}")
    String userName;
    @Value("${telegrambot.botToken}")
    String botToken;
Ở đây, chú thích @Value khởi tạo các dòng tương ứng từ tệp application.properties mà Spring biết theo mặc định. Và chú thích @Component sẽ tạo Bean cho chúng ta khi ứng dụng khởi động. Bây giờ chúng ta hãy xem tệp cấu hình 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;
    }
}
Không có phép thuật nào ở đây; khi khởi động, Spring tạo các đối tượng SetWebhook và TelegramBot cho chúng ta. Bây giờ hãy tạo điểm vào cho tin nhắn của chúng ta:
@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();
    }
}
Máy chủ Telegram gửi tin nhắn ở định dạng JSON đến địa chỉ webhook đã đăng ký bằng phương thức POST, bộ điều khiển của chúng tôi nhận chúng và truyền chúng đến thư viện telegram dưới dạng đối tượng Cập nhật. Mình đã làm phương thức get như vậy) Bây giờ chúng ta chỉ cần triển khai một số logic để xử lý tin nhắn và phản hồi trong lớp TelegramFacade , mình sẽ đưa ra đoạn code ngắn của nó để các bạn có thể khởi chạy ứng dụng rồi đi theo cách riêng của mình hoặc chuyển sang triển khai trên Heroku thì nó sẽ là phiên bản đầy đủ:
@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;
    }

}
Phương pháp này sẽ phản hồi bất kỳ Hello world! Để khởi chạy ứng dụng của mình, chúng tôi chỉ cần đảm bảo rằng chúng tôi có thể kiểm tra ứng dụng của mình trực tiếp từ IDEA. Để làm được điều này, chúng ta cần tải tiện ích ngrok. https://ngrok.com/download Tiện ích này là một dòng lệnh cung cấp cho chúng ta địa chỉ tạm thời trong 2 giờ và chuyển hướng tất cả các tin nhắn đến cổng được chỉ định của máy chủ cục bộ. Chúng tôi khởi chạy và viết ngrok http 5000 vào dòng (hoặc bạn có thể chỉ định cổng của mình): Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - 5Chúng tôi nhận được kết quả: Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - 6https://23b1a54ccbbd.ngrok.io - đây là địa chỉ webhook của chúng tôi. Như bạn có thể nhận thấy trong tệp thuộc tính mà chúng tôi đã viết server.port=5000 khi khởi động máy chủ Tomcat, nó sẽ chiếm cổng 5000, hãy đảm bảo rằng các trường này giống nhau. Ngoài ra, đừng quên rằng địa chỉ được đưa ra trong hai giờ. Trên dòng lệnh, điều này được giám sát bởi trường Phiên hết hạn. Khi hết thời gian, bạn sẽ cần lấy lại địa chỉ và làm thủ tục đăng ký trên điện tín. Bây giờ chúng ta lấy dòng https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io Và bằng những chuyển động khéo léo của bàn tay, chúng ta thay thế mã thông báo bằng mã của chúng tôi, url bằng mã của chúng tôi, dán dòng kết quả vào trình duyệt và nhấp enter. Bạn sẽ nhận được kết quả như sau: Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - 7Vậy là xong, bây giờ bạn có thể chạy ứng dụng: Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - số 8Kiểm tra xem lớp của bạn với phương thức main có như thế này không:
@SpringBootApplication
public class TelegramBotApplication {

   public static void main(String[] args) {
      SpringApplication.run(TelegramBotApplication.class, args);
   }
}
Nếu bạn đã làm mọi thứ chính xác, bây giờ bot của bạn sẽ trả lời bất kỳ tin nhắn nào có cụm từ “ Xin chào thế giới” . Sau đó bạn có thể đi theo cách riêng của bạn. Nếu bạn đồng ý với tôi và muốn thực hiện tất cả các bước thì hãy bắt đầu viết các thực thể cho cơ sở dữ liệu và tự tạo cơ sở dữ liệu. Hãy bắt đầu với cơ sở dữ liệu: Như tôi đã nói, tôi giả sử rằng bạn đã có những kỹ năng tối thiểu khi làm việc với cơ sở dữ liệu và bạn đã cài đặt cơ sở dữ liệu postgreSQL cục bộ , nếu không, hãy đi theo con đường này. https://www.postgresql.org/download/ Trong tệp application.properties, thay thế thông tin đăng nhập và mật khẩu cơ sở dữ liệu bằng mật khẩu của riêng bạn. Trong IDEA có một tab cơ sở dữ liệu ở bên phải, trong đó bạn cần nhấp vào +/Data source/PostgreSQL . Do đó, khi nhấp vào Kiểm tra kết nối, bạn sẽ nhận được kết quả khả quan: Telegram bot - nhắc nhở qua webHook trong Java hoặc nói không với lịch Google!  - 9Bây giờ bạn có thể tạo cơ sở dữ liệu với các bảng trực tiếp từ môi trường phát triển hoặc bạn có thể sử dụng giao diện web pgadmin , nằm trong menu bắt đầu. Chúng ta sẽ cần 3 bảng:
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
);
Tôi khuyên bạn nên tạo tập lệnh này một cách riêng biệt; chúng ta sẽ cần nó để tạo cơ sở dữ liệu trên Heroku, để không phải viết nó hai lần. Chúng ta hãy đi bộ một chút. Tôi sẽ nói ngay rằng chúng ta chỉ cần bảng event_cash để làm việc với Heroku do tính chất cụ thể của nó và mong muốn vô độ của tôi là được làm việc với lớp Time ; nó sẽ không hữu ích trong phiên bản cục bộ. Trong bảng người dùng , chúng tôi sẽ ghi lại id tài khoản của người dùng telegram, tên của anh ấy, có thể không tồn tại, múi giờ của người dùng sẽ được tính toán để gửi thông báo chính xác, cũng như trạng thái bật/tắt của việc gửi thông báo. Chúng tôi sẽ ghi lại id người dùng, thời gian thông báo, mô tả trong bảng user_events , tự động tạo id cho sự kiện và đặt tần suất thông báo. Bảng event_cash sẽ ghi lại thông báo trước khi nó được gửi và nếu được gửi sẽ xóa nó khỏi bảng. Các bảng đã sẵn sàng, bây giờ hãy thêm các thực thể.
@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;
    }
}
Chúng ta hãy điểm qua những điểm chính một chút. @Entity - đánh dấu lớp cho dada jpa của chúng tôi rằng lớp này là một thực thể cho cơ sở dữ liệu, tức là. khi lấy dữ liệu từ cơ sở dữ liệu, nó sẽ được hiển thị cho chúng ta dưới dạng đối tượng Event, User và EventCashEntity. @Table - chúng tôi nói tên bảng của chúng tôi trong cơ sở dữ liệu. Để đảm bảo tên bảng không bị gạch chân màu đỏ, chúng ta cần phải đồng ý trong IDEA với tùy chọn sửa lỗi được đề xuất và nhấp vào Gán nguồn dữ liệu. Và chọn căn cứ của chúng tôi ở đó. @id và @GeneratedValue - được Spring sử dụng để tạo cơ sở dữ liệu nếu nó chưa tồn tại. @Column được sử dụng để chỉ ra tên của các trường trong bảng nếu chúng không khớp nhau, nhưng các quy tắc về mã tốt khuyên bạn nên luôn viết điều này. Thái độ của OneToMany - Tôi khuyên bạn nên dành thời gian và tìm hiểu xem nó ở đây là gì https://en.wikibooks.org/wiki/Java_Persistence Tôi không thể giải thích rõ ràng hơn, hãy tin tôi đi. Hãy để tôi nói rằng trong trường hợp này, chú thích @OneToMany nói rằng một người dùng có thể có nhiều sự kiện và chúng sẽ được cung cấp cho chúng tôi dưới dạng danh sách. Bây giờ chúng ta cần lấy dữ liệu từ các bảng. Trong thư viện SRING DATA JPA mọi thứ đã được viết sẵn cho chúng ta, chúng ta chỉ cần tạo giao diện cho mỗi bảng và mở rộng nó từ 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,>
Logic chính để làm việc với cơ sở dữ liệu được chuyển sang một dịch vụ, được gọi là Đối tượng truy cập dữ liệu (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>
Trong trường hợp này, chúng tôi không xử lý dữ liệu nào, chúng tôi chỉ lấy dữ liệu từ các bảng. Tất cả chúng tôi đều sẵn sàng cung cấp mã hoàn chỉnh của lớp T elegramFacade và bắt đầu phân tích logic.
@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);

    }
}
Hãy xem những trường nào là cần thiết cho
final MessageHandler messageHandler;
    final CallbackQueryHandler callbackQueryHandler;
    final BotStateCash botStateCash;
Nếu tất cả chúng ta đều viết mã trong một lớp thì cuối cùng chúng ta sẽ gặp khó khăn; do đó, chúng ta gán logic để làm việc với tin nhắn văn bản cho lớp MessageHandler và logic để làm việc với các tin nhắn truy vấn ngược cho lớp CallbackQueryHandler . Đã đến lúc tìm hiểu allbackquery là gì và có những loại menu nào. Để làm điều này, tôi sẽ cung cấp cho bạn một hình ảnh khác về giao diện của bot: Telegram bot — напоминалка через webHook на Java or скажи нет Google-календарю! - 10Có hai loại menu. Những cái được gắn ở dưới cùng của cửa sổ - menu chính và những cái được gán cho tin nhắn, chẳng hạn như nút xóa, chỉnh sửa, thay đổi nút thắt lưng. Khi bạn nhấp vào nút menu chính, một tin nhắn cùng tên sẽ được gửi, chẳng hạn như khi bạn nhấp vào “Lời nhắc của tôi” , văn bản “Lời nhắc của tôi” sẽ chỉ được gửi . Và khi cài đặt bàn phím callbackquery, một giá trị cụ thể được đặt cho mỗi nút và giá trị của nó sẽ được gửi mà không hiển thị trên màn hình. Tiếp theo chúng ta có trường BotStateCash . Đây là một lớp được tạo đặc biệt để theo dõi trạng thái của bot và chú ý, đây là một yếu tố phức tạp, bạn cần phải căng thẳng. Nhân tiện, số lượng ký tự đã bị vượt quá, nhân tiện, không được viết ở đâu cả)). Vì vậy đây là liên kết đến phần hai
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION