Tente novamente enviar para reddit uma postagem sem tração suficiente

Tente novamente enviar para reddit uma postagem sem tração suficiente

1. Visão geral

Posting to Reddit is a crap shoot. Uma postagem pode funcionar muito bem e receber muita atenção, enquanto outra, talvez uma postagem melhor, não receba nenhum amor. Que tal ficar de olho nessas postagens desde o início e - se elas não estiverem recebendo tração suficiente -deleting them quickly and resubmitting them.

Neste artigo rápido, continuamosthe Reddit case study implementando uma funcionalidade interessante -delete and resubmit a post if it’s not getting enough attention immediatly.

O objetivo simples é permitir que o usuário configure quantos votos no Reddit são suficientes para considerar que o Post está recebendo tração suficiente para deixá-lo em paz - dentro de um determinado intervalo de tempo.

2. Mais permissões do Reddit

Primeiro - precisamosask for additional permissions da API do Reddit - especificamente, precisamos editar as postagens.

Então, vamos adicionar o escopo “edit” ao nosso RedditResource:

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

3. A Entidade e o Repositório

Agora - vamos adicionar as informações extras em nossa entidadePost:

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

Os campos:

  • redditID: ID da postagem no Reddit, para ser usado ao verificar a pontuação e ao excluir a postagem

  • noOfAttempts: Número máximo de tentativas de reenvio (exclua a postagem e reenvie)

  • timeInterval: intervalo de tempo para verificar se o poste está recebendo tração suficiente

  • minScoreRequired: pontuação mínima necessária para considerá-lo bem-sucedido o suficiente para sair

A seguir - vamos adicionar algumas novas operações em nossa interfacePostRepository - a fim de recuperar facilmente as postagens quando precisarmos verificá-las:

public interface PostRepository extends JpaRepository {

    List findBySubmissionDateBeforeAndIsSent(Date date, boolean sent);

    List findByUser(User user);

    List findByRedditIDNotNullAndNoOfAttemptsGreaterThan(int attempts);
}

4. Uma nova tarefa agendada

Agora - vamos definir uma nova tarefa - a tarefa de reenvio - no agendador:

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

A cada poucos minutos, isso é simplesmente iterar sobre as postagens que ainda estão em jogo - e, se elas não estiverem recebendo tração suficiente, ele as exclui e as envia novamente.

E aqui está o métodocheckAndReSubmit():

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

Também precisaremos acompanhar oredditID ao enviá-lo pela primeira vez para o 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);
        ...
}

A lógica aqui também é bastante simples - apenas salvamos o ID e diminuímos o contador de número de tentativas.

5. Obter Reddit Post Score

Agora - vamos ver como podemos obter a pontuação atual da postagem do 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;
}

Observe que:

  • Precisamos do escopo “read” ao recuperar as informações de postagem do Reddit

  • Adicionamos “t3_” ao id do reddit para obterfull name da postagem

6. Excluir o post do Reddit

A seguir - vamos ver como excluir a postagem do Reddit usando seu id:

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. ORedditController

Agora - vamos adicionar as novas informações ao controlador:

@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. A IU - Configurar as Regras

Finalmente - vamos modificar nosso formulário de programação muito simples para adicionar reenviar as novas configurações:










9. Conclusão

Continuamos aprimorando o que este aplicativo simples pode fazer - agora podemos postar no Reddit e - se a postagem não estiver ganhando força o suficiente rapidamente - podemos fazer com que o sistema o exclua e volte a postar para dar a ele uma chance melhor de desempenho.