JavaRush /Java-Blog /Random-DE /Telegram-Bot – Erinnerung per WebHook in Java oder Nein z...
Vladimir Popov
Level 41

Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender! Teil 1

Veröffentlicht in der Gruppe Random-DE
Mein Name ist Wladimir. Ich bin 43 Jahre alt. Und wenn Sie, lieber Leser, über 40 sind, dann ja, nach 40 können Sie Programmierer werden, wenn Sie möchten. Meine Arbeit hat überhaupt nichts mit Programmieren zu tun, ich bin Projektmanager im Bereich Automatisierung und so. Aber ich habe vor, meinen Beruf zu wechseln. Oh, diese neuen Trends... verändern Ihr Tätigkeitsfeld alle 5-7 Jahre. Also : Das Projekt ist ziemlich umfangreich geworden, daher müssen einige Punkte weggelassen oder kurz angesprochen werden, in der Hoffnung, dass der Leser weiß, wie man googelt. Das Internet ist voll von Veröffentlichungen von Telegram-Bots, die nach dem Long-Polling-Prinzip arbeiten. Und es gibt nur sehr wenige, die nach dem Webhook-Prinzip funktionieren. Was ist das? Lange Abfrage – das bedeutet, dass Ihre Anwendung selbst den Telegrammserver in einer bestimmten Häufigkeit und langsam nach Nachrichten abfragt. Webhook – bedeutet, dass der Telegram-Server Nachrichten sofort an den von Ihnen angegebenen Server umleitet. In unserem Fall mit freundlicher Genehmigung des Heroku-Dienstes. Mehr darüber und über den Bot im Allgemeinen können Sie natürlich auf der Telegram-Website lesen – https://tlgrm.ru/docs/bots/api. Die Bot-Schnittstelle sieht so aus: Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 1 Ich betrachte diese Anwendung genau als Training Projekt aus dem Grund, dass ich beim Schreiben mehr Informationen von diesem Bot gelernt habe als beim Training. Möchten Sie Programmieren lernen? Fangen Sie an, Code zu schreiben!!! Aber! Es wird keine detaillierte Anleitung zum Hochladen der Anwendung auf Github oder zum Erstellen einer Datenbank geben. Davon gibt es reichlich im Internet und es ist sehr detailliert beschrieben; außerdem wird es eine sehr lange Lektüre sein. Die Anwendung funktioniert wie folgt: Geben Sie eine Beschreibung des Ereignisses ein, geben Sie Datum und Uhrzeit des Ereignisses ein, wählen Sie die Häufigkeit aus (Sie können dies einmal tun, Sie können jeden Tag zu einer bestimmten Zeit eine Erinnerung erhalten, Sie können sie einmal erhalten). im Monat zu einer bestimmten Zeit oder einmal im Jahr). Variationen von Benachrichtigungen können endlos hinzugefügt werden; ich habe viele Ideen. Als nächstes werden die eingegebenen Daten in der Datenbank gespeichert (ebenfalls kostenlos auf Heroku bereitgestellt, 10.000 Zeilen sind kostenlos). Dann ruft Spring einmal zu Beginn des Tages um 0:00 Uhr Serverzeit alle Ereignisse basierend auf den Kriterien aus der Datenbank ab Das sollte an diesem Tag ausgelöst werden und sendet sie zur angegebenen Zeit zur Ausführung. AUFMERKSAMKEIT!!! DIESER TEIL DES PROGRAMMS IST EXPERIMENTELL! ES GIBT EINE UMSETZUNG, DIE EINFACHER UND WAHRHEITLICHER IST! Dies wurde speziell gemacht, um zu sehen, wie der Zeitunterricht funktioniert! Sie können den funktionierenden Bot mit Ihren eigenen Händen berühren, indem Sie @calendar_event_bot in den Warenkorb eingeben, aber rechnen Sie nicht damit, denn ich mache mich immer noch darüber lustig. Code – https://github.com/papoff8295/webHookBotForHabr Um Ihr eigenes zu starten, müssen Sie grundsätzlich die folgenden Schritte ausführen: • Registrieren Sie sich bei @BotFather , es ist nicht schwierig, besorgen Sie sich ein Token und einen Namen. • Forken Sie das Projekt auf Github. • Registrieren Sie sich auf Heroku, erstellen Sie eine Anwendung (wir gehen sie Schritt für Schritt durch) und stellen Sie sie aus Ihrem Repository bereit. • Erstellen Sie eine Datenbank auf Heroku. • Ersetzen Sie die entsprechenden Felder im Repository durch Ihre eigenen (Token, Name der Tabellen in Entitäten, webHookPath, Benutzername, Passwort und Pfad zur Datenbank. Dies alles wird analysiert.) • Sorgen Sie dafür, dass Heroku rund um die Uhr funktioniert. 7 mit https://uptimerobot.com/ Die endgültige Struktur des Projekts ist wie folgt: Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 2 Beginnen wir mit der Erstellung eines Projekts in https://start.spring.io. Wählen Sie die Abhängigkeiten aus, die wir benötigen, wie in der Abbildung gezeigt: Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 3Wählen Sie unsere eigenen aus Geben Sie einen Namen für das Projekt ein und klicken Sie auf „Generieren“ . Als nächstes werden Sie aufgefordert, das Projekt auf Ihrer Festplatte zu speichern. Sie müssen nur noch die Datei pom.xm l in Ihrer Entwicklungsumgebung öffnen. Vor Ihnen liegt ein fertiges Projekt. Jetzt müssen wir nur noch unsere Hauptbibliothek hinzufügen. Ich habe die Bibliothek von https://github.com/rubenlagus/TelegramBots verwendet . Im Allgemeinen kann man verwirrt sein und darauf verzichten. Schließlich besteht der ganze Sinn der Arbeit darin, eine URL wie diese zu verketten: https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io Schauen wir es uns ein wenig an : https://api.telegram.org – Telegrammserver. bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/ – hinter dem Wort Bot steht ein geheimes Token, das Sie bei der Registrierung eines Bots erhalten. setWebhook?url=https://e9c658b548aa.ngrok.io – Name der Methode und ihrer Parameter. In diesem Fall installieren wir Ihren Webhook-Server, alle Nachrichten werden an ihn gesendet. Generell kam ich zu dem Schluss, dass das Projekt nicht zu klein für eine Veröffentlichung sei, aber bei manueller Implementierung wäre es im Allgemeinen unlesbar. Das endgültige Aussehen der POM -Datei sieht also so aus:
<!--?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>
Alles ist bereit, unseren Bot zu schreiben. Lassen Sie uns die TelegramBot- Klasse erstellen . Ich werde die Namen der Ordner nicht schreiben, Sie können sie in der Projektstruktur oben sehen.
@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);
    }
}
Die Klasse erweitert SpringWebhookBot aus unserer Telegrammbibliothek, und wir müssen nur eine Methode implementieren, onWebhookUpdateReceived . Es akzeptiert geparstes JSON als Update-Objekt und gibt zurück, was der Telegram-Server von uns „hören“ möchte. Hier haben wir Anmerkungen aus der Lombok- Bibliothek . Lombok – das Leben eines Programmierers einfacher machen!! Nun ja, das ist. Wir müssen Getter und Setter nicht neu definieren, Lombok erledigt das für uns, und wir müssen auch keine Zugriffsebenenkennung schreiben. Es lohnt sich nicht mehr zu schreiben, dass dies durch die Annotationen @Getter, @Setter, @FieldDefaults erfolgt. Das Feld botPath bedeutet unsere Webhook-Adresse, die wir später auf Heroku erhalten. Das Feld botUsername bedeutet den Namen unseres Bots, den wir bei der Registrierung unseres Bots in Telegram erhalten. Das botToken- Feld ist unser Token, das wir bei der Registrierung unseres Bots in Telegram erhalten. Das Feld telegramFacade ist unsere Klasse, in der die Nachrichtenverarbeitung stattfinden wird. Wir werden etwas später darauf zurückkommen, lassen Sie es vorerst rot sein. Jetzt ist es an der Zeit, dass wir @BotFather kontaktieren und den begehrten botToken und den botUsernamen erhalten. Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 4Schreiben Sie ihm einfach per Telegramm und er wird Ihnen alles erzählen. Wir schreiben die Daten in unsere application.properties, am Ende sieht es so aus:
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
Diese Konfiguration ist für die Arbeit mit einer lokalen Datenbank konfiguriert; später werden wir die notwendigen Änderungen vornehmen. Ersetzen Sie botToken und Benutzernamen durch Ihren eigenen. Es ist nicht sinnvoll, Daten aus application.properties direkt in der Anwendung zu verwenden. Erstellen wir aus diesen Daten eine Bean oder eine Wrapper-Klasse.
@Component
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)

