hebdobot/src/main/java/fr/imirhil/april/hebdobot/irc/Bot.java

540 lines
18 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 fr.imirhil.april.hebdobot.irc;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.jibble.pircbot.PircBot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.imirhil.april.hebdobot.Context;
import fr.imirhil.april.hebdobot.review.CollectiveTopic;
import fr.imirhil.april.hebdobot.review.IndividualTopic;
import fr.imirhil.april.hebdobot.review.Message;
import fr.imirhil.april.hebdobot.review.Review;
import fr.imirhil.april.hebdobot.review.Topic;
/**
* The Class Bot.
*/
public class Bot extends PircBot
{
/**
* The Class Handler.
*/
private abstract class Handler
{
/**
* Handle.
*
* @param sender
* the sender
* @param message
* the message
* @return true, if successful
*/
public abstract boolean handle(String sender, String message);
}
private static final Logger logger = LoggerFactory.getLogger(Bot.class);
private final String host;
private final int port;
private final String channel;
private Review review = null;
private final Collection<ReviewListener> listeners;
private final List<Handler> handlers;
/**
* Instantiates a new bot.
*
* @param host
* the host
* @param port
* the port
* @param name
* the name
* @param channel
* the channel
*/
public Bot(final String host, final int port, final String name, final String channel)
{
this.host = host;
this.port = port;
this.channel = channel;
this.setName(name);
this.listeners = new LinkedList<ReviewListener>();
this.handlers = new LinkedList<Handler>();
}
/**
* Adds the.
*
* @param listener
* the listener
*/
public void add(final ReviewListener listener)
{
this.listeners.add(listener);
}
/**
* Close.
*/
public void close()
{
this.disconnect();
this.dispose();
}
/**
* Inits the.
*
* @throws Exception
* the exception
*/
public void init() throws Exception
{
this.connect(this.host, this.port);
this.joinChannel(this.channel);
this.registerHandlers();
}
/* (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, String message)
{
logger.debug("Message received - channel : {}, sender : {}, message : {}", channel, sender, message);
if (channel.equalsIgnoreCase(this.channel))
{
message = message.trim();
boolean ended = false;
Iterator<Handler> iterator = this.handlers.iterator();
while (!ended)
{
if (iterator.hasNext())
{
Handler currentHandler = iterator.next();
if (currentHandler.handle(sender, message))
{
ended = true;
}
}
else
{
ended = true;
}
}
}
}
/**
* Register handlers.
*/
private void registerHandlers()
{
// Help
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (StringUtils.equalsIgnoreCase(message, "!help"))
{
Bot.this.sendMessage(sender, "Bienvenue " + sender);
Bot.this.sendMessage(sender, "Je suis " + Bot.this.getName() + ", le robot de gestion des revues hebdomadaires de l'APRIL");
Bot.this.sendMessage(sender, "Voici les commandes que je comprend :");
Bot.this.sendMessage(sender, " ");
Bot.this.sendMessage(sender, "— !debut : commencer une nouvelle revue");
Bot.this.sendMessage(sender, "— !fin : terminer la revue en cours");
Bot.this.sendMessage(sender, "— # titre : démarrer un sujet individuel");
Bot.this.sendMessage(sender, "— ## titre : démarrer un sujet collectif");
Bot.this.sendMessage(sender, "— !courant : affiche le sujet en cours");
Bot.this.sendMessage(sender, "— !manquants : affiche les participants qui n'ont pas répondu sur le dernier sujet");
Bot.this.sendMessage(sender, "— % message : un commentaire");
result = true;
}
else
{
result = false;
}
//
return result;
}
});
// Die
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (!StringUtils.equalsIgnoreCase(message, "!stop"))
{
result = false;
}
else if (Bot.this.review != null)
{
Bot.this.sendMessage("% Une revue est en cours, arrêt impossible");
result = false;
}
else
{
Context.close();
result = true;
}
//
return result;
}
});
// Start
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (!StringUtils.equalsIgnoreCase(message, "!debut"))
{
result = false;
}
else
{
Bot.this.review = new Review(sender);
Bot.this.sendMessage(sender, "Vous êtes le conducteur de réunion");
Bot.this.sendMessage(sender, "Pour terminer la réunion, tapez \"!fin\"");
Bot.this.sendMessage("% Début de la réunion hebdomadaire");
Bot.this.sendMessage(
"% rappel : toute ligne commençant par % sera considérée comme un commentaire et non prise en compte dans la synthèse");
result = true;
}
//
return result;
}
});
// Stop
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (Bot.this.review == null || !StringUtils.equalsIgnoreCase(message, "!fin"))
{
result = false;
}
else
{
if (!Bot.this.review.isOwner(sender))
{
Bot.this.sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
result = false;
}
else
{
for (final ReviewListener listener : Bot.this.listeners)
{
listener.onEnd(Bot.this.review);
}
Bot.this.sendMessage("% " + Bot.this.review.getOwner()
+ ", ne pas oublier d'ajouter le compte-rendu de la revue sur https://agir.april.org/issues/135");
final String participants = StringUtils.join(Bot.this.review.getParticipants(), " ");
Bot.this.sendMessage("% " + participants + ", pensez à noter votre bénévalo : http://www.april.org/my?action=benevalo");
Bot.this.sendMessage("% Fin de la revue hebdomadaire");
Bot.this.review = null;
result = true;
}
}
//
return result;
}
});
// Collective topic, must be before individual topic
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (Bot.this.review == null || !message.matches("\\s*##.*"))
{
result = false;
}
else
{
if (Bot.this.review.isOwner(sender))
{
final CollectiveTopic topic = new CollectiveTopic(message.replaceFirst("##", "").trim());
Bot.this.review.begin(topic);
Bot.this.sendMessage("Sujet collectif : " + topic.getTitle());
if (topic.getTitle().toLowerCase().contains("bloquage"))
{
Bot.this.sendMessage("% si rien à dire vous pouvez dire %ras");
}
else
{
Bot.this.sendMessage("% 1 minute max");
}
result = true;
}
else
{
Bot.this.sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
result = false;
}
}
//
return result;
}
});
// Individual topic
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (Bot.this.review == null || !message.matches("\\s*#[^#].*"))
{
result = false;
}
else
{
if (Bot.this.review.isOwner(sender))
{
Bot.this.sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
result = false;
}
else
{
final IndividualTopic topic = new IndividualTopic(message.replaceFirst("#", "").trim());
Bot.this.review.begin(topic);
Bot.this.sendMessage("Sujet individuel : " + topic.getTitle());
Bot.this.sendMessage("% quand vous avez fini vous le dites par % fini");
result = true;
}
}
//
return result;
}
});
// Missing
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (Bot.this.review == null || !StringUtils.equalsIgnoreCase(message, "!manquants"))
{
result = false;
}
else
{
final Topic topic = Bot.this.review.getCurrentTopic();
if (topic == null)
{
Bot.this.sendMessage("Aucun sujet traité");
result = true;
}
else
{
final Collection<String> participants = Bot.this.review.getParticipants();
final Collection<String> currentParticipants = topic.getParticipants();
final Collection<String> missing = CollectionUtils.subtract(participants, currentParticipants);
if (missing.isEmpty())
{
Bot.this.sendMessage("Aucun participant manquant \\o/");
result = true;
}
else
{
Bot.this.sendMessage(String.format("Les participants suivants sont manquants : %1s", StringUtils.join(missing, ", ")));
result = true;
}
}
}
//
return result;
}
});
// Current
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (Bot.this.review == null || !StringUtils.equalsIgnoreCase(message, "!courant"))
{
result = false;
}
else
{
final Topic current = Bot.this.review.getCurrentTopic();
if (current == null)
{
Bot.this.sendMessage("% Pas de sujet en cours");
}
else if (current instanceof IndividualTopic)
{
Bot.this.sendMessage("% Sujet individuel en cours : " + current.getTitle());
}
else if (current instanceof CollectiveTopic)
{
Bot.this.sendMessage("% Sujet collectif en cours : " + current.getTitle());
}
result = true;
}
//
return result;
}
});
// Topic message
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (Bot.this.review == null || message.startsWith("%"))
{
result = false;
}
else
{
Bot.this.review.add(new Message(sender, message));
result = true;
}
//
return result;
}
});
// All the other
this.handlers.add(new Handler()
{
/* (non-Javadoc)
* @see fr.imirhil.april.hebdobot.irc.Bot.Handler#handle(java.lang.String, java.lang.String)
*/
@Override
public boolean handle(final String sender, final String message)
{
boolean result;
if (Bot.this.review == null)
{
result = false;
}
else
{
Bot.this.review.addRaw(new Message(sender, message));
result = true;
}
//
return result;
}
});
}
/**
* Send message.
*
* @param message
* the message
*/
public void sendMessage(final String message)
{
logger.debug("Send message : {}", message);
this.sendMessage(this.channel, message);
}
}