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上发帖,而且–如果帖子没有迅速得到足够的牵引力–我们可以让系统删除它,然后重新发帖,以使它有更好的表现机会。