agirbot/src/org/april/hebdobot/model/Hebdobot.java

543 lines
19 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (C) 2011-2013,2017 Nicolas Vinot <aeris@imirhil.fr>
* Copyright (C) 2017 Christian Pierre MOMON <cmomon@april.org>
*
* This file is part of (April) Hebdobot.
*
* Hebdobot is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Hebdobot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Hebdobot. If not, see <http://www.gnu.org/licenses/>
*/
package org.april.hebdobot.model;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.april.hebdobot.HebdobotException;
import org.april.hebdobot.cron.CronManager;
import org.april.hebdobot.cron.CronSettings;
import org.april.hebdobot.identica.IdenticaSettings;
import org.april.hebdobot.pastebin.PastebinClient;
import org.april.hebdobot.pastebin.PastebinSettings;
import org.april.hebdobot.pastebin.Private;
import org.april.hebdobot.review.CollectiveTopic;
import org.april.hebdobot.review.IndividualTopic;
import org.april.hebdobot.review.Message;
import org.april.hebdobot.review.Review;
import org.april.hebdobot.review.Topic;
import org.april.hebdobot.twitter.TwitterClient;
import org.april.hebdobot.twitter.TwitterSettings;
import org.jibble.pircbot.IrcException;
import org.jibble.pircbot.NickAlreadyInUseException;
import org.jibble.pircbot.PircBot;
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.devinsy.util.strings.StringsUtils;
/**
* The Class Hebdobot.
*/
public class Hebdobot extends PircBot
{
private static final Logger logger = LoggerFactory.getLogger(Hebdobot.class);
private String host;
private int port;
private String channel;
private String reviewFileSuffix;
private Review review;
private IdenticaSettings identicaSettings;
private PastebinSettings pastebinSettings;
private TwitterSettings twitterSettings;
private CronSettings cronSettings;
private UserAliases aliases;
private CronManager cronManager;
/**
* Instantiates a new bot.
*
* @param host
* the host
* @param port
* the port
* @param name
* the name
* @param channel
* the channel
*/
public Hebdobot(final String host, final int port, final String name, final String channel, final String reviewFileSuffix)
{
this.host = host;
this.port = port;
this.channel = channel;
this.setName(name);
this.reviewFileSuffix = reviewFileSuffix;
this.review = null;
this.identicaSettings = new IdenticaSettings();
this.pastebinSettings = new PastebinSettings();
this.twitterSettings = new TwitterSettings();
this.cronSettings = new CronSettings();
this.aliases = new UserAliases();
this.cronManager = null;
}
/**
* Close.
*/
public void close()
{
this.disconnect();
this.dispose();
}
public UserAliases getAliases()
{
return this.aliases;
}
public CronSettings getCronSettings()
{
return this.cronSettings;
}
public IdenticaSettings getIdenticaSettings()
{
return this.identicaSettings;
}
public PastebinSettings getPastebinSettings()
{
return this.pastebinSettings;
}
public TwitterSettings getTwitterSettings()
{
return this.twitterSettings;
}
/**
* Notify.
*
* @param minutes
* the minutes
*/
public void notifyIrc(final String message)
{
sendMessage(message);
}
/**
* Notify twitter.
*
* @param message
* the message
*/
public void notifyTwitter(final String message)
{
if (this.twitterSettings.isValid())
{
TwitterClient twitter = new TwitterClient(this.twitterSettings.getConsumerKey(), this.twitterSettings.getConsumerSecret());
twitter.tweet(message);
}
}
/* (non-Javadoc)
* @see org.jibble.pircbot.PircBot#onMessage(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
@Override
protected void onMessage(final String channel, final String sender, final String login, final String hostname, final String message)
{
logger.debug("Message received - channel : {}, sender : {}, message : {}", channel, sender, message);
if (channel.equalsIgnoreCase(this.channel))
{
String text = message.trim();
if ((StringUtils.equalsIgnoreCase(text, "!aide")) || (StringUtils.equalsIgnoreCase(text, "!help")))
{
logger.info("!help caught.");
// Help.
sendMessage(sender, "Bienvenue " + sender);
sendMessage(sender, "Je suis " + getName() + ", le robot de gestion des revues hebdomadaires de l'APRIL.");
sendMessage(sender, "Voici les commandes que je comprends :");
sendMessage(sender, " ");
sendMessage(sender, " !debut : commencer une nouvelle revue");
sendMessage(sender, " !fin : terminer la revue en cours");
sendMessage(sender, " # titre : démarrer un sujet individuel");
sendMessage(sender, " ## titre : démarrer un sujet collectif");
sendMessage(sender, " !courant : affiche le sujet en cours");
sendMessage(sender, " !manquants : affiche les participants qui n'ont pas répondu sur le dernier sujet");
sendMessage(sender, " % message : un commentaire");
sendMessage(sender, " !stop : abandonner la revue en cours");
sendMessage(sender, " !vaten : faire partir le bot");
sendMessage(sender, " !aide : afficher cette aide");
}
else if (StringUtils.equalsIgnoreCase(text, "!vaten"))
{
logger.info("!die caught.");
// Die.
if (this.review == null)
{
try
{
sendMessage(sender + ", ok bye.");
Thread.sleep(1000);
System.exit(0);
}
catch (InterruptedException exception)
{
logger.warn("Pause abort: " + exception.getMessage());
}
}
else
{
sendMessage("% Une revue est en cours, abandon impossible.");
}
}
else if (StringUtils.equalsIgnoreCase(text, "!stop"))
{
logger.info("!stop caught.");
// Stop.
if (this.review == null)
{
sendMessage("Aucune revue en cours, abandon impossible.");
}
else
{
sendMessage("Abandon de la revue en cours.");
this.review = null;
}
}
else if (StringsUtils.equalsAnyIgnoreCase(text, "!debut", "!début"))
{
logger.info("!debut caught.");
// Start.
if (this.cronManager != null)
{
try
{
this.cronManager.shutdown();
}
catch (SchedulerException exception)
{
logger.warn("Scheduler shutdown failed.", exception);
}
}
this.review = new Review(sender, this.aliases);
sendMessage(sender, "Vous êtes le conducteur de réunion");
sendMessage(sender, "Pour terminer la réunion, tapez \"!fin\"");
sendMessage("% Début de la réunion hebdomadaire");
sendMessage("% rappel : toute ligne commençant par % sera considérée comme un commentaire et non prise en compte dans la synthèse");
}
else if (StringUtils.equalsIgnoreCase(text, "!fin"))
{
logger.info("!fin caught.");
// Stop.
if (this.review == null)
{
sendMessage(sender + ", pas de revue en cours.");
}
else if (!this.review.isOwner(sender))
{
sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
}
else
{
{
String date = ISODateTimeFormat.basicDate().print(new DateTime());
String textReview = this.review.toString();
if (this.pastebinSettings.isValid())
{
logger.info("Pastebin the review.");
try
{
PastebinClient pastebinClient = new PastebinClient(this.pastebinSettings.getApiKey());
String returnValue = pastebinClient.paste(textReview, "Revue APRIL " + date, Private.UNLISTED);
sendMessage("% Compte-rendu de la revue : " + returnValue);
}
catch (final Exception exception)
{
logger.error("Error during Pastebin submit.", exception);
}
}
if (this.reviewFileSuffix != null)
{
logger.info("Write review file.");
try
{
File file = new File(date + "_" + this.reviewFileSuffix);
FileUtils.writeStringToFile(file, textReview);
sendMessage("% Compte-rendu de la revue : " + file.getName());
}
catch (final Exception exception)
{
logger.error("Error during file generation", exception);
}
}
}
sendMessage("% " + this.review.getOwner()
+ ", ne pas oublier d'ajouter le compte-rendu de la revue sur https://agir.april.org/issues/135");
String participants = StringUtils.join(this.review.getParticipants(), " ");
sendMessage("% " + participants + ", pensez à noter votre bénévalo : http://www.april.org/my?action=benevalo");
sendMessage("% Fin de la revue hebdomadaire");
this.review = null;
}
}
else if (text.matches("\\s*##.*"))
{
logger.info("\\s*##.* caught.");
// Collective topic, must be before individual topic.
if (this.review != null)
{
if (this.review.isOwner(sender))
{
CollectiveTopic topic = new CollectiveTopic(text.replaceFirst("##", "").trim());
this.review.begin(topic);
sendMessage("Sujet collectif : " + topic.getTitle());
if (topic.getTitle().toLowerCase().contains("bloquage"))
{
sendMessage("% si rien à dire vous pouvez dire %ras");
}
else
{
sendMessage("% 1 minute max");
}
}
else
{
sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
}
}
}
else if (text.matches("\\s*#[^#].*"))
{
logger.info("\\s*#[^#].* caught.");
// Individual topic.
if (this.review != null)
{
if (this.review.isOwner(sender))
{
IndividualTopic topic = new IndividualTopic(text.replaceFirst("#", "").trim());
this.review.begin(topic);
sendMessage("Sujet individuel : " + topic.getTitle());
sendMessage("% quand vous avez fini vous le dites par % fini");
}
else
{
sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
}
}
}
else if (StringUtils.equalsIgnoreCase(text, "!manquants"))
{
logger.info("!manquants caught.");
// Missing.
if (this.review == null)
{
sendMessage("Pas de revue en cours.");
}
else
{
Topic topic = this.review.getCurrentTopic();
if (topic == null)
{
sendMessage("Aucun sujet traité");
}
else
{
Collection<String> participants = this.review.getParticipants();
Collection<String> currentParticipants = topic.getParticipants();
Collection<String> missing = CollectionUtils.subtract(participants, currentParticipants);
if (missing.isEmpty())
{
sendMessage("Aucun participant manquant \\o/");
}
else
{
sendMessage(String.format("Les participants suivants sont manquants : %1s", StringUtils.join(missing, ", ")));
}
}
}
}
else if (StringUtils.equalsIgnoreCase(text, "!courant"))
{
logger.info("!courant caught.");
// Current.
if (this.review == null)
{
sendMessage("Pas de revue en cours.");
}
else
{
Topic current = this.review.getCurrentTopic();
if (current == null)
{
sendMessage("% Pas de sujet en cours");
}
else if (current instanceof IndividualTopic)
{
sendMessage("% Sujet individuel en cours : " + current.getTitle());
}
else if (current instanceof CollectiveTopic)
{
sendMessage("% Sujet collectif en cours : " + current.getTitle());
}
}
}
else if (StringUtils.equalsIgnoreCase(text, "!statut"))
{
logger.info("!status caught.");
sendMessage(sender, sender + ", voici l'état d'Hebdobot :");
sendMessage(sender, " revue en cours : " + (this.review == null));
if (this.review == null)
{
sendMessage(sender, " animateur revue : none");
}
else
{
sendMessage(sender, " animateur revue : " + this.review.getOwner());
}
sendMessage(sender, " Alias settings : " + (this.aliases.size()));
sendMessage(sender, " Identica settings : " + (this.identicaSettings.isValid()));
sendMessage(sender, " Pastebin settings : " + (this.pastebinSettings.isValid()));
sendMessage(sender, " Twitter settings : " + (this.twitterSettings.isValid()));
sendMessage(sender, " Cron settings : " + (this.cronSettings.size()));
}
else if (text.startsWith("%"))
{
logger.info("% caught.");
// Ignore.
}
else if (text.startsWith("!"))
{
logger.info("!??? caught.");
// Command unknown.
sendMessage(sender + ", command unknown: " + text);
}
else
{
logger.info("Else caught.");
// Topic message.
if (this.review == null)
{
if ((StringsUtils.containsAnyIgnoreCase(text, "bonjour", "salut", "hello")) && (StringUtils.containsIgnoreCase(text, "hebdobot")))
{
sendMessage(sender + ", bonjour \\o/");
}
}
else
{
this.review.add(new Message(sender, text));
}
}
/*
else
{
logger.info("Else caught.");
// All the other.
if (this.review != null)
{
this.review.addRaw(new Message(sender, text));
}
}*/
}
}
/**
* Inits the.
*
* the exception
*
* @throws HebdobotException
*/
public void run() throws HebdobotException
{
try
{
logger.info("Cron initializing.");
{
this.cronManager = new CronManager(this, this.cronSettings);
this.cronManager.start();
}
logger.info("Cron initialized.");
logger.info("Bot connection.");
this.connect(this.host, this.port);
logger.info("Bot connected.");
logger.info("Bot joining channel ({}).", this.channel);
this.joinChannel(this.channel);
logger.info("Bot ready.");
}
catch (NickAlreadyInUseException exception)
{
throw new HebdobotException(exception);
}
catch (IOException exception)
{
throw new HebdobotException(exception);
}
catch (IrcException exception)
{
throw new HebdobotException(exception);
}
catch (SchedulerException exception)
{
throw new HebdobotException("Error in cron settings.", exception);
}
}
/**
* Send message.
*
* @param message
* the message
*/
public void sendMessage(final String message)
{
logger.debug("Send message : {}", message);
this.sendMessage(this.channel, message);
}
}