JavaRush /Java Blog /Random-ID /Menambahkan klien ke artikel - "Proyek Java dari A hingga...

Menambahkan klien ke artikel - "Proyek Java dari A hingga Z"

Dipublikasikan di grup Random-ID
Halo semuanya, teman-teman terkasih. Selangkah demi selangkah kami semakin dekat dengan tujuan kami - menjadi MVP proyek kami - JavaRush Telegram Bot. Seperti yang saya katakan di artikel terakhir, tugas tersisa hanya 5. Hari ini kita akan membahas dua di antaranya. "Proyek Java dari A hingga Z": Menambahkan klien ke artikel - 1Saya ingin mengulangi bahwa proyek ini tidak akan berakhir di sini. Saya masih punya banyak ide dan visi tentang bagaimana proyek ini harus dikembangkan, hal-hal baru apa yang bisa ditambahkan, apa yang bisa dilakukan dengan lebih baik. Sebelum MVP, kami akan membuat artikel terpisah tentang topik refactoring - yaitu tentang meningkatkan kualitas kode tanpa mengubah fungsinya. Pada saat itu, keseluruhan proyek akan terlihat dan menjadi jelas apa dan di mana yang dapat ditingkatkan. Dalam kasus kami, kami akan terlindungi secara maksimal dari kerusakan fungsi, karena banyak pengujian telah ditulis. Kami juga akan menulis retrospektif tentang apa yang kami inginkan dan apa yang kami dapatkan pada akhirnya. Ini adalah hal yang sangat berguna: mari kita lihat seberapa benar segala sesuatunya terlihat enam bulan lalu. Setidaknya ini sangat menarik bagi saya. Jika ada yang ingin mencoba sendiri sebagai penguji manual, kirimkan surat kepada kami dan kami akan berkolaborasi. Mari kita jadikan proyek ini lebih baik bersama-sama! Jadi, ini dia: dua tugas yang dijelaskan enam bulan lalu: JRTB-8 dan JRTB-9 . Saya mulai mencari apa yang perlu diterapkan untuk tugas-tugas ini, dan menyadari bahwa dalam hal peluncuran perintah, semuanya sudah siap. Itu terjadi...) Di sini, Anda dapat melihat StartCommand , metode eksekusinya :
@Override
public void execute(Update update) {
   String chatId = update.getMessage().getChatId().toString();

   telegramUserService.findByChatId(chatId).ifPresentOrElse(
           user -> {
               user.setActive(true);
               telegramUserService.save(user);
           },
           () -> {
               TelegramUser telegramUser = new TelegramUser();
               telegramUser.setActive(true);
               telegramUser.setChatId(chatId);
               telegramUserService.save(telegramUser);
           });

   sendBotMessageService.sendMessage(chatId, START_MESSAGE);
}
Logikanya berfungsi di sini: jika database kami sudah memiliki pengguna seperti itu berdasarkan chatId, kami cukup menyetel bidang active = true untuknya. Dan jika tidak ada pengguna seperti itu, kami membuat yang baru. Sama untuk perintah /stop di StopCommand :
@Override
public void execute(Update update) {
   telegramUserService.findByChatId(update.getMessage().getChatId().toString())
           .ifPresent(it -> {
               it.setActive(false);
               telegramUserService.save(it);
           });
   sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), STOP_MESSAGE);
}
Terlihat bahwa saat memanggil perintah ini, hanya kolom active = false yang disetel untuk pengguna. Dan itu saja: langganannya akan aktif dan menunggu saat pengguna kembali memutuskan untuk mengaktifkan obrolan dengan bot. Dan sepertinya tugas tersebut sudah selesai dan bisa ditutup. Tapi itu tidak ada di sana. Tugas paling penting adalah membuat pemberitahuan tentang artikel baru di langganan. Di sinilah tugas-tugas ini akan diperbarui dan diselesaikan sepenuhnya. Artinya, sampai kita menerapkan notifikasi artikel baru, tidak bisa ditutup. Oleh karena itu, mari kita selesaikan tugas JRTB-4 - membuat cek setiap 20 menit dan pemberitahuan tentang artikel baru. Teman-teman! Apakah Anda ingin segera mengetahui kapan kode baru untuk proyek tersebut dirilis? Kapan artikel baru keluar? Bergabunglah dengan saluran tg saya . Di sana saya mengumpulkan artikel saya, pemikiran saya, pengembangan sumber terbuka saya bersama.

