Added user aliases management.

This commit is contained in:
Christian P. MOMON 2017-12-25 00:29:57 +01:00
parent ffaaf8dc4c
commit 533e2d1486
12 changed files with 321 additions and 187 deletions

View File

@ -5,9 +5,10 @@
* Set formatter and save actions settings and applied it.
* Made a code review.
* Place internal classes in their own file.
* Renamed package from fr.imirhil.april to org.april
* Splitted launcher and CLI.
* anonymized Twitter API key
* renamed package from fr.imirhil.april to org.april
* replaced Maven with Ant
* eplaced Maven with Ant
* no more code injection

View File

@ -4,7 +4,7 @@ NAME=hebdobot
BASE_DIR=$HOME/$NAME
PID_FILE=$BASE_DIR/$NAME.pid
DAEMON=java
DAEMON_ARGS="-cp *:lib/* org.april.hebdobot.Application"
DAEMON_ARGS="-cp *:lib/* org.april.hebdobot"
CMD="/sbin/start-stop-daemon --chdir $BASE_DIR --quiet --make-pidfile --pidfile $PID_FILE --exec $DAEMON"
case "$1" in

View File

@ -1,2 +1,2 @@
#!/bin/sh
java -cp '*:lib/*' org.april.hebdobot.Application
java -cp '*:lib/*' org.april.hebdobot

View File

@ -0,0 +1,5 @@
#
# Sample Hebdobot user file
#
Christian P. MOMON=cpm__,cpm_screen

View File

@ -30,6 +30,7 @@ import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.StringUtils;
import org.april.hebdobot.HebdobotException;
import org.april.hebdobot.model.Hebdobot;
import org.april.hebdobot.model.UserAliases;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -44,6 +45,7 @@ public class HebdobotCLI
public static final String HEBDOBOT_VERSION = "v2.0";
private static final String DEFAULT_CONFIG_FILE = "hebdobot.conf";
private static final String DEFAULT_ALIAS_FILE = "users.conf";
/**
* Instantiates a new hebdobot launcher.
@ -124,11 +126,21 @@ public class HebdobotCLI
if (configFile.exists())
{
// Load configuration file.
logger.info("Config file loading… ({}).", configFile.getAbsolutePath());
HebdobotConfigFile config = new HebdobotConfigFile(configFile);
logger.info("Config file loaded.");
// Load user aliases file.
File aliasFile = new File(configFile.getParentFile(), DEFAULT_ALIAS_FILE);
logger.info("Aliases file loading… ({}).", aliasFile.getAbsolutePath());
UserAliases aliases = new UserAliases(aliasFile);
logger.info("Aliases file loaded.");
if (config.isValid())
{
logger.info("Bot configuring…");
Hebdobot bot = new Hebdobot(config.getIrcHost(), config.getIrcPort(), config.getIrcName(), config.getIrcChannel(),
config.getReviewFileSuffix());
@ -137,6 +149,8 @@ public class HebdobotCLI
bot.getIdenticaSettings().setApiSecret(config.getIdenticaApiSecret());
bot.getTwitterSettings().setConsumerKey(config.getTwitterConsumerKey());
bot.getTwitterSettings().setConsumerSecret(config.getTwitterConsumerSecret());
bot.getAliases().putAll(aliases);
logger.info("Bot configured.");
bot.run();
}

View File

@ -61,6 +61,7 @@ public class Hebdobot extends PircBot
private IdenticaSettings identicaSettings;
private PastebinSettings pastebinSettings;
private TwitterSettings twitterSettings;
private UserAliases aliases;
/**
* Instantiates a new bot.
@ -86,6 +87,7 @@ public class Hebdobot extends PircBot
this.identicaSettings = new IdenticaSettings();
this.pastebinSettings = new PastebinSettings();
this.twitterSettings = new TwitterSettings();
this.aliases = new UserAliases();
}
/**
@ -97,6 +99,11 @@ public class Hebdobot extends PircBot
this.dispose();
}
public UserAliases getAliases()
{
return this.aliases;
}
public IdenticaSettings getIdenticaSettings()
{
return this.identicaSettings;
@ -148,6 +155,8 @@ public class Hebdobot extends PircBot
if (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");
@ -163,6 +172,8 @@ public class Hebdobot extends PircBot
}
else if (StringUtils.equalsIgnoreCase(text, "!stop"))
{
logger.info("!stop caught.");
// Die.
if (this.review == null)
{
@ -176,8 +187,10 @@ public class Hebdobot extends PircBot
}
else if ((StringUtils.equalsIgnoreCase(text, "!debut")) || (StringUtils.equalsIgnoreCase(text, "!début")))
{
logger.info("!debut caught.");
// Start.
this.review = new Review(sender);
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");
@ -185,6 +198,8 @@ public class Hebdobot extends PircBot
}
else if (StringUtils.equalsIgnoreCase(text, "!fin"))
{
logger.info("!fin caught.");
// Stop.
if (this.review != null)
{
@ -199,17 +214,20 @@ public class Hebdobot extends PircBot
{
String date = ISODateTimeFormat.basicDate().print(new DateTime());
String textReview = this.review.toString();
try
if (this.pastebinSettings.isValid())
{
PastebinClient pastebinClient = new PastebinClient(this.pastebinSettings.getApiKey());
try
{
PastebinClient pastebinClient = new PastebinClient(this.pastebinSettings.getApiKey());
String returnValue = pastebinClient.paste(textReview, "Revue APRIL " + date, Private.UNLISTED);
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);
sendMessage("% Compte-rendu de la revue : " + returnValue);
}
catch (final Exception exception)
{
logger.error("Error during Pastebin submit.", exception);
}
}
if (this.reviewFileSuffix != null)
@ -238,6 +256,8 @@ public class Hebdobot extends PircBot
}
else if (text.matches("\\s*##.*"))
{
logger.info("\\s*##.* caught.");
// Collective topic, must be before individual topic.
if (this.review != null)
{
@ -263,6 +283,8 @@ public class Hebdobot extends PircBot
}
else if (text.matches("\\s*#[^#].*"))
{
logger.info("\\s*#[^#].* caught.");
// Individual topic.
if (this.review == null)
{
@ -278,80 +300,88 @@ public class Hebdobot extends PircBot
sendMessage("% quand vous avez fini vous le dites par % fini");
}
}
else if (StringUtils.equalsIgnoreCase(text, "!manquants"))
{
// 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();
}
else if (StringUtils.equalsIgnoreCase(text, "!manquants"))
{
logger.info("!manquants caught.");
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"))
// Missing.
if (this.review == null)
{
// 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 (text.startsWith("%"))
{
// Topic message.
if (this.review == null)
{
sendMessage("Pas de revue en cours.");
}
else
{
this.review.add(new Message(sender, text));
}
sendMessage("Pas de revue en cours.");
}
else
{
// All the other.
if (this.review != null)
Topic topic = this.review.getCurrentTopic();
if (topic == null)
{
this.review.addRaw(new Message(sender, text));
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 (text.startsWith("%"))
{
logger.info("% caught.");
// Topic message.
if (this.review == null)
{
sendMessage("Pas de revue en cours.");
}
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));
}
}
}
@ -368,8 +398,11 @@ public class Hebdobot extends PircBot
{
try
{
logger.info("Bot connection.");
this.connect(this.host, this.port);
logger.info("Bot joining channel ({}).", this.channel);
this.joinChannel(this.channel);
logger.info("Bot ready.");
}
catch (NickAlreadyInUseException exception)
{

View File

@ -0,0 +1,140 @@
/**
* Copyright (C) 2011-2013 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.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.april.hebdobot.HebdobotException;
import org.april.hebdobot.util.HebdobotUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class UserAliases.
*/
public class UserAliases
{
private static final Logger logger = LoggerFactory.getLogger(UserAliases.class);
private final Map<String, String> aliases;
/**
* Instantiates a new user aliases.
*/
public UserAliases()
{
this.aliases = new HashMap<String, String>();
}
/**
* Instantiates a new user aliases.
*
* @param source
* the source
* @throws HebdobotException
* the hebdobot exception
*/
public UserAliases(final File source) throws HebdobotException
{
this.aliases = new HashMap<String, String>();
try
{
Properties users = HebdobotUtils.loadProperties(source);
for (String realName : users.stringPropertyNames())
{
String[] nicks = users.getProperty(realName).split(",");
for (String nick : nicks)
{
this.aliases.put(nick, realName);
}
}
}
catch (FileNotFoundException exception)
{
logger.warn("File not found.");
}
catch (IOException exception)
{
throw new HebdobotException("IO error.", exception);
}
}
/**
* Gets the real name.
*
* @param nick
* the nick
* @return the real name
*/
public String getRealName(final String nick)
{
String result;
result = this.aliases.get(nick);
if (result == null)
{
boolean ended = false;
Iterator<String> iterator = this.aliases.keySet().iterator();
while (!ended)
{
if (iterator.hasNext())
{
String currentNick = iterator.next();
if (nick.toLowerCase().contains(currentNick.toLowerCase()))
{
ended = true;
result = this.aliases.get(currentNick) + " ( " + nick + " )";
}
}
else
{
result = nick;
ended = true;
}
}
}
//
return result;
}
/**
* Put all.
*
* @param source
* the source
*/
public void putAll(final UserAliases source)
{
this.aliases.putAll(source.aliases);
}
}

View File

