1. 概要

Redditへの投稿はくだらないことです。1つの投稿はうまく機能し、多くの注目を集める可能性がありますが、別の投稿は、まったく愛されないかもしれません。 これらの投稿を早い段階で監視し、十分な牽引力が得られない場合は、すぐに削除して再送信するのはどうでしょうか。

この簡単な記事では、興味深い機能を実装することでRedditのケーススタディを続けています。

単純な目標は、特定の時間間隔内で、投稿がそれを残すのに十分な牽引力を得ていると見なすのに十分なRedditへの投票数をユーザーが構成できるようにすることです。

2. その他のReddit権限

まず、Reddit APIから追加の権限を要求する必要があります–具体的には投稿を編集する必要があります。

そこで、Reddit Resourceに「edit」スコープを追加します。

@Bean
public OAuth2ProtectedResourceDetails reddit() {
    AuthorizationCodeResourceDetails details = 
      new AuthorizationCodeResourceDetails();
    details.setScope(Arrays.asList("identity", "read", "submit", "edit"));
    ...
}

3. エンティティとリポジトリ

次に、Postエンティティに追加情報を追加しましょう。

@Entity
public class Post {
    ...
    private String redditID;
    private int noOfAttempts;
    private int timeInterval;
    private int minScoreRequired;
}

フィールド:

  • redditID :Redditの投稿ID。スコアを確認するときや投稿を削除するときに使用されます
  • noOfAttempts :再送信の最大試行回数(投稿を削除して再送信)
  • timeInterval :投稿が十分な牽引力を得ているかどうかを確認する時間間隔
  • minScoreRequired :それが成功したと見なすために必要な最小スコア

次に、 PostRepository インターフェースにいくつかの新しい操作を追加して、チェックが必要なときに投稿を簡単に取得できるようにします。

public interface PostRepository extends JpaRepository<Post, Long> {

    List<Post> findBySubmissionDateBeforeAndIsSent(Date date, boolean sent);

    List<Post> findByUser(User user);

    List<Post> findByRedditIDNotNullAndNoOfAttemptsGreaterThan(int attempts);
}

4. 新しいスケジュールされたタスク

次に、新しいタスク(再送信タスク)をスケジューラーに定義しましょう。

@Scheduled(fixedRate = 3 * 60 * 1000)
public void checkAndReSubmitPosts() {
    List<Post> submitted = 
      postReopsitory.findByRedditIDNotNullAndNoOfAttemptsGreaterThan(0);
    for (Post post : submitted) {
        checkAndReSubmit(post);
    }
}

数分ごとに、これはまだプレイ中の投稿を繰り返し処理するだけです。十分なトラクションが得られない場合は、投稿を削除して再送信します。

そして、これが checkAndReSubmit()メソッドです。

private void checkAndReSubmit(Post post) {
    try {
        checkAndReSubmitInternal(post);
    } catch (final Exception e) {
        logger.error("Error occurred while check post " + post.toString(), e);
    }
}
private void checkAndReSubmitInternal(Post post) {
    if (didIntervalPassed(post.getSubmissionDate(), post.getTimeInterval())) {
        int score = getPostScore(post.getRedditID());
        if (score < post.getMinScoreRequired()) {
            deletePost(post.getRedditID());
            resetPost(post);
        } else {
            post.setNoOfAttempts(0);
            postReopsitory.save(post);
        }
    }
}
private boolean didIntervalPassed(Date submissonDate, int postInterval) {
    long currentTime = new Date().getTime();
    long interval = currentTime - submissonDate.getTime();
    long intervalInMinutes = TimeUnit.MINUTES.convert(interval, TimeUnit.MILLISECONDS);
    return intervalInMinutes > postInterval;
}
private void resetPost(Post post) {
    long time = new Date().getTime();
    time += TimeUnit.MILLISECONDS.convert(post.getTimeInterval(), TimeUnit.MINUTES);
    post.setRedditID(null);
    post.setSubmissionDate(new Date(time));
    post.setSent(false);
    post.setSubmissionResponse("Not sent yet");
    postReopsitory.save(post);
}

また、最初にRedditに送信するときに、redditIDを追跡する必要があります。

private void submitPostInternal(Post post) {
    ...
    JsonNode node = redditRestTemplate.postForObject(
      "https://oauth.reddit.com/api/submit", param, JsonNode.class);
    JsonNode errorNode = node.get("json").get("errors").get(0);
    if (errorNode == null) {
        post.setRedditID(node.get("json").get("data").get("id").asText());
        post.setNoOfAttempts(post.getNoOfAttempts() - 1);
        ...
}

ここでのロジックも非常に単純です。IDを保存し、試行回数カウンターを減らすだけです。

5. Reddit投稿スコアを取得する

では、Redditから投稿の現在のスコアを取得する方法を見てみましょう。

private int getPostScore(String redditId) {
    JsonNode node = redditRestTemplate.getForObject(
      "https://oauth.reddit.com/api/info?id=t3_" + redditId, JsonNode.class);
    int score = node.get("data").get("children").get(0).get("data").get("score").asInt();
    return score;
}

ご了承ください:

  • Redditから投稿情報を取得するときは、「read」スコープが必要です
  • 投稿のフルネームを取得するために、redditIDに「t3_」を追加します

6. Reddit投稿を削除する

次へ– IDを使用してRedditの投稿を削除する方法を見てみましょう:

private void deletePost(String redditId) {
    MultiValueMap<String, String> param = new LinkedMultiValueMap<String, String>();
    param.add("id", "t3_" + redditId);
    redditRestTemplate.postForObject(
      "https://oauth.reddit.com/api/del.json", param, JsonNode.class);
}

7. RedditController

次に、新しい情報をコントローラーに追加しましょう。

@RequestMapping(value = "/schedule", method = RequestMethod.POST)
public String schedule(Model model, 
  @RequestParam Map<String, String> formParams) throws ParseException {
    Post post = new Post();
    post.setTitle(formParams.get("title"));
    post.setSubreddit(formParams.get("sr"));
    post.setUrl(formParams.get("url"));
    post.setNoOfAttempts(Integer.parseInt(formParams.get("attempt")));
    post.setTimeInterval(Integer.parseInt(formParams.get("interval")));
    post.setMinScoreRequired(Integer.parseInt(formParams.get("score")));
    ....
}

8. UI –ルールを構成する

最後に、非常に単純なスケジュールフォームを変更して、新しい設定を再送信します。

<label class="col-sm-3">Resubmit Settings</label>

<label>Number of Attempts</label> 
<select name="attempt">
    <option value="0" selected>None</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
</select>

<label>Time interval</label>
<select name="interval">
    <option value="0" selected >None</option>
    <option value="45">45 minutes</option>
    <option value="60">1 hour</option>
    <option value="120">2 hours</option>
</select>

<label>Min score</label>
<input type="number"value="0" name="score" required/>

9. 結論

このシンプルなアプリでできることを継続的に改善しています。Redditに投稿できるようになりました。投稿がすぐに十分な牽引力を得られない場合は、システムに削除して再投稿して、より良いチャンスを与えることができます。実行します。