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() { Listsubmitted = 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) { MultiValueMapparam = 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 MapformParams) 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, и – если сообщение не набирает достаточной скорости – мы можем попросить систему удалить его и повторно опубликовать, чтобы дать ему больше шансов на успех.