Retry to Submit to Reddit a Post Without Enough Traction – 重新尝试向Reddit提交一个没有足够吸引力的帖子

最后修改: 2015年 5月 31日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Posting to Reddit is a crap shoot. One post may do great and get a whole lot of attention while another, maybe better post will get no love at all. What about keeping an eye on these posts early on and – if they’re not getting enough traction – deleting them quickly and resubmitting them.

在Reddit上发帖是一件很糟糕的事情。一个帖子可能做得很好,得到了大量的关注,而另一个也许更好的帖子却根本没有得到任何关注。如果在早期就关注这些帖子,并且–如果它们没有得到足够的牵引力–迅速删除它们并重新提交它们,那会怎么样?

In this quick article we’re continuing the Reddit case study by implementing an interesting functionality – delete and resubmit a post if it’s not getting enough attention immediatly.

在这篇快速文章中,我们将继续Reddit案例研究,实现一个有趣的功能–如果一个帖子没有立即得到足够的关注,就删除并重新提交

The simple goal is to allow the user to configure how many votes on Reddit are enough to consider the Post is getting enough traction to leave it up – inside a certain time interval.

简单的目标是允许用户配置在Reddit上有多少票数足以认为该帖子得到了足够的牵引力,可以让它继续存在–在一定的时间间隔内。

2. More Reddit Permissions

2.更多的Reddit权限

First – we’ll need to ask for additional permissions from the Reddit API – specifically we need to edit posts.

首先–我们需要从Reddit API请求额外的权限–特别是我们需要编辑帖子。

So we’ll add “edit” scope to our Reddit Resource:

所以我们要在我们的Reddit Resource上添加”edit“范围。

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

3. The Entity and the Repository

3.实体和存储库

Now – let’s add the extra information in our Post entity:

现在–让我们在我们的Post实体中添加额外信息。

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

The fields:

田地。

  • redditID: Post ID on Reddit, to be used when checking the score and when deleting the post
  • noOfAttempts: Maximum number of resubmit tries (delete Post and resubmit it)
  • timeInterval: Time interval to check if the post is getting enough traction
  • minScoreRequired: Minimum score required to consider it successful enough to leave up

Next – let’s add some new operations into our PostRepository interface – in order to easily retrieve posts when we need to check check them:

接下来–让我们在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. A New Scheduled Task

4.一个新的预定任务

Now – let’s define a new task – the re-submit task – into the scheduler:

现在,让我们在调度器中定义一个新的任务–重新提交任务。

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

Each few minutes, this is simply iterating over the posts that are still in play – and, if they’re not getting enough traction, it deletes them and submits them again.

每隔几分钟,这只是对仍在进行的帖子进行迭代–如果它们没有得到足够的牵引力,就会删除它们并重新提交。

And here is checkAndReSubmit() method:

这里是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);
}

We’ll also need to keep track of the redditID when first submitting it to Reddit:

在第一次提交给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);
        ...
}

The logic here is also quite simple – we just save the id and decrease the number of attempts counter.

这里的逻辑也很简单–我们只需保存ID并减少尝试次数的计数器。

5. Get Reddit Post Score

5.获得Reddit帖子得分

Now – let’s see how we can get the current score of the post from 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;
}

Note that:

请注意,。

  • We need the “read” scope when retrieving the post information from Reddit
  • We add “t3_” to the reddit id to obtain full name of the post

6. Delete the Reddit Post

6.删除Reddit帖子

Next – let’s see how delete Reddit post using its id:

下一步–让我们看看如何使用其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. The RedditController

7、RedditController

Now – let’s add the new info to the controller:

现在–让我们把新的信息添加到控制器中。

@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. The UI – Configure the Rules

8.用户界面 – 配置规则

Finally – let’s modify our very simple schedule form to add resubmit the new settings:

最后–让我们修改我们非常简单的日程表,添加重新提交的新设置。

<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. Conclusion

9.结论

We’re continuing to improve what this simple app can do – we can now post to Reddit and – if the post isn’t getting enough traction quickly – we can have the system delete it and re-post to give it a better chance of performing.

我们正在继续改进这个简单的应用程序的功能–我们现在可以在Reddit上发帖,而且–如果帖子没有迅速得到足够的牵引力–我们可以让系统删除它,然后重新发帖,以使它有更好的表现机会。