public class TelegramBotConfig {
    @Value("${telegrambot.webHookPath}")
    String webHookPath;
    @Value("${telegrambot.userName}")
    String userName;
    @Value("${telegrambot.botToken}")
    String botToken;
Hier initialisiert die Annotation @Value die entsprechenden Zeilen aus der Datei application.properties, die Spring standardmäßig kennt. Und die @Component-Annotation erstellt beim Start der Anwendung ein Bean für uns. Schauen wir uns nun die Spring-Konfigurationsdatei an:
@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;
    }
}
Hier gibt es keine Magie; beim Start erstellt Spring SetWebhook- und TelegramBot-Objekte für uns. Lassen Sie uns nun Einstiegspunkte für unsere Nachrichten erstellen:
@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();
    }
}
Der Telegram-Server sendet Nachrichten im JSON-Format mit der POST-Methode an die registrierte Webhook-Adresse, unser Controller empfängt sie und übermittelt sie in Form eines Update-Objekts an die Telegram-Bibliothek. Метод get я сделал просто так ) Теперь нам осталось реализовать Wieую-то логику обработки сообщений и ответа в классе TelegramFacade , я приведу его краткий Code, чтобы уже можно было запускать приложение и дальше идти своим путем oder перейти уже у deploy на Heroku, потом будет Vollversion:
@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;
    }

}
Diese Methode reagiert auf alle Hello world!-Anfragen. Um unsere Anwendung zu starten, müssen wir lediglich sicherstellen, dass wir unsere Anwendung direkt von IDEA aus testen können. Dazu müssen wir das Dienstprogramm ngrok herunterladen. https://ngrok.com/download Dieses Dienstprogramm ist eine Befehlszeile, die uns eine temporäre Adresse für 2 Stunden gibt und alle Nachrichten an den angegebenen Port des lokalen Servers umleitet. Wir starten und schreiben ngrok http 5000 in die Zeile (oder Sie können Ihren Port angeben): Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 5Wir erhalten das Ergebnis: Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 6https://23b1a54ccbbd.ngrok.io – das ist unsere Webhook-Adresse. Wie Sie vielleicht in der Eigenschaftendatei bemerkt haben, die wir beim Starten des Tomcat-Servers server.port=5000 geschrieben haben, belegt dieser Port 5000. Stellen Sie sicher, dass diese Felder identisch sind. Vergessen Sie auch nicht, dass die Adresse zwei Stunden lang angegeben wird. Auf der Befehlszeile wird dies durch das Feld „Sitzung läuft ab“ überwacht. Wenn die Zeit abgelaufen ist, müssen Sie die Adresse erneut abrufen und den Vorgang zur Registrierung im Telegramm durchführen. Jetzt nehmen wir die Zeile https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io Und mit geschickten Handbewegungen ersetzen wir den Token durch unseren, die URL durch unseren, einfügen Geben Sie die resultierende Zeile in den Browser ein und klicken Sie auf die Eingabetaste. Sie sollten das folgende Ergebnis erhalten: Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 7Das war’s, jetzt können Sie die Anwendung ausführen: Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 8Überprüfen Sie, ob Ihre Klasse mit der Hauptmethode so aussah:
@SpringBootApplication
public class TelegramBotApplication {

