Tweetez StackExchange Questions avec Spring Social

1. Introduction

Ceci est le troisième et dernier article sur un petit projet parallèle - un robot qui tweete automatiquement les questions de divers Q

Le lien:/tweeting-stackexchange-with-spring-social-part-1/[premier article]traite de la création d’un client simple pour l’API StackExchange REST. Dans le lien:/spring social twitter__setup[deuxième article], nous avons défini l’interaction avec Twitter à l’aide de Spring Social.

Cet article décrit la dernière partie de l’implémentation - la partie responsable de l’interaction entre le client Stackexchange et le TwitterTemplate .

2. Le service Tweet Stackexchange

L’interaction entre le client Stackexchange - exposant les questions brutes, et le TwitterTemplate - entièrement configuré et capable de tweeter - est un service très simple - le TweetStackexchangeService . L’API publiée par ceci est:

public void tweetTopQuestionBySite(String site, String twitterAccount){ ... }
public void tweetTopQuestionBySiteAndTag(String site, String twitterAccount, String tag){ ... }

La fonctionnalité est simple: ces API continueront à lire les questions de l’API Stackexchange REST (par le biais du client), jusqu’à ce qu’il soit constaté que n’a pas été tweeté avant sur ce compte particulier.

Lorsque cette question est trouvée, elle est tweetée via le TwitterTemplate correspondant à ce compte et une entité très simple Question est enregistrée localement. Cette entité ne stocke que l’id de la question et le compte Twitter sur lequel elle a été tweetée.

  • Par exemple ** la question suivante:

L’entité Question contient simplement:

  • le id de la question - 4596351 dans ce cas

  • le compte Twitter sur lequel la question a été tweetée -

SpringAtSO le site Stackexcange ** d’où provient la question -

Stackoverflow

Nous devons garder cette information à jour pour savoir quelles questions ont déjà été tweetées et lesquelles ne l’ont pas été.

3. Le planificateur

Le planificateur utilise les fonctionnalités de tâches planifiées de Spring - elles sont activées via la configuration Java:

@Configuration
@EnableScheduling
public class ContextConfig {
  //}

Le planificateur actuel est relativement simple:

@Component
@Profile(SpringProfileUtil.DEPLOYED)
public class TweetStackexchangeScheduler {

   @Autowired
   private TweetStackexchangeService service;

  //API

   @Scheduled(cron = "0 0 1,5 **  **  ** ")
   public void tweetStackExchangeTopQuestion() throws JsonProcessingException, IOException {
      service.tweetTopQuestionBySiteAndTag("StackOverflow", Tag.clojure.name(), "BestClojure", 1);
      String randomSite = StackexchangeUtil.pickOne("SuperUser", "StackOverflow");
      service.tweetTopQuestionBySiteAndTag(randomSite, Tag.bash.name(), "BestBash", 1);
   }
}

Deux opérations de tweet sont configurées ci-dessus - un tweets de questions StackOverflow portant la mention «clojure» sur le compte Best Of Clojure .

L’autre opération tweetait des questions marquées «bash» - et parce que ce genre de questions apparaît en fait sur plusieurs sites du réseau Stackexchange:

StackOverflow , SuperUser et AskUbuntu Il existe tout d’abord un processus de sélection rapide pour choisir l’un de ces sites, après quoi la question est tweetée.

Enfin, le travail cron est programmé pour s’exécuter à 1 heure et à 5 heures chaque jour.

4. Installer

Ceci étant un projet animalier, il a démarré avec une structure de base de données très simple - elle est toujours aussi simple à présent, mais c’était encore plus vrai. L’un des objectifs principaux était donc de pouvoir modifier facilement la structure de la base de données - il existe bien sûr several tools pour les migrations de bases de données, mais ils sont tous excessifs pour un projet si simple.

J’ai donc décidé de conserver les données de configuration dans a un format de texte simple - qui sera mis à jour de manière semi-automatique.

L’installation comporte deux étapes principales:

  • les identifiants des questions tweetées sur chaque compte twitter sont récupérés

et stocké dans un fichier texte ** le schéma de base de données est abandonné et l’application redémarrée - ceci

créera à nouveau le schéma et configurera toutes les données du fichier texte dans la nouvelle base de données

4.1. Les données brutes d’installation

Le processus de récupération des données de la base de données existante est assez simple avec JDBC. nous définissons d’abord un RowMapper:

class TweetRowMapper implements RowMapper<String> {
   private Map<String, List<Long>> accountToQuestions;

   public TweetRowMapper(Map<String, List<Long>> accountToQuestions) {
      super();
      this.accountToQuestions = accountToQuestions;
   }

   public String mapRow(ResultSet rs, int line) throws SQLException {
      String questionIdAsString = rs.getString("question__id");
      long questionId = Long.parseLong(questionIdAsString);
      String account = rs.getString("account");

      if (accountToQuestions.get(account) == null) {
         accountToQuestions.put(account, Lists.<Long> newArrayList());
      }
      accountToQuestions.get(account).add(questionId);
      return "";
   }
}

Cela construira une liste de questions pour chaque compte Twitter.

Ensuite, nous allons l’utiliser dans un simple test:

@Test
public void whenQuestionsAreRetrievedFromTheDB__thenNoExceptions() {
   Map<String, List<Long>> accountToQuestionsMap = Maps.newHashMap();
   jdbcTemplate.query
      ("SELECT **  FROM question__tweet;", new TweetRowMapper(accountToQuestionsMap));

   for (String accountName : accountToQuestionsMap.keySet()) {
      System.out.println
         (accountName + "=" + valuesAsCsv(accountToQuestionsMap.get(accountName)));
   }
}

Après avoir récupéré les questions d’un compte, le test les listera simplement. par exemple:

SpringAtSO=3652090,1079114,5908466,...

4.2. Restauration des données de configuration

Les lignes de données générées par l’étape précédente sont stockées dans a setup.properties file qui est mis à la disposition de Spring. :

@Configuration
@PropertySource({ "classpath:setup.properties" })
public class PersistenceJPAConfig {
  //}

Lorsque l’application démarre, le processus d’installation est effectué. Ce processus simple utilise un Spring ApplicationListener, qui écoute sur un ContextRefreshedEvent :

@Component
public class StackexchangeSetup implements ApplicationListener<ContextRefreshedEvent> {
    private boolean setupDone;

    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (!setupDone) {
            recreateAllQuestionsOnAllTwitterAccounts();
            setupDone = true;
        }
    }
}

Enfin, les questions sont extraites du fichier setup.properties et recréées:

private void recreateAllQuestionsOnTwitterAccount(String twitterAccount) {
   String tweetedQuestions = env.getProperty(twitterAccount.name();
   String[]questionIds = tweetedQuestions.split(",");
   recreateQuestions(questionIds, twitterAccount);
}
void recreateQuestions(String[]questionIds, String twitterAccount) {
   List<String> stackSitesForTwitterAccount = twitterAccountToStackSites(twitterAccount);
   String site = stackSitesForTwitterAccount.get(0);
   for (String questionId : questionIds) {
      QuestionTweet questionTweet = new QuestionTweet(questionId, twitterAccount, site);
      questionTweetDao.save(questionTweet);
   }
}

Ce processus simple permet de mettre à jour facilement la structure de la base de données - étant donné que les données sont entièrement effacées et entièrement recréées, il n’est pas nécessaire de procéder à une migration réelle.

5. Liste complète des comptes

La liste complète des comptes Twitter est:

StackOverflow JavaTopSO - Java ** questions de

StackOverflow RESTDaily - REST ** questions de

StackOverflow BestJPA - JPA ** questions de

StackOverflow MavenFact - Maven ** questions de

StackOverflow BestGit - Git ** questions de

StackOverflow AskUbuntuBest - AskUbuntu ** meilleur

questions générales (tous les sujets) ServerFaultBest - ServerFault **

meilleures questions (tous les sujets) BestBash - meilleures questions Bash ** de

StackOverflow, ServerFault et AskUbuntu ** ClojureFact - questions clojures

StackOverflow ** ScalaFact - Questions sur Scala de

StackOverflow ** EclipseFacts - Questions sur Eclipse

de StackOverflow ** jQueryDaily - questions jQuery de

StackOverflow ** BestAlgorithms - algorithme

questions de StackOverflow

Deux tweets par jour sont créés sur chacun de ces comptes, avec les questions les mieux notées sur leur sujet spécifique.

6. Conclusion

Ce troisième article termine la série sur l’intégration avec StackOverflow et d’autres sites StackExchange afin de récupérer des questions via leur API REST, et sur l’intégration avec Twitter et Spring Social pour répondre à ces questions via Twitter. Une direction potentielle à explorer est la même chose avec Google Plus - en utilisant probablement Pages, pas des comptes.

  • 14 comptes Twitter ** sont opérationnels à la suite de ce projet - se concentrant sur divers sujets et produisant un contenu de faible volume et, espérons-le, de haute qualité (des idées pour d’autres tags qui méritent leur propre compte Twitter sont les bienvenues dans les commentaires).