Kami menerapkan JRTB-4

Apa yang perlu kita lakukan sebagai bagian dari tugas ini:
  1. Buat pekerjaan yang secara berkala akan mengunjungi semua grup tempat kita berlangganan di database, mengurutkan artikel berdasarkan tanggal publikasi dan memeriksa apakah ID publikasi terakhir cocok dengan nilai di GroupSub. Jika tidak cocok, maka Anda perlu memahami secara pasti berapa banyak artikel yang telah diterbitkan sejak terakhir kali. Kami memperbarui last_article_id di GroupSub7 ke kondisi saat ini.

  2. Ketika kami menemukan daftar artikel yang diterbitkan, kami menemukan semua pengguna ACTIVE untuk grup ini dan mengirimi mereka pemberitahuan tentang artikel baru.

Untuk melakukan ini, kita akan menggunakan sesuatu seperti Spring Scheduler. Ini adalah mekanisme di Spring Framework, dengan itu Anda dapat membuat tugas yang akan dieksekusi pada waktu tertentu. Bisa setiap 15-20-40 menit, atau setiap Kamis pukul 15.30 atau pilihan lainnya. Mereka juga disebut kertas kalkir dari bahasa Inggris - joba. Saat kami melakukan tugas ini, saya sengaja meninggalkan satu cacat dalam pencarian artikel baru. Ini cukup jarang dan hanya muncul dalam situasi di mana saya menguji pengoperasian tugas ini secara manual. Untuk melakukan ini, Anda perlu menulis klien untuk mencari artikel. Untuk melakukan ini, kita akan menggunakan Swagger API yang sudah tidak asing lagi bagi kita . Ada pasca-pengontrol. Kami hanya tertarik mencari kumpulan artikel dengan menggunakan filter tertentu:
/api/1.0/rest/posts Dapatkan postingan berdasarkan filter
Kami akan menangani permintaan ini. Apa yang kita butuhkan di dalamnya? Dapatkan daftar artikel milik grup tertentu, dan artikel tersebut harus diurutkan berdasarkan tanggal publikasi. Dengan cara ini kami dapat mengambil 15 artikel terakhir dan memeriksa apakah publikasi baru telah diterbitkan berdasarkan lastArticleId dari database kami. Jika ada, kami akan meneruskannya untuk diproses dan dikirim ke pengguna. Jadi kita perlu menulis JavaRushPostClient .

Kami menulis JavaRushPostClient

Di sini kami tidak akan mencoba untuk mencakup semua permintaan yang dikirimkan kepada kami di API dan hanya akan membuat permintaan yang kami perlukan. Dengan melakukan ini, kami mencapai dua tujuan sekaligus:
  1. Kami mempercepat proses penulisan aplikasi kami.

  2. Kami menyerahkan pekerjaan ini kepada mereka yang ingin membantu komunitas kami dan memutuskan untuk mencoba sendiri sebagai pengembang. Saya akan membuat tugas untuk ini yang bisa diselesaikan setelah MVP.

Jadi mari kita lakukan. Untuk menanyakan bagian Model di Swagger UI, kita akan membuat DTO berikut:"Proyek Java dari A hingga Z": Menambahkan klien ke artikel - 2

Info Pengguna Dasar:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

import lombok.Data;

/**
* DTO, which represents base user information.
*/
@Data
public class BaseUserInfo {
   private String city;
   private String country;
   private String displayName;
   private Integer id;
   private String job;
   private String key;
   private Integer level;
   private String pictureUrl;
   private String position;
   private UserPublicStatus publicStatus;
   private String publicStatusMessage;
   private Integer rating;
   private Integer userId;
}

Bahasa:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents languages.
*/
public enum Language {
   UNKNOWN,
   ENGLISH,
   GERMAN,
   SPANISH,
   HINDI,
   FRENCH,
   PORTUGUESE,
   POLISH,
   BENGALI,
   PUNJABI,
   CHINESE,
   ITALIAN,
   INDONESIAN,
   MARATHI,
   TAMIL,
   TELUGU,
   JAPANESE,
   KOREAN,
   URDU,
   TAIWANESE,
   NETHERLANDS,
   RUSSIAN,
   UKRAINIAN
}

Info Suka:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents like's information.
*/
public class LikesInfo {

   private Integer count;
   private LikeStatus status;
}

Status Suka:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents like's status.
*/
public enum LikeStatus {

   UNKNOWN,
   LIKE,
   HOT,
   FOLLOW,
   FAVORITE,
   SOLUTION,
   HELPFUL,
   ARTICLE,
   OSCAR,
   DISLIKE,
   WRONG,
   SPAM,
   ABUSE,
   FOUL,
   TROLLING,
   OFFTOPIC,
   DUPLICATE,
   DIRTY,
   OUTDATED,
   BORING,
   UNCLEAR,
   HARD,
   EASY,
   FAKE,
   SHAM,
   AWFUL
}

Jenis Posting:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents post types.
*/
public enum PostType {
   UNKNOWN, USUAL, INNER_LINK, OUTER_LINK
}

Status Publik Pengguna:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents user public status.
*/
public enum UserPublicStatus {
   UNKNOWN,
   BEGINNER,
   ACTIVE,
   STRONG,
   GRADUATED,
   INTERNSHIP_IN_PROGRESS,
   INTERNSHIP_COMPLETED,
   RESUME_COMPLETED,
   LOOKING_FOR_JOB,
   HAVE_JOB;
}

VisibilityStatus:
package com.github.javarushcommunity.jrtb.javarushclient.dto;

/**
* DTO, which represents visibility status.
*/
public enum VisibilityStatus {
   UNKNOWN,
   RESTRICTED,
   PUBLIC,
   PROTECTED,
   PRIVATE,
   DISABLED,
   DELETED
}
Berdasarkan semua DTO ini, mari kita tulis kelas utama untuk menerima artikel:

Info Posting:

package com.github.javarushcommunity.jrtb.javarushclient.dto;

import lombok.Data;

/**
* DTO, which represents post information.
*/
@Data
public class PostInfo {

   private BaseUserInfo authorInfo;
   private Integer commentsCount;
   private String content;
   private Long createdTime;
   private String description;
   private GroupInfo groupInfo;
   private Integer id;
   private String key;
   private Language language;
   private LikesInfo likesInfo;
   private GroupInfo originalGroupInfo;
   private String pictureUrl;
   private Double rating;
   private Integer ratingCount;
   private String title;
   private PostType type;
   private Long updatedTime;
   private UserDiscussionInfo userDiscussionInfo;
   private Integer views;
   private VisibilityStatus visibilityStatus;

}
Sekarang mari kita buat antarmuka untuk digunakan dan implementasinya. Kita hanya memerlukan satu metode untuk bekerja dengan artikel:

Klien JavaRushPost:

package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;

import java.util.List;

/**
* Client for Javarush Open API corresponds to Posts.
*/
public interface JavaRushPostClient {