   public static void main(String[] args) {
      SpringApplication.run(TelegramBotApplication.class, args);
   }
}
Wenn Sie alles richtig gemacht haben, antwortet Ihr Bot jetzt auf jede Nachricht mit dem Satz „ Hallo Welt“ . Dann kannst du deinen eigenen Weg gehen. Wenn Sie wie ich sind und daran interessiert sind, alle Schritte durchzugehen, dann beginnen wir mit dem Schreiben von Entitäten für die Datenbank und der Erstellung der Datenbank selbst. Beginnen wir mit der Datenbank: Wie bereits gesagt gehe ich davon aus, dass Sie bereits über minimale Kenntnisse im Umgang mit der Datenbank verfügen und eine lokale PostgreSQL- Datenbank installiert haben . Wenn nicht, folgen Sie diesem Weg. https://www.postgresql.org/download/ Ersetzen Sie in der Datei application.properties den Datenbank-Login und das Passwort durch Ihre eigenen. In IDEA gibt es rechts eine Datenbank-Registerkarte, in der Sie auf +/Datenquelle/PostgreSQL klicken müssen . Wenn Sie dann auf Verbindung testen klicken, sollten Sie ein zufriedenstellendes Ergebnis erhalten: Jetzt können Sie direkt aus der Entwicklungsumgebung heraus eine Datenbank mit Tabellen erstellen oder die pgadmin-Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 9 Weboberfläche verwenden , die sich im Startmenü befindet. Wir benötigen 3 Tische:
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
);
Ich empfehle, dieses Skript separat zu erstellen; wir werden es benötigen, um eine Datenbank auf Heroku zu erstellen, damit wir es nicht zweimal schreiben müssen. Lass uns ein wenig spazieren gehen. Ich sage gleich, dass wir aufgrund ihrer Besonderheiten und meines unstillbaren Wunsches, mit der Time- Klasse zu arbeiten, nur die Tabelle event_cash benötigen, um mit Heroku zu arbeiten ; sie wird in der lokalen Version nicht nützlich sein. In der Benutzertabelle erfassen wir die ID des Telegram-Benutzerkontos, seinen Namen, der möglicherweise nicht existiert, die Zeitzone des Benutzers wird für das korrekte Senden von Benachrichtigungen berechnet, sowie den Ein-/Aus- Status des Sendens von Benachrichtigungen. Wir zeichnen die Benutzer- ID , den Benachrichtigungszeitpunkt und die Beschreibung in der Tabelle „user_events“ auf , generieren automatisch eine ID für das Ereignis und legen die Häufigkeit der Benachrichtigungen fest. Die Tabelle „event_cash“ zeichnet die Benachrichtigung auf, bevor sie gesendet wird, und entfernt sie, wenn sie gesendet wird, aus der Tabelle. Die Tabellen sind fertig, nun fügen wir die Entitäten hinzu.
@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;
    }
}
Lassen Sie uns die wichtigsten Punkte noch einmal durchgehen. @Entity – markiert die Klasse für unser Dada JPA, dass diese Klasse eine Entität für die Datenbank ist, d.h. Beim Abrufen von Daten aus der Datenbank werden uns diese in Form eines Event-, User- und EventCashEntity-Objekts präsentiert. @Table – wir sagen den Namen unserer Tabelle in der Datenbank. Um sicherzustellen, dass der Tabellenname nicht rot unterstrichen wird, müssen wir in IDEA der vorgeschlagenen Fehlerkorrekturoption zustimmen und auf Datenquellen zuweisen klicken. Und wählen Sie dort unsere Basis aus. @id und @GeneratedValue – werden von Spring verwendet, um eine Datenbank zu erstellen, falls diese noch nicht vorhanden ist. @Column wird verwendet, um den Namen der Felder in der Tabelle anzugeben, wenn diese nicht übereinstimmen. Die Regeln für guten Code empfehlen jedoch, dass Sie dies immer schreiben. OneToMany- Einstellung – ich empfehle, Zeit zu investieren und herauszufinden, was es hier ist: https://en.wikibooks.org/wiki/Java_Persistence Ich kann es nicht klarer erklären, glauben Sie mir einfach. Lassen Sie mich nur sagen, dass in diesem Fall die Annotation @OneToMany besagt, dass ein Benutzer viele Ereignisse haben kann und diese uns in Form einer Liste bereitgestellt werden. Jetzt müssen wir Daten aus den Tabellen abrufen. In der SRING DATA JPA- Bibliothek ist bereits alles für uns geschrieben, wir müssen nur eine Schnittstelle für jede Tabelle erstellen und diese aus JpaRepository erweitern.
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,>
Die Hauptlogik für die Arbeit mit der Datenbank wird an einen Dienst übergeben, das sogenannte 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>
In diesem Fall erfolgt bei uns keine Datenverarbeitung, wir rufen lediglich Daten aus den Tabellen ab. Wir sind alle bereit, den vollständigen Code der TelegramFacade -Klasse bereitzustellen und mit der Analyse der Logik zu beginnen.
@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);

    }
}
Schauen wir uns an, wofür Felder benötigt werden
final MessageHandler messageHandler;
    final CallbackQueryHandler callbackQueryHandler;
    final BotStateCash botStateCash;
Wenn wir alle in einer Klasse programmieren, haben wir am Ende ein Fußtuch zum Mond; daher weisen wir die Logik für die Arbeit mit Textnachrichten der Klasse MessageHandler und die Logik für die Arbeit mit Callbackquery-Nachrichten der Klasse CallbackQueryHandler zu . Es ist an der Zeit, herauszufinden, was Allbackquery ist und welche Arten von Menüs es gibt. Dazu zeige ich Ihnen noch ein weiteres Bild der Benutzeroberfläche des Bots: Telegram-Bot – Erinnerung per WebHook in Java oder Nein zum Google-Kalender!  - 10Es gibt zwei Arten von Menüs. Diejenigen, die am unteren Rand des Fensters angebracht sind – das Hauptmenü, und diejenigen, die der Nachricht zugewiesen sind, zum Beispiel die Schaltflächen „Löschen“, „Bearbeiten“, „Band ändern“. Wenn Sie auf die Hauptmenüschaltfläche klicken, wird eine gleichnamige Nachricht gesendet. Wenn Sie beispielsweise auf „Meine Erinnerungen“ klicken, wird einfach der Text „Meine Erinnerungen“ gesendet . Und bei der Installation der CallbackQuery-Tastatur wird für jede Schaltfläche ein bestimmter Wert festgelegt und dieser Wert wird gesendet, ohne ihn auf dem Bildschirm anzuzeigen. Als nächstes haben wir das BotStateCash- Feld . Dies ist eine speziell erstellte Klasse, die den Status des Bots überwacht. Achtung, dies ist ein komplexes Element, das Sie anstrengen müssen. Die Zeichenanzahl wurde überschritten, was übrigens nirgendwo geschrieben steht)). Hier also der Link zum zweiten Teil
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION