親愛なる皆さん、こんにちは。私たちは、プロジェクトの MVP である JavaRush Telegram Bot になるという目標に一歩ずつ近づいています。前回の記事で述べたように、残っているタスクは 5 つだけです。今日はそのうちの 2 つを取り上げます。 繰り返しになりますが、このプロジェクトはここで終わるわけではありません。このプロジェクトをどのように発展させるべきか、どのような新しいことを追加できるか、何が改善できるかについて、私にはまだたくさんのアイデアやビジョンがあります。MVP の前に、リファクタリングのトピック、つまり機能を変更せずにコードの品質を向上させることについて別の記事を作成する予定です。その頃にはプロジェクト全体が見えてきて、どこを改善できるかが明確になるでしょう。私たちの場合、多くのテストが記述されているため、機能が破壊されることは最大限に保護されます。また、私たちが望んでいたものと最終的に得たものについての振り返りも書きます。これは非常に便利です。6 か月前にすべてがどの程度正しく認識されていたかを見てみましょう。少なくともこれは私にとって非常に興味深いです。手動テスターとして試してみたい人は、私たちに手紙を書いてください。協力します。一緒にこのプロジェクトをより良いものにしていきましょう!6 か月前に説明した 2 つのタスク、 JRTB-8とJRTB-9です。これらのタスクのために何を実装する必要があるかを検討し始めたところ、コマンドの起動に関してはすべてがすでに準備が整っていることに気付きました。それは起こります...) ここで、 StartCommand、実行メソッドを確認できます。
「購読」、「ベルを鳴らして」 、プロジェクトに星を付け、コメントを書いて記事を評価してください。 読んでくださった皆様、ありがとうございました。またお会いしましょう!
@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);
}
ここでロジックが機能します。データベースに chatId によるそのようなユーザーがすでに存在する場合、そのユーザーに対して active = true フィールドを設定するだけです。そのようなユーザーが存在しない場合は、新しいユーザーを作成します。StopCommandの/stopコマンドも同様です。
@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);
}
このコマンドを呼び出すと、ユーザーに対して active = false フィールドのみが設定されることがわかります。これですべてです。ユーザーのサブスクリプションは存続し、ユーザーが再びボットとのチャットをアクティブ化することを決定したときに待機します。そして、タスクはすでに完了しており、閉じることができるようです。しかし、そこにはありませんでした。最も重要なタスクは、サブスクリプションの新しい記事に関するアラートを作成することです。ここで、これらのタスクが完全に更新され、完了します。つまり、新しい記事の通知を実装するまでは閉じることができません。したがって、タスク JRTB-4 (20 分ごとのチェックと新しい記事に関する通知の作成) を処理しましょう。 友達!プロジェクトの新しいコードがいつリリースされるかをすぐに知りたいですか? 新しい記事はいつ公開されますか? 私のTGチャンネルに参加してください。そこでは、私の記事、考え、オープンソース開発をまとめています。
JRTB-4を実装します
このタスクの一環として行う必要があることは次のとおりです。-
データベース内でサブスクリプションを持っているすべてのグループに定期的にアクセスし、記事を出版日順に並べ替えて、最後の出版物の ID が GroupSub の値と一致するかどうかを確認するジョブを作成します。一致しない場合は、前回以降に公開された記事の数を正確に把握する必要があります。GroupSub7 の last_article_id を現在の状態に更新します。
-
公開された記事のリストを見つけると、これらのグループのアクティブなユーザーをすべて見つけて、新しい記事に関する通知を送信します。
/api/1.0/rest/posts フィルターで投稿を取得する
このご要望に沿って対応させていただきます。その中で何が必要なのでしょうか?特定のグループに属する記事のリストを取得します。公開日順に並べ替える必要があります。このようにして、過去 15 件の記事を取得し、データベースのlastArticleIdに基づいて新しい出版物が発行されたかどうかを確認できます。存在する場合は、処理してユーザーに送信するためにそれらを渡します。したがって、 JavaRushPostClientを記述する必要があります。
JavaRushPostClientを書きます
ここでは、API で渡されたすべてのリクエストをカバーしようとはせず、必要なリクエストのみを作成します。これにより、次の 2 つの目標を同時に達成できます。-
アプリケーションの作成プロセスを高速化します。
-
この作業は、コミュニティを支援したいと考え、開発者として自分自身を試してみようと決心した人たちに任せます。MVP の後に完了できるタスクを作成します。
基本ユーザー情報:
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;
}
言語:
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
}
好きな情報:
package com.github.javarushcommunity.jrtb.javarushclient.dto;
/**
* DTO, which represents like's information.
*/
public class LikesInfo {
private Integer count;
private LikeStatus status;
}
いいねステータス:
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
}
投稿タイプ:
package com.github.javarushcommunity.jrtb.javarushclient.dto;
/**
* DTO, which represents post types.
*/
public enum PostType {
UNKNOWN, USUAL, INNER_LINK, OUTER_LINK
}
ユーザーパブリックステータス:
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
}
これらすべての DTO に基づいて、記事を受け取るメイン クラスを作成しましょう。
投稿情報:
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;
}
次に、操作するインターフェイスとその実装を作成しましょう。記事を操作するために必要なメソッドは 1 つだけです。
JavaRushPostClient:
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 は2 つの引数を取ります。グループ ID と、ボットがすでに投稿した記事の最後の ID です。したがって、 lastPostIdの記事より後に公開された記事はすべて送信されます。そしてその実装:
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;
}
}
リクエストにいくつかのフィルターを追加します。
- order = NEW - リストに新しいものが最初に含まれるようにします。
- groupKid = groupId - 特定のグループのみを検索します。
- 制限 = 15 — リクエストごとの記事数を制限します。頻度は 15 ~ 20 分で、この時間内に書き込まれるのは 15 (!) 未満になると予想されます。
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());
}
}
これは、クライアントとの通信があるかどうかを確認する非常に簡単なテストです。彼は、Java プロジェクト グループで 15 件の新しい記事を見つけました。私がこのグループの最初の記事の ID を彼に与えたので、すでに 15 件以上の記事が存在しています...すでに 22 件あります。こんなにたくさんあるとは思いもしませんでした。どうすればすぐにわかったのでしょうか?彼は数を数えに行ったと思いますか? いや)私はあるグループの記事数を調べてみました。ちなみに、他の記事でもこのように見ることができます...そして、RANDOM グループには記事が何件ありますか?...今言っておきますが、1062 件あります。深刻な量。
GO TO FULL VERSION