package net.mc_pandacraft.java.plugin.pandacraftutils.modules; import java.sql.Date; import java.sql.SQLException; import java.text.DateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Random; import mkremins.fanciful.FancyMessage; import net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils; import net.mc_pandacraft.java.plugin.pandacraftutils.commands.AbstractCommandExecutor; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.MPGroupElement; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.MPGroupTable; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.MPGroupUserElement; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.MPGroupUserTable; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.MPMessageElement; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.MPMessageTable; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.MPWebSessionElement; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.MPWebSessionTable; import net.mc_pandacraft.java.plugin.pandacraftutils.data_model.ORM; import net.mc_pandacraft.java.plugin.pandacraftutils.players.OffPlayer; import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayer; import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayerManager; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import de.luricos.bukkit.xAuth.events.xAuthLoginEvent; public class PrivateMessagesManager extends BukkitRunnable { private PandacraftUtils plugin = PandacraftUtils.getInstance(); private static final long TIMEOUT_WEB_SESSION = 10000; // msec public PrivateMessagesManager() { plugin.getServer().getScheduler().runTaskTimer(plugin, this, 2L, 10L); // récupération des /mail /* plugin.getServer().getScheduler().runTaskLater(plugin, new Runnable() { @Override public void run() { UserMap players = EssentialsInterface.getPlugin().getUserMap(); plugin.getLogger().info("Importing player's /mail from Essentials data ..."); if (players == null) return; plugin.getLogger().info("There are "+players.getUniqueUsers()+" players files in Essentials/userdata"); Set<String> users = players.getAllUniqueUsers(); for (String su : users) { User u = players.getUser(su); if (u.getBase() != null && u.getBase().isOnline()) continue; List<String> mails = u.getMails(); if (mails.isEmpty()) continue; for (String mail : mails) { String[] split = mail.split(":", 2); String sourceName = split[0].trim(); String message = split[1].trim(); try { inputMessage(new MessageSender(sourceName), u.getName(), message); } catch (MessageSendingException e) { plugin.getLogger().severe(e.getMessage()); } } u.setMails(null); } players.reloadConfig(); } }, 1L); */ } @Override public void run() { // récupération des messages non synchronisé : try { List<MPMessageElement> messages = ((MPMessageTable)ORM.getTable("mp_message")).getAllUnsyncMessage(); for (MPMessageElement message : messages) { if (message.getViewerNick().equals(message.getSourceNick())) tryDisplayMessageToConsole(message); tryDisplayMessage(message); message.setServerSync(true); message.save(); } } catch (SQLException e) { plugin.getLogger().severe("Impossible de récupérer les messages privés de la base de donnée"); e.printStackTrace(); } } /** * @param sender l'origine du message * @param message le message * @throws MessageSendingException */ public void respondMessage(MessageSender sender, String message) throws MessageSendingException { OnlinePlayer op = OnlinePlayerManager.get(Bukkit.getPlayer(sender.senderName)); if (op == null) throw new MessageSendingException("Seul les joueurs en ligne peuvent utiliser /r"); if (op.getLastMessageTarget() == null) throw new MessageSendingException("Vous n'avez pas encore envoyé de message. Utilisez /msg"); inputMessage(sender, op.getLastMessageTarget(), message); } /** * @param sender l'origine du message * @param dest pseudo du destinataire ou "g:" suivi du nom du groupe destinataire (insensible à la casse) * @param message le message * @throws MessageSendingException */ public void inputMessage(MessageSender sender, String dest, String message) throws MessageSendingException { if (dest.startsWith("g:") || dest.startsWith("G:")) { // groupe String groupe = dest.substring(2); if (!AbstractCommandExecutor.isValidPlayerName(groupe)) throw new MessageSendingException("Le nom du groupe n'est pas valide (lettres, chiffres, §7_§r et entre 2 et 16 caractères)"); MPGroupElement groupEl = null; try { groupEl = ((MPGroupTable)ORM.getTable("mp_group")).getFirst("groupName LIKE '"+groupe+ "'", "id"); if (groupEl == null) throw new MessageSendingException("Ce groupe n'existe pas"); // on vérifie si le joueur source est dans le groupe if (sender.isPlayer()) { MPGroupUserElement userInGroup = ((MPGroupUserTable)ORM.getTable("mp_group_user")).getPlayerInGroup(groupEl, sender.senderName); if (userInGroup == null) throw new MessageSendingException("Vous n'êtes pas dans ce groupe"); } List<MPGroupUserElement> groupUsers = groupEl.getUsers(); long time = System.currentTimeMillis(); int secKey = new Random().nextInt(); for (MPGroupUserElement userInGroup : groupUsers) { MPMessageElement messEl = new MPMessageElement(time, secKey, userInGroup.getPlayerName(), sender.senderName, message, (userInGroup.getPlayerName().equalsIgnoreCase(sender.senderName)), true); messEl.setDestGroup(groupEl.getId()); messEl.save(); tryDisplayMessage(messEl); if (userInGroup.getPlayerName().equalsIgnoreCase(sender.senderName) || (!(sender.isPlayer()) && userInGroup == groupUsers.get(0))) // affiche aussi les messages provenant de la console, vers les groupes tryDisplayMessageToConsole(messEl); } if (sender.isPlayer()) { OnlinePlayer op = OnlinePlayerManager.get(plugin.getServer().getPlayer(sender.senderName)); if (op != null) op.setLastMessageTarget("g:"+groupEl.getGroupName()); } } catch (SQLException e) { e.printStackTrace(); throw new MessageSendingException("Erreur lors de la récupération du groupe ou de ses membres"); } } else { // joueur if (!AbstractCommandExecutor.isValidPlayerName(dest)) throw new MessageSendingException("Le pseudo n'est pas valide"); OffPlayer offP = new OffPlayer(dest); if (!offP.hasPlayedBefore()) { throw new MessageSendingException("Le joueur n'a jamais existé"); } String destUserName = offP.getCastCorrectedName(); long time = System.currentTimeMillis(); int secKey = new Random().nextInt(); if (sender.isPlayer() && !destUserName.equalsIgnoreCase(sender.senderName)) { MPMessageElement el = new MPMessageElement(time, secKey, sender.senderName, sender.senderName, message, true, true); el.setDestNick(destUserName); el.save(); tryDisplayMessage(el); } MPMessageElement elCible = new MPMessageElement(time, secKey, destUserName, sender.senderName, message, false, true); elCible.setDestNick(destUserName); elCible.save(); tryDisplayMessage(elCible); tryDisplayMessageToConsole(elCible); if (sender.isPlayer()) { OnlinePlayer op = OnlinePlayerManager.get(plugin.getServer().getPlayer(sender.senderName)); if (op != null) op.setLastMessageTarget(destUserName); } } } /** * * @param player le joueur qui veut voir ses messages non lus * @return vrai si le joueur a bien des messages non lu, faux sinon. Retourne vrai en cas d'erreur lors de la récupération des messages */ public boolean displayUnreadMessages(Player player) { try { List<MPMessageElement> messages = ((MPMessageTable)ORM.getTable("mp_message")).getAllUnreadForPlayer(player.getName()); if (messages.size() == 0) { player.sendMessage(ChatColor.GRAY+"Vous n'avez pas de messages non lus"); return false; } for(MPMessageElement mess : messages) tryDisplayMessage(mess); return true; } catch (SQLException e) { e.printStackTrace(); player.sendMessage(ChatColor.RED+"Impossible de lire les messages non lus"); return true; } } /** * Tente d'afficher le message dans le cas où le joueur cible est en ligne. Si ce * joueur est en ligne, le message est marqué comme lu. Si le joueur cible ignore * la source du message, la copie du message est supprimé de la base. * @param message le message à afficher */ private void tryDisplayMessage(MPMessageElement message) { try { OffPlayer offP = new OffPlayer(message.getViewerNick()); MessageSender sender = new MessageSender(message.getSourceNick()); boolean isIgnoring = sender.isPlayer() && offP.getEssentialsUser().isIgnoredPlayer(new OffPlayer(message.getSourceNick()).getEssentialsUser()); if (isIgnoring) { message.delete(); return; } OnlinePlayer op = OnlinePlayerManager.get(offP.getBukkitOnlinePlayer()); if (op == null) return; // la cible n'est pas en ligne if (!op.isAuthenticated()) return; // la cible n'a pas fait son /login message.setRead(true); message.save(); // le message est affiché sur l'écran de la source du message boolean dispToSender = (message.getViewerNick().equalsIgnoreCase(message.getSourceNick())); // ------- // tooltip // ------- Date d = new Date(message.getTime()); DateFormat date = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.FRANCE); DateFormat hour = DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.FRANCE); String affDate = date.format(d) + " à " + hour.format(d); List<String> tooltipLines = new ArrayList<String>(); tooltipLines.add(ChatColor.GRAY+affDate); tooltipLines.add(ChatColor.GRAY+"de "+ChatColor.RESET+new MessageSender(message.getSourceNick()).getDisplayName()+ChatColor.GRAY+" ("+displayablePlayerStatus(getPlayerStatut(message.getSourceNick()))+ChatColor.GRAY+")"); if (message.getDestGroup() == null) // vers un joueur tooltipLines.add(ChatColor.GRAY+"vers "+ChatColor.RESET+new OffPlayer(message.getDestNick()).getDisplayName()+ChatColor.GRAY+" ("+displayablePlayerStatus(getPlayerStatut(message.getDestNick()))+ChatColor.GRAY+")"); else { // vers un groupe MPGroupElement groupEl = message.getDestGroupElement(); tooltipLines.add(ChatColor.GRAY+"vers le groupe "+ChatColor.GOLD+groupEl.getGroupName()); List<MPGroupUserElement> groupUsers = groupEl.getUsers(); for (MPGroupUserElement gUser : groupUsers) { if (!gUser.getPlayerName().equalsIgnoreCase(message.getSourceNick())) tooltipLines.add(ChatColor.GRAY+"- "+ChatColor.RESET+new OffPlayer(gUser.getPlayerName()).getDisplayName()+ChatColor.GRAY+" ("+displayablePlayerStatus(getPlayerStatut(gUser.getPlayerName()))+ChatColor.GRAY+")"); } } // ------- if (dispToSender) { String destAff = (message.getDestGroup() == null)? ( (message.getDestNick().equalsIgnoreCase(message.getViewerNick())) ? "moi": new OffPlayer(message.getDestNick()).getDisplayName() ): ChatColor.GOLD+"g:"+message.getDestGroupElement().getGroupName(); String destCommand = (message.getDestGroup() == null)? message.getDestNick(): "g:"+message.getDestGroupElement().getGroupName(); tooltipLines.add(0, ChatColor.GRAY+"(Cliquez pour répondre)"); new FancyMessage("") .then("§6<§rmoi§6 → §r"+destAff+"§r§6>") .suggest("/m "+destCommand+" ") .tooltip(tooltipLines) .then(" §6"+ChatColor.translateAlternateColorCodes('&', message.getMessage()).replace("§r", "§r§6")) .color(ChatColor.GOLD) .send(op.getPlayer()); } else { String senderAff = new MessageSender(message.getSourceNick()).getDisplayName(); String destAff = (message.getDestGroup() == null)? ((message.getDestNick().equalsIgnoreCase(message.getViewerNick()))? "moi": new OffPlayer(message.getDestNick()).getDisplayName()): ChatColor.GOLD+"g:"+message.getDestGroupElement().getGroupName(); String destCommand = (message.getDestGroup() == null)? message.getSourceNick(): "g:"+message.getDestGroupElement().getGroupName(); if (message.getSourceNick() != null) tooltipLines.add(0, ChatColor.GRAY+"(Cliquez pour répondre)"); FancyMessage fm = new FancyMessage("") .then("§6<§r"+senderAff+"§r§6 → §r"+destAff+"§r§6>"); if (message.getSourceNick() != null) fm.suggest("/m "+destCommand+" "); fm.tooltip(tooltipLines) .then(" §6"+ChatColor.translateAlternateColorCodes('&', message.getMessage()).replace("§r", "§r§6")) .color(ChatColor.GOLD) .send(op.getPlayer()); // op.getPlayer().playSound(op.getPlayer().getLocation(), Sound.ORB_PICKUP, 1, 0.3F); } } catch (SQLException e) { plugin.getLogger().severe("Impossible d'afficher un message"); e.printStackTrace(); } } private void tryDisplayMessageToConsole(MPMessageElement message) { try { String senderAff = new MessageSender(message.getSourceNick()).getDisplayName(); String destAff = (message.getDestGroup() == null)? new OffPlayer(message.getDestNick()).getDisplayName(): "g:"+message.getDestGroupElement().getGroupName(); plugin.getServer().getConsoleSender().sendMessage("§6<§r"+senderAff+"§r§6 → §r"+destAff+"§r§6> §6"+ChatColor.translateAlternateColorCodes('&', message.getMessage()).replace("§r", "§r§6")); } catch (SQLException e) { plugin.getLogger().severe("Impossible d'afficher un message"); e.printStackTrace(); } } public void onxAuthLogin(xAuthLoginEvent event) { try { List<MPMessageElement> messages = ((MPMessageTable)ORM.getTable("mp_message")).getAllUnreadForPlayer(event.getPlayer().getName()); if (messages.size() == 0) return; String[] m = new String[] { ChatColor.GOLD+"--------------- Messagerie privée ---------------", ChatColor.GOLD+"Vous avez "+messages.size()+" message"+((messages.size()>1)?"s":"")+" non lu"+((messages.size()>1)?"s":""), ChatColor.GOLD+"Faites "+ChatColor.GRAY+"/m"+ChatColor.GOLD+" pour voir le"+((messages.size()>1)?"s":"")+" message"+((messages.size()>1)?"s":""), ChatColor.GOLD+"----------------------------------------------", }; event.getPlayer().sendMessage(m); } catch(SQLException e) { e.printStackTrace(); } } /** * * @param playerName le pseudo du joueur, insensible à la casse. * @return Le statut du joueur passé en paramètre.<br/> * <code>null</code> si le paramètre est <code>null</code>. */ private PlayerStatut getPlayerStatut(String playerName) { if (playerName == null) return null; if (!AbstractCommandExecutor.isValidPlayerName(playerName)) return PlayerStatut.OFFLINE; OnlinePlayer op = OnlinePlayerManager.get(playerName); if (op != null) return op.isAfk() ? PlayerStatut.AFK_IG : PlayerStatut.ONLINE_IG; try { MPWebSessionElement webSession = ((MPWebSessionTable)ORM.getTable("mp_web_session")).getFirst("playerName LIKE '"+playerName+"'", null); if (webSession != null) { long lastWebActivity = webSession.getLastWebActivity(); if (System.currentTimeMillis() - lastWebActivity < TIMEOUT_WEB_SESSION) return PlayerStatut.ONLINE_WEB; } } catch (SQLException e) { e.printStackTrace(); } return PlayerStatut.OFFLINE; } private String displayablePlayerStatus(PlayerStatut ps) { if (ps == PlayerStatut.ONLINE_IG) return ChatColor.GREEN+"En ligne, IG"; if (ps == PlayerStatut.AFK_IG) return ChatColor.YELLOW+"AFK, IG"; if (ps == PlayerStatut.ONLINE_WEB) return ChatColor.GOLD+"En ligne, web"; if (ps == PlayerStatut.OFFLINE) return ChatColor.GRAY+"Hors ligne"; return ChatColor.WHITE+"N/A"; } public enum PlayerStatut { ONLINE_IG, AFK_IG, ONLINE_WEB, OFFLINE } public static class MessageSender { public final String senderName; public MessageSender(String pName) { senderName = pName; } public MessageSender() { this((String)null); } public MessageSender(OffPlayer p) { this(p.getName()); } public MessageSender(CommandSender sender) { this((sender instanceof Player)?sender.getName():null); } public boolean isPlayer() { return senderName != null; } public String getDisplayName() { if (isPlayer()) return new OffPlayer(senderName).getDisplayName(); else return ChatColor.GOLD+"Système"+ChatColor.RESET; } } @SuppressWarnings("serial") public class MessageSendingException extends Exception { private MessageSendingException(String mess) { super(mess); } } }