Рубрики
Без рубрики

Повторите попытку Отправить в Reddit сообщение Без достаточной тяги

Новая функция в приложении case-study Reddit – удаление и повторная попытка публикации, которая не набирает обороты на ранней стадии.

Автор оригинала: baeldung.

1. Обзор

Публикация в Reddit-это дерьмовая съемка. Один пост может быть отличным и привлечь много внимания, в то время как другой, возможно, лучший пост вообще не получит любви. Как насчет того, чтобы следить за этими сообщениями на ранней стадии и – если они не получают достаточной поддержки – быстро удалять их и повторно отправлять .

В этой краткой статье мы продолжаем тематическое исследование Reddit , реализуя интересную функциональность – удаляем и повторно отправляем сообщение, если оно не получает достаточного внимания немедленно .

Простая цель состоит в том, чтобы позволить пользователю настроить, сколько голосов на Reddit достаточно, чтобы считать, что пост набирает достаточно оборотов, чтобы оставить его в течение определенного промежутка времени.

2. Дополнительные разрешения Reddit

Во – первых, нам нужно запросить дополнительные разрешения из API Reddit – в частности, нам нужно редактировать сообщения.

Поэтому мы добавим область ” edit ” в наш Reddit Ресурс :

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

3. Сущность и Репозиторий

Теперь – давайте добавим дополнительную информацию в наш Пост объект:

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

Поля:

  • reddit ID : Идентификатор записи на Reddit, который будет использоваться при проверке оценки и при удалении записи
  • нет попыток : Максимальное количество попыток повторной отправки (удалить сообщение и повторно отправить его)
  • интервал времени : Интервал времени, чтобы проверить, получает ли сообщение достаточную тягу
  • требуется минимальный балл : Минимальный балл, необходимый для того, чтобы считать его достаточно успешным, чтобы уйти

Далее – давайте добавим некоторые новые операции в наш интерфейс PostRepository – чтобы легко извлекать сообщения, когда нам нужно их проверить:

public interface PostRepository extends JpaRepository {

    List findBySubmissionDateBeforeAndIsSent(Date date, boolean sent);

    List findByUser(User user);

    List findByRedditIDNotNullAndNoOfAttemptsGreaterThan(int attempts);
}

4. Новая Запланированная Задача

Теперь давайте определим новую задачу – задачу повторной отправки – в планировщик:

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

Каждые несколько минут это просто повторение сообщений, которые все еще находятся в игре, и, если они не получают достаточной тяги, он удаляет их и отправляет снова.

А вот проверить и отправить() метод:

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 при первой отправке его в Reddit:

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);
        ...
}

Логика здесь тоже довольно проста – мы просто сохраняем идентификатор и уменьшаем счетчик попыток.

5. Получите оценку Reddit Post

Теперь давайте посмотрим, как мы можем получить текущую оценку поста от 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;
}

Обратите внимание, что:

  • Нам нужна область ” read ” при извлечении информации о публикации из Reddit
  • Мы добавляем ” t3_ ” к идентификатору reddit, чтобы получить полное имя поста

6. Удалите сообщение Reddit

Далее – давайте посмотрим, как удалить сообщение Reddit, используя его идентификатор:

private void deletePost(String redditId) {
    MultiValueMap param = new LinkedMultiValueMap();
    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 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. Пользовательский интерфейс – Настройка правил

Наконец, давайте изменим нашу очень простую форму расписания, чтобы добавить повторную отправку новых настроек:



 






9. Заключение

Мы продолжаем улучшать то, что может сделать это простое приложение – теперь мы можем публиковать сообщения в Reddit, и – если сообщение не набирает достаточной скорости – мы можем попросить систему удалить его и повторно опубликовать, чтобы дать ему больше шансов на успех.