   /**
    * Find new posts since lastPostId in provided group.
    *
    * @param groupId provided group ID.
    * @param lastPostId provided last post ID.
    * @return the collection of the new {@link PostInfo}.
    */
   List<PostInfo> findNewPosts(Integer groupId, Integer lastPostId);
}
findNewPosts mengambil dua argumen: ID grup dan ID terakhir artikel yang telah diposting bot. Oleh karena itu, semua artikel yang diterbitkan setelah artikel dengan lastPostId akan dikirimkan . Dan implementasinya:
package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;
import kong.unirest.GenericType;
import kong.unirest.Unirest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class JavaRushPostClientImpl implements JavaRushPostClient {

   private final String javarushApiPostPath;

   public JavaRushPostClientImpl(@Value("${javarush.api.path}") String javarushApi) {
       this.javarushApiPostPath = javarushApi + "/posts";
   }

   @Override
   public List<PostInfo> findNewPosts(Integer groupId, Integer lastPostId) {
       List<PostInfo> lastPostsByGroup = Unirest.get(javarushApiPostPath)
               .queryString("order", "NEW")
               .queryString("groupKid", groupId)
               .queryString("limit", 15)
               .asObject(new GenericType<List<PostInfo>>() {
               }).getBody();
       List<PostInfo> newPosts = new ArrayList<>();
       for (PostInfo post : lastPostsByGroup) {
           if (lastPostId.equals(post.getId())) {
               return newPosts;
           }
           newPosts.add(post);
       }
       return newPosts;
   }
}
Kami menambahkan beberapa filter ke permintaan:
  • order = NEW - agar daftar berisi yang baru terlebih dahulu;
  • groupKid = groupId - cari hanya untuk grup tertentu;
  • limit = 15 — kami membatasi jumlah artikel per permintaan. Frekuensi kami adalah 15-20 menit dan kami berharap selama ini tidak LEBIH dari 15 (!) yang akan ditulis.
Selanjutnya, ketika kami telah menemukan artikel, kami menelusuri daftarnya dan mencari artikel baru. Algoritmenya sederhana dan intuitif. Jika Anda ingin memperbaikinya, tulislah). Mari kita tulis tes sederhana untuk klien ini:
package com.github.javarushcommunity.jrtb.javarushclient;

import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;

import static com.github.javarushcommunity.jrtb.javarushclient.JavaRushGroupClientTest.JAVARUSH_API_PATH;

@DisplayName("Integration-level testing for JavaRushPostClient")
class JavaRushPostClientTest {

   private final JavaRushPostClient postClient = new JavaRushPostClientImpl(JAVARUSH_API_PATH);

   @Test
   public void shouldProperlyGetNew15Posts() {
       //when
       List<PostInfo> newPosts = postClient.findNewPosts(30, 2935);

       //then
       Assertions.assertEquals(15, newPosts.size());
   }
}
Ini adalah tes yang sangat sederhana yang memeriksa apakah ada komunikasi dengan klien atau tidak. Dia menemukan 15 artikel baru di grup proyek Java, karena saya memberinya ID artikel pertama di grup ini, dan sudah ada lebih dari 15... Sudah ada 22! Saya bahkan tidak menyangka jumlahnya akan sebanyak itu. Bagaimana saya bisa mengetahuinya dengan cepat? Apakah menurut Anda dia pergi untuk menghitungnya? Tidak) Saya menggunakan kesombongan dan melihat jumlah artikel untuk kelompok tertentu. Ngomong-ngomong, Anda bisa melihat seperti ini di artikel lain... Dan berapa banyak artikel yang ada di grup ACAK?... Saya akan beri tahu Anda sekarang: ada 1062 artikel! Jumlah yang serius.

Akhir dari bagian pertama

Di sini kami telah menambahkan pekerjaan dengan klien berdasarkan artikel. Kami sudah melakukan segalanya, kali ini menurut saya semuanya harus sederhana dan cepat. Di artikel selanjutnya kita akan menambahkan Spring Scheduler dan menulis FindNewArticleService . Ya, seperti biasa, suka - berlangganan - bunyikan belnya , beri bintang pada proyek kami , tulis komentar, dan beri peringkat artikel! Terima kasih telah membaca - sampai jumpa lagi!

Daftar semua materi dalam seri ini ada di awal artikel ini.

Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION