1. Einführung
Dies ist der dritte und letzte Artikel über ein kleines Nebenprojekt - ein Bot, der automatisch Fragen von verschiedenen Stack & Exchange-Websites für Fragen und Antworten zu speziellen Konten twittert (vollständige Liste am Ende des Artikels).
Der Link:/tweeting-stackexchange-with-spring-social-part-1/[erster Artikel]befasste sich mit dem Erstellen eines simple client für die StackExchange-REST-API. Im Link:/spring social twitter__setup[zweiter Artikel]haben wir die Interaktion mit Twitter mithilfe von Spring Social eingerichtet.
In diesem Artikel wird der letzte Teil der Implementierung beschrieben - der verantwortliche Teil für die Interaktion zwischen dem Stackexchange-Client und der TwitterTemplate .
2. Der Tweet Stackexchange Service
Die Interaktion zwischen dem Stackexchange Client - der die rohen Fragen offenlegt - und dem TwitterTemplate - vollständig eingerichtet und in der Lage zu tweeten - ist ein sehr einfacher Dienst - der TweetStackexchangeService . Die hier veröffentlichte API lautet:
public void tweetTopQuestionBySite(String site, String twitterAccount){ ... }
public void tweetTopQuestionBySiteAndTag(String site, String twitterAccount, String tag){ ... }
Die Funktionalität ist einfach: Diese APIs lesen immer wieder Fragen aus der Stackexchange-REST-API (über den Client), bis festgestellt wird, dass vor diesem Konto noch nicht getwittert wurde.
Wenn diese Frage gefunden wird, wird sie über das diesem Konto entsprechende TwitterTemplate ** getwittert, und eine sehr einfache Question -Entität wird lokal gespeichert. Diese Entität speichert nur die ID der Frage und des Twitter-Kontos, auf dem sie getwittert wurde.
-
Zum Beispiel ** folgende Frage:
https://twitter.com/SpringTip/status/326561270604103680 (@wurde tweeted]]im Konto SpringTip .
Die Entität Frage enthält einfach:
-
die ID der Frage - 4596351 in diesem Fall
-
das Twitter-Konto , auf dem die Frage getwittert wurde -
SpringAtSO die Stackexcange Site ** , von der die Frage stammt -
Paketüberfluss
Wir müssen diese Informationen nachverfolgen, damit wir wissen, welche Fragen bereits getwittert wurden und welche nicht.
3. Der Scheduler
Der Scheduler nutzt die geplanten Task-Funktionen von Spring - diese werden über die Java-Konfiguration aktiviert:
@Configuration
@EnableScheduling
public class ContextConfig {
//}
Der eigentliche Scheduler ist relativ einfach:
@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);
}
}
Es gibt zwei oben konfigurierte Tweet-Operationen - ein Tweets aus StackOverflow-Fragen, die auf dem https://twitter.com/ClojureFact [Best Of Clojure-Twitter-Konto mit „clojure“ gekennzeichnet sind.
Die andere Operation twittert Fragen, die mit „bash“ gekennzeichnet sind - und da diese Fragen tatsächlich auf mehreren Websites des Stackexchange-Netzwerks angezeigt werden:
StackOverflow , SuperUser und AskUbuntu Zunächst erfolgt eine schnelle Auswahl, um eine dieser Websites auszuwählen. Anschließend wird die Frage getwittert.
Schließlich wird der cron-Job täglich um 1 Uhr und 5 Uhr morgens ausgeführt.
4. Konfiguration
Da es sich um ein Haustierprojekt handelt, begann es mit einer sehr einfachen Datenbankstruktur - es ist immer noch einfach, aber es war noch viel mehr. Eines der Hauptziele bestand daher darin, die Datenbankstruktur leicht ändern zu können - natürlich gibt es für Datenbankmigrationen natürlich several tools so ein einfaches Projekt.
Also beschloss ich, die Einstellungsdaten im https://github.com/eugenp/stackexchange2twitter/blob/master/src/main/resources/setup.properties (einem einfachen Textformat) beizubehalten.
Das Setup besteht aus zwei Hauptschritten:
-
Die IDs der Fragen, die auf jedem Twitter-Account getwittert wurden, werden abgerufen
und in einer Textdatei gespeichert ** Das Datenbankschema wird gelöscht und die Anwendung neu gestartet - dies
erstellt das Schema erneut und setzt alle Daten aus der Textdatei in die neue Datenbank zurück
4.1. Die Rohdaten zum Setup
Das Abrufen der Daten aus der vorhandenen Datenbank ist mit JDBC einfach genug. Zuerst definieren wir einen 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 "";
}
}
Dadurch wird eine Liste mit Fragen für jeden Twitter-Account erstellt.
Als Nächstes werden wir dies in einem einfachen Test verwenden:
@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)));
}
}
Nachdem Sie die Fragen für ein Konto abgerufen haben, listet der Test sie einfach auf. zum Beispiel:
SpringAtSO=3652090,1079114,5908466,...
4.2. Wiederherstellen der Setup-Daten
Die durch den vorherigen Schritt erzeugten Datenzeilen werden in der Datei a setup.properties gespeichert, die Spring zur Verfügung gestellt wird :
@Configuration
@PropertySource({ "classpath:setup.properties" })
public class PersistenceJPAConfig {
//}
Wenn die Anwendung gestartet wird, wird der Setup-Vorgang ausgeführt. Dieser einfache Prozess verwendet einen Spring ApplicationListener, der ein ContextRefreshedEvent überwacht:
@Component
public class StackexchangeSetup implements ApplicationListener<ContextRefreshedEvent> {
private boolean setupDone;
public void onApplicationEvent(ContextRefreshedEvent event) {
if (!setupDone) {
recreateAllQuestionsOnAllTwitterAccounts();
setupDone = true;
}
}
}
Schließlich werden die Fragen aus der Datei setup.properties abgerufen und erneut erstellt:
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);
}
}
Dieser einfache Vorgang ermöglicht ein einfaches Aktualisieren der DB-Struktur. Da die Daten vollständig gelöscht und vollständig neu erstellt werden, ist keine eigentliche Migration erforderlich.
5. Vollständige Liste der Konten
Die vollständige Liste der Twitter-Konten lautet:
-
SpringTip - Spring -Fragen aus
Paketüberfluss JavaTopSO - Java ** Fragen von
Paketüberfluss RESTDaily - REST ** Fragen von
Paketüberfluss ** https://twitter.com/BestJPA
Paketüberfluss MavenFact - Maven ** Fragen von
Paketüberfluss BestGit - Git ** -Fragen von
Paketüberfluss AskUbuntuBest AskUbuntu
allgemeine Fragen (alle Themen) ServerFaultBest - ServerFault **
beste Fragen (alle Themen) BestBash - beste Bash-Fragen ** aus
StackOverflow, ServerFault und AskUbuntu ** ClojureFact - Clojure-Fragen aus
Paketüberfluss ** ScalaFact - Scala-Fragen aus
Paketüberfluss ** EclipseFacts - Eclipse-Fragen
von StackOverflow ** jQueryDaily - jQuery Fragen aus
Paketüberfluss ** BestAlgorithms - Algorithmus
Fragen von StackOverflow
Auf jedem dieser Konten werden 2 Tweets pro Tag erstellt, wobei die am höchsten bewerteten Fragen zum jeweiligen Thema angezeigt werden.
6. Fazit
Dieser dritte Artikel schließt die Serie über die Integration in StackOverflow und andere StackExchange-Sites ab, um Fragen über ihre REST-API abzurufen, und die Integration mit Twitter und Spring Social, um diese Fragen zu twittern. Eine potenzielle Richtung, die es wert ist, ausgewertet zu werden, ist dasselbe mit Google Plus - wahrscheinlich Seiten, nicht Konten.
-
14 Twitter-Konten ** sind als Ergebnis dieses Projekts in Betrieb. Sie konzentrieren sich auf verschiedene Themen und produzieren Inhalte mit geringem Volumen und hoffentlich hoher Qualität (Ideen für andere Tags, die einen eigenen Twitter-Account verdienen, sind in den Kommentaren willkommen).