JavaRush /בלוג Java /Random-HE /בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנ...
Vladimir Popov
רָמָה

בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל! חלק 1

פורסם בקבוצה
שמי ולדימיר. אני בן 43. ואם אתה, הקורא, מעל גיל 40, אז כן, אחרי גיל 40 אתה יכול להפוך למתכנת אם אתה אוהב את זה. העבודה שלי לא קשורה לתכנות בכלל, אני מנהלת פרויקטים בתחום האוטומציה וכל זה. אבל אני מתכנן לשנות את עיסוקי. הו, הטרנדים החדשים האלה... משנים את תחום הפעילות שלך כל 5-7 שנים. אז : הפרויקט התברר כגדול למדי, כך שחלק מהנקודות יצטרכו להישמט או לדבר עליהן בקצרה, בתקווה שהקורא יידע לעשות גוגל. האינטרנט מלא בפרסומים של בוטים של טלגרם הפועלים על העיקרון של סקר ארוך. ויש מעט מאוד שעובדים על עיקרון ה-Webhook. מה זה? סקר ארוך - זה אומר שהאפליקציה שלך עצמה תסקר את שרת הטלגרם עבור הודעות בתדירות מסוימת, לאט. Webhook - פירושו ששרת הטלגרם יפנה באופן מיידי הודעות לשרת שתציין. במקרה שלנו, באדיבות שירות הרוקו. אפשר כמובן לקרוא עוד על כל זה ועל הבוט בכלל באתר טלגרם - https://tlgrm.ru/docs/bots/api ממשק הבוט נראה כך: בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל!  - 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 או אמור לא ללוח השנה של גוגל!  - 2 בואו נתחיל ביצירת פרויקט ב- https://start.spring.io בחר את התלות שאנו צריכים כפי שמוצג באיור: בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל!  - 3בחר משלנו שם עבור הפרויקט ולחץ על צור . לאחר מכן תתבקש לשמור את הפרויקט בדיסק שלך. כל מה שנותר הוא לפתוח את הקובץ pom.xm l מסביבת הפיתוח שלך. לפניכם פרויקט גמור. עכשיו אנחנו רק צריכים להוסיף את הספרייה הראשית שלנו. השתמשתי בספרייה מ- https://github.com/rubenlagus/TelegramBots באופן כללי, אתה יכול להתבלבל ולהסתדר בלעדיה. הרי כל מטרת העבודה היא לשרשר כתובת URL כזו: https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658bgrok.io בוא תסתכל קצת על זה. : https://api.telegram.org – שרת טלגרם. bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/ - אחרי המילה bot הוא אסימון סודי שאתה מקבל בעת רישום בוט. setWebhook?url=https://e9c658b548aa.ngrok.io – שם השיטה והפרמטרים שלה. במקרה זה, אנו מתקינים את שרת ה-webhook שלך, כל ההודעות יישלחו אליו. באופן כללי, החלטתי שהפרויקט לא קטן מדי לפרסום, אבל עם יישום ידני הוא יהיה בדרך כלל בלתי קריא. אז, המראה הסופי של קובץ הפום הוא:
<!--?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 מנותח כאובייקט Update ומחזיר את מה ששרת הטלגרם רוצה "לשמוע" מאיתנו. כאן יש לנו הערות מספריית Lombok . Lombok – מקל על חייו של מתכנת!! ובכן, כלומר. אנחנו לא צריכים להגדיר מחדש מגפרים ומגדירים, Lombok עושה זאת עבורנו, ואנחנו גם לא צריכים לכתוב מזהה רמת גישה. כבר לא כדאי לכתוב שזה נעשה על ידי ההערות @Getter, @Setter, @FieldDefaults השדה botPath פירושו כתובת ה-webhook שלנו, אותה נקבל ב-Heroku מאוחר יותר. השדה botUsername פירושו השם של הבוט שלנו, אותו נקבל בעת רישום הבוט שלנו בטלגרם. שדה botToken הוא הטוקן שלנו, אותו נקבל בעת רישום הבוט שלנו בטלגרם. שדה telegramFacade הוא הכיתה שלנו בה יתבצע עיבוד הודעות, נחזור אליו מעט מאוחר יותר, שיהיה אדום לעת עתה. עכשיו הגיע הזמן שניצור קשר עם @BotFather ולקבל את ה-botToken וה-botUsername הנחשקים. בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל!  - 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 ישירות באפליקציה. בואו ניצור שעועית או כיתת עטיפה מהנתונים האלה.
@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();
    }
}
שרת הטלגרם שולח הודעות בפורמט JSON לכתובת ה-webhook הרשומה בשיטת POST, הבקר שלנו מקבל אותן ומשדר אותן לספריית הטלגרם בצורה של אובייקט Update. עשיתי את שיטת 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;
    }

}
שיטה זו תגיב לכל שלום עולם! כדי להפעיל את האפליקציה שלנו, עלינו לוודא שנוכל לבדוק את האפליקציה שלנו ישירות מ-IDEA. לשם כך עלינו להוריד את כלי השירות ngrok. https://ngrok.com/download כלי זה הוא שורת פקודה שנותנת לנו כתובת זמנית למשך שעתיים ומפנה את כל ההודעות ליציאה המצוינת של השרת המקומי. אנו משיקים וכותבים ngrok http 5000 בשורה (או שאתה יכול לציין את היציאה שלך): בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל!  - 5אנו מקבלים את התוצאה: בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל!  - 6https://23b1a54ccbbd.ngrok.io - זוהי כתובת ה-webhook שלנו. כפי שאולי שמתם לב בקובץ המאפיינים שכתבנו server.port=5000 בעת הפעלת שרת ה-tomcat, הוא יתפוס את פורט 5000, ודא ששדות אלו זהים. כמו כן, אל תשכח שהכתובת ניתנת לשעתיים. בשורת הפקודה, זה מפוקח על ידי השדה פג פג. כאשר הזמן יגמר, תצטרך לקבל את הכתובת שוב ולעבור את הליך הרישום שלה בטלגרם. עכשיו אנחנו לוקחים את הקו https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io ובתנועות יד מיומנות אנחנו מחליפים את ה-, the pasture שלנו, the pasture את השורה המתקבלת לתוך הדפדפן ולחץ על Enter. אתה אמור לקבל את התוצאה הבאה: בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל!  - 7זהו, עכשיו אתה יכול להפעיל את האפליקציה: בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל!  - 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 . כתוצאה מכך, כאשר אתה לוחץ על Test Connection אתה אמור לקבל תוצאה משביעת רצון: בוט טלגרם - תזכורת דרך webHook ב-Java או אמור לא ללוח השנה של גוגל!  - 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 ; זה לא יהיה שימושי בגרסה המקומית. בטבלת המשתמשים נרשום את מזהה החשבון של משתמש הטלגרם, את שמו, שאולי לא קיים, אזור הזמן של המשתמש יחושב לשליחת התראות נכונה וכן את מצב ההפעלה/כיבוי של שליחת ההתראות. אנו נרשום את מזהה המשתמש, זמן ההתראה, התיאור בטבלת user_events , ניצור מזהה אוטומטית לאירוע, ונקבע את תדירות ההתראות. טבלת 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 שלנו שמחלקה זו היא ישות עבור מסד הנתונים, כלומר. בעת שליפת נתונים ממסד הנתונים, הם יוצגו לנו בצורה של אובייקט Event, User ו-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 או אמור לא ללוח השנה של גוגל!  - 10ישנם שני סוגים של תפריטים. אלה שמצורפים לתחתית החלון - התפריט הראשי, וכאלה שמוקצים להודעה, למשל, כפתורי המחיקה, העריכה, החלפת חגורה. כאשר אתה לוחץ על כפתור התפריט הראשי, נשלחת הודעה באותו שם, לדוגמה, כאשר אתה לוחץ על "התזכורות שלי" , הטקסט "התזכורות שלי" פשוט יישלח . ובעת התקנת מקלדת ה-callbackquery, נקבע ערך ספציפי לכל כפתור והערך שלו יישלח מבלי להציגו על המסך. לאחר מכן יש לנו את השדה BotStateCash . זהו מחלקה שנוצרה במיוחד שתפקח על מצב הבוט, ותשומת לב, זהו אלמנט מורכב, אתה צריך להתאמץ. חרג ממספר התווים, אשר, אגב, לא כתוב בשום מקום)). אז הנה הקישור לחלק השני
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION