JavaRush /Java Blog /Random-KO /텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요! 1 ...
Vladimir Popov
레벨 41

텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요! 1 부

Random-KO 그룹에 게시되었습니다
내 이름은 블라디미르입니다. 저는 43세입니다. 그리고 독자 여러분이 40세 이상이라면, 그렇습니다. 40세 이후에도 원하신다면 프로그래머가 될 수 있습니다. 내 작업은 프로그래밍과는 전혀 관련이 없습니다. 저는 자동화 분야의 프로젝트 관리자입니다. 하지만 저는 직업을 바꿀 계획이에요. 아, 이런 새로운 트렌드는... 5~7년마다 활동 분야를 바꾸세요. So : 프로젝트 규모가 상당히 큰 것으로 판명되었으므로 독자가 Google에 대해 알 수 있기를 바라면서 몇 가지 사항을 생략하거나 간략하게 설명해야 합니다. 인터넷에는 롱 폴링(Long Polling) 원칙에 따라 작동하는 텔레그램 봇의 출판물이 가득합니다. 그리고 Webhook 원칙을 적용한 작업은 거의 없습니다. 그것은 무엇입니까? 긴 폴링 - 이는 애플리케이션 자체가 특정 빈도의 메시지에 대해 텔레그램 서버를 천천히 폴링한다는 의미입니다. 웹후크 - 텔레그램 서버가 사용자가 지정한 서버로 즉시 메시지를 리디렉션한다는 의미입니다. 우리의 경우 Heroku 서비스가 제공되었습니다. 물론 Telegram 웹 사이트(https://tlgrm.ru/docs/bots/api)에서 이 모든 것과 일반적인 봇에 대한 자세한 내용을 읽을 수 있습니다. 봇 인터페이스는 다음과 같습니다. 텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요!  - 1 저는 이 애플리케이션을 교육용 애플리케이션으로 간주합니다. 훈련할 때보다 글을 쓸 때 이 봇으로부터 더 많은 정보를 배웠기 때문입니다. 프로그래밍을 배우고 싶나요? 코드 작성 시작!!! 하지만! 애플리케이션을 github에 업로드하는 방법이나 데이터베이스를 만드는 방법에 대한 자세한 지침은 없습니다. 인터넷에는 이에 대한 내용이 많이 있으며 매우 자세하게 설명되어 있으며, 게다가 매우 긴 내용을 읽어야 할 것입니다. 애플리케이션은 다음과 같이 작동합니다. 이벤트 설명 입력, 이벤트 날짜 및 시간 입력, 빈도 선택(한 번만 할 수 있고, 매일 특정 시간에 알림을 받을 수 있으며, 한 번만 받을 수 있습니다) 한 달에 한 번 특정 시간에 또는 1년에 한 번). 알림의 변형은 끝없이 추가될 수 있으며 아이디어가 많습니다. 다음으로, 입력된 데이터는 데이터베이스에 저장됩니다(Heroku에서도 무료로 배포되며, 10,000행은 무료입니다). 그런 다음 서버 시간으로 하루가 시작되는 0시에 Spring은 기준에 따라 데이터베이스에서 모든 이벤트를 검색합니다. 해당 날짜에 실행되어야 하며 지정된 시간에 실행되도록 보냅니다. 주목!!! 프로그램의 이 부분은 실험적입니다! 더 간단하고 사실적인 구현이 있습니다! 이는 시간 수업이 어떻게 진행되는지 확인하기 위해 특별히 수행되었습니다! 장바구니에 @calendar_event_bot을 입력하여 작동하는 봇을 직접 손으로 만져보실 수 있지만, 아직 제가 비웃고 있으니 너무 믿지는 마세요. 코드 - https://github.com/papoff8295/webHookBotForHabr 기본적으로 자신만의 것을 시작하려면 다음 단계를 수행해야 합니다. • @BotFather 에 등록합니다 . 어렵지 않습니다. 토큰과 이름을 얻습니다. • github에서 프로젝트를 포크합니다. • 등록 헤로쿠 에서, 애플리케이션을 생성하고(단계적으로 살펴보겠습니다) 저장소에서 배포합니다. • Heroku에 데이터베이스를 생성합니다. • 저장소의 해당 필드를 자신의 필드로 교체합니다(토큰, 엔터티의 테이블 이름, webHookPath, 사용자 이름, 비밀번호 및 데이터베이스 경로가 모두 구문 분석됩니다). • Heroku가 24시간 작동하도록 설정/ 7 using https:/ /uptimerobot.com/ 프로젝트의 최종 구조는 다음과 같습니다. https://start.spring.io텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요!  - 2 에서 프로젝트를 생성하여 시작하겠습니다 . 그림에 표시된 대로 필요한 종속성을 선택합니다. 자체 선택 프로젝트 이름을 지정하고 생성을 클릭합니다 . 다음으로 프로젝트를 디스크에 저장하라는 메시지가 표시됩니다. 남은 것은 개발 환경에서 pom.xml 파일을 여는 것뿐입니다. 당신 앞에 완성된 프로젝트가 있습니다. 이제 메인 라이브러리를 추가하기만 하면 됩니다. 저는 https://github.com/rubenlagus/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 – 메서드 및 해당 매개변수의 이름입니다. 이 경우 웹훅 서버를 설치하면 모든 메시지가 해당 서버로 전송됩니다. 일반적으로 프로젝트가 게시하기에 너무 작지는 않지만 수동으로 구현하면 일반적으로 읽을 수 없을 것이라고 결정했습니다. 따라서 pom 파일 의 최종 모습은 다음과 같습니다. 텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요!  - 삼
<!--?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 – 프로그래머의 삶을 더 쉽게 만들어줍니다!! 글쎄요. getter와 setter를 재정의할 필요가 없습니다. Lombok이 이 작업을 수행하고 액세스 수준 식별자를 작성할 필요도 없습니다. @Getter, @Setter, @FieldDefaults 주석에 의해 이 작업이 수행된다는 것은 더 이상 쓸 가치가 없습니다. botPath 필드는 나중에 Heroku에서 받게 될 웹훅 주소를 의미합니다. botUsername 필드는 텔레그램에 봇을 등록할 때 받게 될 봇의 이름을 의미합니다. botToken 필드 는 텔레그램에 봇을 등록할 때 받게 되는 토큰입니다. telegramFacade 필드는 메시지 처리가 이루어지는 클래스입니다. 잠시 후에 다시 돌아올 것이므로 지금은 빨간색으로 두십시오. 이제 @BotFather 에게 연락하여 탐나는 botToken 및 botUsername을 얻을 차례입니다 . 텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 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 또는 래퍼 클래스를 생성해 보겠습니다.
@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 주석은 Spring이 기본적으로 알고 있는 application.properties 파일의 해당 행을 초기화합니다. 그리고 @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();
    }
}
텔레그램 서버는 POST 메소드를 사용하여 등록된 웹훅 주소로 JSON 형식의 메시지를 보내고, 컨트롤러는 이를 수신하여 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;
    }

}
이 메서드는 모든 Hello world!에 응답합니다. 애플리케이션을 시작하려면 IDEA에서 직접 애플리케이션을 테스트할 수 있는지 확인하면 됩니다. 이렇게 하려면 ngrok 유틸리티를 다운로드해야 합니다. https://ngrok.com/download 이 유틸리티는 2시간 동안 임시 주소를 제공하고 모든 메시지를 로컬 서버의 지정된 포트로 리디렉션하는 명령줄입니다. ngrok http 5000을 시작하고 해당 줄에 씁니다 (또는 포트를 지정할 수 있음). 텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요!  - 5결과는 텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요!  - 6https://23b1a54ccbbd.ngrok.io입니다. 이것이 웹훅 주소입니다. Tomcat 서버를 시작할 때 server.port=5000이라고 작성한 속성 파일에서 알 수 있듯이 Tomcat 서버는 포트 5000을 차지하므로 이러한 필드가 동일한지 확인하십시오. 또한 주소는 2시간 동안 제공된다는 점도 잊지 마세요. 명령줄에서는 세션 만료 필드를 통해 이를 모니터링합니다. 시간이 지나면 다시 주소를 받아 텔레그램에 등록하는 절차를 거쳐야 합니다. 이제 우리는 https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io 줄을 취합니다. 그리고 능숙한 손 움직임으로 토큰을 우리 것으로 바꾸고, URL을 우리 것으로 바꾸고, 붙여넣습니다. 결과 라인을 브라우저에 입력하고 Enter를 클릭하십시오. 다음과 같은 결과를 얻어야 합니다. 텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요!  - 7이제 애플리케이션을 실행할 수 있습니다. 기본텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요!  - 8 메소드 가 포함된 클래스가 다음과 같은지 확인하세요.
@SpringBootApplication
public class TelegramBotApplication {

   public static void main(String[] args) {
      SpringApplication.run(TelegramBotApplication.class, args);
   }
}
모든 작업을 올바르게 수행했다면 이제 봇은 " Hello world" 라는 문구가 포함된 모든 메시지에 응답합니다 . 그러면 당신은 당신 자신의 길을 갈 수 있습니다. 나와 함께 있고 모든 단계를 진행하는 데 관심이 있다면 데이터베이스에 대한 엔터티 작성을 시작하고 데이터베이스 자체를 생성해 보겠습니다. 데이터베이스부터 시작해 보겠습니다. 이미 말했듯이, 저는 여러분이 이미 데이터베이스 작업에 대한 최소한의 기술을 가지고 있고 로컬 postgreSQL 데이터베이스가 설치되어 있다고 가정합니다 . 그렇지 않은 경우 이 경로를 따르세요. https://www.postgresql.org/download/ application.properties 파일에서 데이터베이스 로그인 및 비밀번호를 자신의 것으로 바꾸십시오. IDEA에는 오른쪽에 데이터베이스 탭이 있으며, 여기서 +/Data source/PostgreSQL을 클릭해야 합니다 . 결과적으로 연결 테스트를 클릭하면 만족스러운 결과를 얻을 수 있습니다. 텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 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에서 데이터베이스를 생성하는 데 필요하므로 두 번 작성하지 마십시오. 조금 걷자. Heroku와 함께 작업하려면 event_cash 테이블 만 필요하다고 바로 말씀드리고 Time 클래스 를 사용하려는 끝없는 열망 때문에 Heroku와 함께 작업하려면 로컬 버전에서는 유용하지 않습니다. 사용자 테이블 에는 텔레그램 사용자 계정의 ID , 이름(존재하지 않을 수 있음)이 기록되며 올바른 알림 전송을 위해 사용자의 시간대는 물론 알림 전송 켜기/끄기 상태도 계산됩니다 . user_events 테이블 에 사용자 ID , 알림 시간, 설명을 기록 하고 이벤트에 대한 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,>
데이터베이스 작업을 위한 기본 논리는 소위 데이터 액세스 개체(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 클래스에 할당 하고 콜백 쿼리 메시지 작업을 위한 로직을 CallbackQueryHandler 클래스에 할당합니다 . allbackquery가 무엇인지 , 어떤 종류의 메뉴가 있는지 알아보는 시간입니다 . 이를 위해 봇 인터페이스에 대한 또 다른 그림을 제공하겠습니다. 텔레그램 봇 - Java의 webHook을 통해 알림을 보내거나 Google 캘린더를 거부하세요!  - 10두 가지 유형의 메뉴가 있습니다. 창 하단에 첨부된 것(메인 메뉴)과 메시지에 할당된 것(예: 삭제, 편집, 벨트 변경 버튼). 메인 메뉴 버튼을 클릭하면 동일한 이름의 메시지가 전송됩니다. 예를 들어 "내 알림"을 ​​클릭하면 "내 알림" 이라는 텍스트가 전송됩니다 . 그리고 콜백쿼리 키보드를 설치하면 각 버튼마다 특정 값이 설정되어 화면에 표시되지 않고 그 값이 전송됩니다. 다음에는 BotStateCash 필드가 있습니다 . 이것은 봇의 상태와 주의를 모니터링하기 위해 특별히 생성된 클래스입니다. 이것은 복잡한 요소이므로 긴장해야 합니다. 문자 수를 초과했는데 어디에도 기록되지 않습니다)). 그럼 2부 링크는 여기 있어요
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION