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

361 lines
12 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.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;
public class Bot extends PircBot
{
private abstract class Handler
{
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 = new LinkedList<ReviewListener>();
private final List<Handler> handlers = new LinkedList<Handler>();
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);
}
public void add(final ReviewListener listener)
{
this.listeners.add(listener);
}
public void close()
{
this.disconnect();
this.dispose();
}
public void init() throws Exception
{
this.connect(this.host, this.port);
this.joinChannel(this.channel);
this.registerHandlers();
}
@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 : {}", new Object[] { channel, sender, message });
if (!channel.equalsIgnoreCase(this.channel))
{
return;
}
message = message.trim();
for (final Handler handler : this.handlers)
{
if (handler.handle(sender, message))
{
break;
}
}
}
private void registerHandlers()
{
// Help
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (!"!help".equalsIgnoreCase(message))
{
return false;
}
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");
return true;
}
});
// Die
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (!"!stop".equalsIgnoreCase(message))
{
return false;
}
if (Bot.this.review != null)
{
Bot.this.sendMessage("% Une revue est en cours, arrêt impossible");
return false;
}
Context.close();
return true;
}
});
// Start
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (!"!debut".equalsIgnoreCase(message))
{
return false;
}
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");
return true;
}
});
// Stop
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (Bot.this.review == null || !"!fin".equalsIgnoreCase(message))
{
return false;
}
if (!Bot.this.review.isOwner(sender))
{
Bot.this.sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
return false;
}
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;
return true;
}
});
// Collective topic, must be before individual topic
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (Bot.this.review == null || !message.matches("\\s*##.*"))
{
return false;
}
if (!Bot.this.review.isOwner(sender))
{
Bot.this.sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
return false;
}
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");
}
return true;
}
});
// Individual topic
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (Bot.this.review == null || !message.matches("\\s*#[^#].*"))
{
return false;
}
if (!Bot.this.review.isOwner(sender))
{
Bot.this.sendMessage(sender + ", vous n'êtes pas le conducteur de la réunion");
return false;
}
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");
return true;
}
});
// Missing
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (Bot.this.review == null || !"!manquants".equalsIgnoreCase(message))
{
return false;
}
final Topic topic = Bot.this.review.getCurrentTopic();
if (topic == null)
{
Bot.this.sendMessage("Aucun sujet traité");
return true;
}
final Collection<String> participants = Bot.this.review.getParticipants();
final Collection<String> currentParticipants = topic.getParticipants();
@SuppressWarnings("unchecked")
final Collection<String> missing = CollectionUtils.subtract(participants, currentParticipants);
if (missing.isEmpty())
{
Bot.this.sendMessage("Aucun participant manquant \\o/");
return true;
}
Bot.this.sendMessage(String.format("Les participants suivants sont manquants : %1s", StringUtils.join(missing, ", ")));
return true;
}
});
// Current
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (Bot.this.review == null || !"!courant".equalsIgnoreCase(message))
{
return false;
}
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());
}
return true;
}
});
// Topic message
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (Bot.this.review == null || message.startsWith("%"))
{
return false;
}
Bot.this.review.add(new Message(sender, message));
return true;
}
});
// All the other
this.handlers.add(new Handler()
{
@Override
public boolean handle(final String sender, final String message)
{
if (Bot.this.review == null)
{
return false;
}
Bot.this.review.addRaw(new Message(sender, message));
return true;
}
});
}
public void sendMessage(final String message)
{
LOGGER.debug("Send message : {}", message);
this.sendMessage(this.channel, message);
}
}