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.