1. 概述
發佈到Reddit是一場投機行為。
一篇帖子可能大受歡迎並獲得大量關注,而另一篇可能更好的帖子卻一無所獲。 密切關注這些帖子,並在它們沒有獲得足夠的關注時,迅速刪除並重新提交。
在本文中,我們將繼續研究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 上用於檢查分數和刪除帖子的 Post ID
- noOfAttempts :最大重提交嘗試次數(刪除並重新提交 Post)
- 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("檢查帖子 " + 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("尚未發送");
postReopsitory.save(post);
}
我們還需要在首次提交時跟蹤 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;
}
請注意:
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);
}
8. 用户界面 – 配置規則
最後,讓我們修改我們的非常簡單的日程表表單,以添加重新提交新設置:
<label class="col-sm-3">重新提交設置</label>
<label>嘗試次數</label>
<select name="attempt">
<option value="0" selected>無</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<label>時間間隔</label>
<select name="interval">
<option value="0" selected >無</option>
<option value="45">45 分鐘</option>
<option value="60">1 小時</option>
<option value="120">2 小時</option>
</select>
<label>最小分數</label>
<input type="number"value="0" name="score" required/>
</code>
9. 結論
我們正在不斷改進這個簡單的應用程序的功能——現在我們可以將內容發佈到Reddit,並且——如果內容發佈後沒有迅速獲得足夠的關注——系統可以刪除並重新發布以提高其表現的機會。