知識庫 / Spring RSS 訂閱

重新提交帖子至Reddit,以期獲得足夠的關注度

REST,Spring
HongKong
4
04:00 AM · Dec 06 ,2025

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. The Entity and the Repository

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

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

字段:

  • redditID:在 Reddit 上查看帖子得分和刪除帖子的使用標識符
  • 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”範圍
  • 我們通過在Reddit ID中添加“t3_”來獲取帖子的全名

刪除 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. 用户界面 – 配置規則

最後,讓我們修改我們的非常簡單的日程表表單,以添加重新提交新設置:

<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,並且—如果發佈內容沒有迅速獲得足夠的關注—系統可以刪除該內容並重新發布,以提高其表現的機會。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.