JavaRush /وبلاگ جاوا /Random-FA /ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن ب...
Vladimir Popov
مرحله

ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل! قسمت 1

در گروه منتشر شد
نام من ولادیمیر است. من 43 سال دارم. و اگر شما، خواننده، بالای 40 سال دارید، بله، پس از 40 سالگی، اگر دوست دارید می توانید برنامه نویس شوید. کار من اصلاً ربطی به برنامه نویسی ندارد، من مدیر پروژه در زمینه اتوماسیون و اینها هستم. اما من قصد دارم شغلم را تغییر دهم. آخه این ترندهای جدید... هر 5-7 سال یه بار زمینه فعالیتتو عوض کن. بنابراین : معلوم شد که پروژه بسیار بزرگ است، بنابراین باید برخی از نکات را حذف کرد یا به طور خلاصه در مورد آنها صحبت کرد، به این امید که خواننده بداند چگونه گوگل کند. اینترنت پر است از انتشارات ربات های تلگرام که بر اساس اصل نظرسنجی طولانی کار می کنند. و تعداد بسیار کمی هستند که روی اصل Webhook کار می کنند. آن چیست؟ نظرسنجی طولانی - این بدان معنی است که خود برنامه شما به آرامی از سرور تلگرام برای پیام ها با فرکانس مشخص نظرسنجی می کند. Webhook - یعنی سرور تلگرام فوراً پیام ها را به سروری که شما مشخص کرده اید هدایت می کند. در مورد ما، با حسن نیت از سرویس Heroku. البته می توانید در مورد همه اینها و به طور کلی در مورد ربات در وب سایت تلگرام بیشتر بخوانید - https://tlgrm.ru/docs/bots/api رابط ربات به این صورت است: ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 1 من این برنامه را دقیقاً به عنوان یک آموزش در نظر می‌گیرم. پروژه به این دلیل است که هنگام نوشتن اطلاعات بیشتری از این ربات یاد گرفتم تا هنگام آموزش. آیا می خواهید برنامه نویسی را یاد بگیرید؟ شروع به نوشتن کد کنید!!! ولی! هیچ دستورالعمل دقیقی در مورد نحوه آپلود برنامه در github یا نحوه ایجاد پایگاه داده وجود نخواهد داشت. این موارد در اینترنت به وفور یافت می شود و با جزئیات زیاد توضیح داده شده است؛ علاوه بر این، خواندن آن بسیار طولانی خواهد بود. این برنامه به صورت زیر عمل می کند: شرح رویداد را وارد کنید، تاریخ و زمان رویداد را وارد کنید، فرکانس را انتخاب کنید (می توانید آن را یک بار انجام دهید، می توانید هر روز در یک زمان خاص یک یادآوری داشته باشید، می توانید یک بار آن را داشته باشید. یک ماه در یک زمان خاص، یا یک بار در سال). تنوع اعلان ها را می توان بی نهایت اضافه کرد؛ من ایده های زیادی دارم. سپس داده های وارد شده در پایگاه داده ذخیره می شود (همچنین به صورت رایگان در Heroku مستقر می شود، 10000 ردیف رایگان است) سپس یک بار در ابتدای روز در ساعت 0:00 به وقت سرور، Spring تمام رویدادها را بر اساس معیارها از پایگاه داده بازیابی می کند. که باید در آن روز شلیک کند و در زمان مشخص آنها را برای اعدام می فرستد. توجه!!! این بخش از برنامه تجربی است! یک پیاده سازی وجود دارد که ساده تر و واقعی تر است! این به طور خاص برای دیدن نحوه عملکرد کلاس تایم انجام شد! با تایپ @calendar_event_bot در سبد خرید می‌توانید ربات کار را با دستان خود لمس کنید، اما روی آن حساب نکنید، زیرا من هنوز دارم آن را مسخره می‌کنم. کد - https://github.com/papoff8295/webHookBotForHabr اساسا، برای راه‌اندازی پروژه خود باید مراحل زیر را انجام دهید: • ثبت نام در @BotFather ، دشوار نیست، یک رمز و نام دریافت کنید • پروژه را در github فورک کنید • ثبت نام کنید در هروکو، یک برنامه ایجاد کنید (ما آن را مرحله به مرحله مرور خواهیم کرد)، از مخزن خود مستقر کنید. • ایجاد یک پایگاه داده در Heroku • فیلدهای مربوطه را در مخزن با خود جایگزین کنید (توکن، نام جداول موجودیت ها، webHookPath، نام کاربری، رمز عبور و مسیر به پایگاه داده، همه اینها تجزیه می شود) • کاری کنید که Heroku 24/24 کار کند. 7 با استفاده از https:// /uptimerobot.com/ ساختار نهایی پروژه به شرح زیر است: ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 2 بیایید با ایجاد یک پروژه در https://start.spring.io شروع کنیم ، وابستگی های مورد نیاز خود را مطابق شکل انتخاب کنیم: ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 3خودمان را انتخاب کنیم. نام پروژه را بزنید و روی Generate کلیک کنید . در مرحله بعد از شما خواسته می شود که پروژه را در دیسک خود ذخیره کنید. تنها چیزی که باقی می ماند این است که فایل pom.xm l را از محیط توسعه خود باز کنید. یک پروژه تمام شده پیش روی شماست. اکنون فقط باید کتابخانه اصلی خود را اضافه کنیم. من از کتابخانه https://github.com/rubenlagus/TelegramBots استفاده کردم به طور کلی، می توانید گیج شوید و بدون آن کار کنید. پس از همه، تمام هدف کار این است که یک URL مانند این را به هم بچسبانید: https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b58 Leta look at little. : https://api.telegram.org – سرور تلگرام. bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/ - بعد از کلمه ربات یک رمز مخفی است که هنگام ثبت ربات دریافت می کنید. setWebhook?url=https://e9c658b548aa.ngrok.io – نام روش و پارامترهای آن. در این صورت سرور وب هوک شما را نصب می کنیم، تمام پیام ها به آن ارسال می شود. به طور کلی، من تصمیم گرفتم که پروژه برای انتشار خیلی کوچک نیست، اما با اجرای دستی به طور کلی غیرقابل خواندن خواهد بود. بنابراین، ظاهر نهایی فایل pom این است:
<!--?xml version="1.0" encoding="UTF-8"?-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelversion>4.0.0</modelversion>
   <parent>
      <groupid>org.springframework.boot</groupid>
      <artifactid>spring-boot-starter-parent</artifactid>
      <version>2.5.0</version>
      <relativepath> <!-- lookup parent from repository -->
   </relativepath></parent>
   <groupid>ru.popov</groupid>
   <artifactid>telegrambot</artifactid>
   <version>0.0.1-SNAPSHOT</version>
   <name>telegrambot</name>
   <description>Demo project for Spring Boot</description>
   <properties>
      <java.version>1.8</java.version>
   </properties>
   <dependencies>
      <dependency>
         <groupid>org.springframework.boot</groupid>
         <artifactid>spring-boot-starter-web</artifactid>
      </dependency>

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

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

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

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

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

   </dependencies>

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