@ -18,6 +18,8 @@
*/
package org.april.hebdobot.pastebin;
import org.apache.commons.lang3.StringUtils;
/**
* The Class IdenticaSettings.
*/
@ -49,6 +51,28 @@ public class PastebinSettings
return this.apiKey;
}
/**
* Checks if is valid.
*
* @return true, if is valid
*/
public boolean isValid()
{
boolean result;
if (StringUtils.isBlank(this.apiKey))
{
result = false;
}
else
{
result = true;
}
//
return result;
}
public void setApiKey(final String apiKey)
{
this.apiKey = apiKey;

View File

@ -26,8 +26,7 @@ import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.april.hebdobot.Context;
import org.april.hebdobot.xml.UserAlias;
import org.april.hebdobot.model.UserAliases;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
@ -38,13 +37,13 @@ public class Review
{
private static final int LENGTH = 80;
private static final UserAlias USER_ALIAS = Context.getBean(UserAlias.class);
private final Set<String> participants;
private final List<IndividualTopic> individualTopics;
private final List<CollectiveTopic> collectiveTopics;
private Topic currentTopic;
private final List<Message> messages;
private final String owner;
private final UserAliases aliases;
/**
* Instantiates a new review.
@ -52,7 +51,7 @@ public class Review
* @param owner
* the owner
*/
public Review(final String owner)
public Review(final String owner, final UserAliases aliases)
{
this.participants = new HashSet<String>();
this.individualTopics = new LinkedList<IndividualTopic>();
@ -60,6 +59,7 @@ public class Review
this.messages = new Messages();
this.owner = owner;
this.aliases = aliases;
}
/**
@ -154,6 +154,7 @@ public class Review
result.addAll(topic.getParticipants());
}
//
return result;
}
@ -166,7 +167,12 @@ public class Review
*/
public boolean isOwner(final String name)
{
return this.owner.equalsIgnoreCase(name);
boolean result;
result = this.owner.equalsIgnoreCase(name);
//
return result;
}
/* (non-Javadoc)
@ -191,7 +197,7 @@ public class Review
addCenter(buffer, "Participants", '-');
for (final String participant : this.participants)
{
addChunk(buffer, "* " + USER_ALIAS.getRealName(participant) + "\n");
addChunk(buffer, "* " + this.aliases.getRealName(participant) + "\n");
}
if (!this.individualTopics.isEmpty())
@ -201,7 +207,7 @@ public class Review
addEmpty(buffer);
addLine(buffer, '=');
addEmpty(buffer);
addCenter(buffer, USER_ALIAS.getRealName(participant), '-');
addCenter(buffer, this.aliases.getRealName(participant), '-');
for (final IndividualTopic topic : this.individualTopics)
{
if (topic.hasParticipant(participant))
@ -443,5 +449,4 @@ public class Review
//
return result;
}
}

View File

@ -53,7 +53,7 @@ public class HebdobotUtils
* the hebdobot exception
* @throws IOException
*/
public static Properties loadProperties(final File source) throws HebdobotException, IOException
public static Properties loadProperties(final File source) throws IOException
{
Properties result;

View File

@ -1,97 +0,0 @@
/**
* Copyright (C) 2011-2013 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.xml;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.SchemaFactory;
import org.jibble.pircbot.User;
import org.xml.sax.SAXException;
/**
* The Class UserAlias.
*/
public class UserAlias
{
private final Map<String, String> aliases = new HashMap<String, String>();
/**
* Instantiates a new user alias.
*
* @param source
* the source
*/
public UserAlias(final InputStream source)
{
try
{
final Unmarshaller unmarshaller = JAXBContext.newInstance(Users.class).createUnmarshaller();
unmarshaller.setSchema(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
.newSchema(UserAlias.class.getResource("/org/april/hebdobot/users.xsd")));
for (final User user : unmarshaller.unmarshal(new StreamSource(source), Users.class).getValue().getUser())
{
final String realName = user.getRealName();
for (final String nick : user.getNick())
{
this.aliases.put(nick, realName);
}
}
}
catch (final SAXException exception)
{
exception.printStackTrace();
throw new RuntimeException(exception);
}
catch (final JAXBException exception)
{
exception.printStackTrace();
throw new RuntimeException(exception);
}
}
/**
* Gets the real name.
*
* @param nick
* the nick
* @return the real name
*/
public String getRealName(final String nick)
{
for (final Entry<String, String> entry : this.aliases.entrySet())
{
if (nick.toLowerCase().contains(entry.getKey().toLowerCase()))
{
return entry.getValue() + " ( " + nick + " )";
}
}
return nick;
}
}

9
test/users.conf Normal file
View File

@ -0,0 +1,9 @@
#
# Sample Hebdobot user file
#
Christian P. MOMON=cpm__,cpm_screen
Lionel Allorge=liot,liot_
Frédéric Couchet=madix
François Poulain=Polux[2]
Étienne Gonnu=lonugem