</project>
همه چیز برای نوشتن ربات ما آماده است. بیایید کلاس TelegramBot را ایجاد کنیم . من نام پوشه ها را نمی نویسم، می توانید آنها را در ساختار پروژه بالا نگاه کنید.
@Getter
@Setter
@FieldDefaults(level = AccessLevel.PRIVATE)
public class TelegramBot extends SpringWebhookBot {
    String botPath;
    String botUsername;
    String botToken;

    private TelegramFacade telegramFacade;

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

    @Override
    public BotApiMethod<!--?--> onWebhookUpdateReceived(Update update) {
        return telegramFacade.handleUpdate(update);
    }
}
کلاس SpringWebhookBot را از کتابخانه تلگرام ما گسترش می دهد، و ما فقط باید یک روش را پیاده سازی کنیم، onWebhookUpdateReceived . JSON تجزیه شده را به عنوان یک آبجکت به‌روزرسانی می‌پذیرد و آنچه را که سرور تلگرام می‌خواهد از ما بشنود، برمی‌گرداند. در اینجا ما حاشیه نویسی از کتابخانه Lombok داریم . لومبوک - زندگی یک برنامه نویس را آسان تر می کند! خوب، این است. ما نیازی به تعریف مجدد دریافت کننده ها و تنظیم کننده ها نداریم، Lombok این کار را برای ما انجام می دهد و همچنین نیازی به نوشتن شناسه سطح دسترسی نداریم. دیگر ارزش نوشتن این را ندارد که این کار توسط حاشیه‌نویسی‌های @Getter، @Setter، @FieldDefaults انجام می‌شود فیلد botPath به معنای آدرس وب هوک ما است که بعداً در Heroku دریافت خواهیم کرد. فیلد botUsername به معنای نام ربات ما است که هنگام ثبت ربات خود در تلگرام آن را دریافت خواهیم کرد. فیلد botToken توکن ماست که هنگام ثبت ربات خود در تلگرام دریافت خواهیم کرد. فیلد telegramFacade کلاس ما است که در آن پردازش پیام انجام می شود، کمی بعد به آن برمی گردیم، اجازه دهید فعلا قرمز باشد. اکنون وقت آن است که با BotFather@ تماس بگیریم و botToken و botUsername را دریافت کنیم. ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 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
این پیکربندی برای کار با یک پایگاه داده محلی پیکربندی شده است؛ بعداً تغییرات لازم را انجام خواهیم داد. بات توکن و نام کاربری خود را جایگزین کنید . استفاده مستقیم از داده های application.properties در برنامه خوب نیست. بیایید از این داده ها یک کلاس bean یا wrapper ایجاد کنیم.
@Component
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)

public class TelegramBotConfig {
    @Value("${telegrambot.webHookPath}")
    String webHookPath;
    @Value("${telegrambot.userName}")
    String userName;
    @Value("${telegrambot.botToken}")
    String botToken;
در اینجا حاشیه نویسی @Value خطوط مربوطه را از فایل application.properties، که Spring به طور پیش فرض از آن مطلع است، مقداردهی اولیه می کند. و هنگام شروع برنامه، حاشیه نویسی @Component یک Bean برای ما ایجاد می کند. اکنون به فایل پیکربندی Spring نگاهی می اندازیم:
@Configuration
public class AppConfig {
    private final TelegramBotConfig botConfig;

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

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

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

        return bot;
    }
}
اینجا هیچ جادویی وجود ندارد؛ در هنگام راه اندازی، اسپرینگ اشیاء 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 به آدرس وب هوک ثبت شده با استفاده از روش POST ارسال می کند، کنترل کننده ما آنها را دریافت کرده و در قالب یک آبجکت Update به کتابخانه تلگرام ارسال می کند. من روش دریافت را همینطور انجام دادم) حالا فقط باید یک منطق برای پردازش پیام ها و پاسخ ها در کلاس TelegramFacade پیاده سازی کنیم ، کد کوتاه آن را می دهم تا بتوانید برنامه را راه اندازی کنید و سپس راه خود را بروید یا تغییر دهید تا Deploy کنید. در 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 را در خط راه اندازی کرده و می نویسیم (یا می توانید پورت خود را مشخص کنید): ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 5نتیجه را می گیریم: ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 6https://23b1a54ccbbd.ngrok.io - این آدرس وب هوک ما است. همانطور که در فایل خواصی که هنگام راه اندازی سرور تامکت نوشتیم server.port=5000 متوجه شده اید، پورت 5000 را اشغال می کند، مطمئن شوید که این فیلدها یکسان هستند. ضمناً فراموش نکنید که آدرس برای دو ساعت داده می شود. در خط فرمان، این مورد توسط قسمت Session Expires نظارت می شود. پس از اتمام زمان، باید دوباره آدرس را دریافت کرده و مراحل ثبت آن در تلگرام را طی کنید. اکنون ما خط را انتخاب می کنیم https://api.telegram.org/bot1866835969:AAE6gJG6ptUyqhV2XX0MxyUak4QbAGGnz10/setWebhook?url=https://e9c658b548aa.ngrok.io و با حرکات ماهرانه دست با حرکات خود جایگزین می کنیم. خط حاصل را وارد مرورگر کرده و روی enter کلیک کنید. شما باید نتیجه زیر را بگیرید: ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 7تمام شد، اکنون می توانید برنامه را اجرا کنید: ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 8بررسی کنید که کلاس شما با متد main به این صورت باشد:
@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 کلیک کنید . در نتیجه، وقتی روی Test Connection کلیک می‌کنید ، باید نتیجه رضایت‌بخشی دریافت کنید: ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 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 با گزینه اصلاح خطای پیشنهادی موافقت کنیم و روی Assign data sources کلیک کنیم. و پایگاه ما را در آنجا انتخاب کنید. @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,>
منطق اصلی کار با پایگاه داده به سرویسی منتقل می شود که به اصطلاح Object Access Data (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;
اگر همه در یک کلاس کدنویسی کنیم، در نهایت با یک footcloth به ماه می‌رسیم؛ بنابراین، منطق کار با پیام‌های متنی را به کلاس MessageHandler و منطق کار با پیام‌های callbackquery را به کلاس CallbackQueryHandler اختصاص می‌دهیم . وقت آن رسیده است که بفهمیم allbackquery چیست و چه نوع منوهایی وجود دارد. برای انجام این کار، تصویر دیگری از رابط کاربری ربات به شما می‌دهم: ربات تلگرام - یادآوری از طریق وب هوک در جاوا یا نه گفتن به تقویم گوگل!  - 10دو نوع منو وجود دارد. مواردی که به پایین پنجره متصل هستند - منوی اصلی و مواردی که به پیام اختصاص داده شده اند، به عنوان مثال، دکمه های حذف، ویرایش، تغییر کمربند. وقتی روی دکمه منوی اصلی کلیک می‌کنید، پیامی به همین نام ارسال می‌شود، مثلاً وقتی روی «یادآوری‌های من» کلیک می‌کنید، متن «یادآوری‌های من» به سادگی ارسال می‌شود . و هنگام نصب کیبورد callbackquery برای هر دکمه مقدار مشخصی در نظر گرفته شده و مقدار آن بدون نمایش روی صفحه ارسال می شود. بعد ما فیلد BotStateCash را داریم . این یک کلاس مخصوص ایجاد شده است که وضعیت ربات را نظارت می کند، و توجه، این یک عنصر پیچیده است، شما باید فشار دهید. از تعداد کاراکترها بیشتر شد که اتفاقاً در هیچ کجا نوشته نشده است)). بنابراین این لینک قسمت دوم است
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION