Package com.ensifera.animosity.craftirc

Source Code of com.ensifera.animosity.craftirc.CraftIRC$RemoveHoldTask

package com.ensifera.animosity.craftirc;

import java.io.*;
import java.lang.StringBuilder;
import java.util.*;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.milkbowl.vault.chat.Chat;

import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;

import com.ensifera.animosity.craftirc.libs.com.sk89q.util.config.Configuration;
import com.ensifera.animosity.craftirc.libs.com.sk89q.util.config.ConfigurationNode;
import com.ensifera.animosity.craftirc.libs.org.jibble.pircbot.Colors;

/**
* @author Animosity
* @author ricin
* @author Protected
* @author mbaxter
*/
public class CraftIRC extends JavaPlugin {
    private Configuration configuration;

    //Misc class attributes
    private List<Minebot> instances;
    private boolean debug;
    private Timer holdTimer = new Timer();
    private Timer retryTimer = new Timer();
    private Map<HoldType, Boolean> hold;
    private String firstChannelTag;
    private boolean derpFakeExceptionSent = false;

    //Bots and channels config storage
    private List<ConfigurationNode> bots;
    private List<ConfigurationNode> colormap;
    private Map<Integer, List<ConfigurationNode>> channodes;
    private Map<Path, ConfigurationNode> paths;

    //Endpoints
    private Map<String, EndPoint> endpoints;
    private Map<EndPoint, String> tags;
    private Map<String, CommandEndPoint> irccmds;
    private Map<String, List<String>> taggroups;
    private Chat vault;

    //Replacement Filters
    private Map<String, Map<String, String>> replaceFilters;
    private boolean cancelChat;

    void log(String message) {
        this.getLogger().info(message);
    }

    void logWarn(String message) {
        this.getLogger().warning(message);
    }

    void logDerp(String message) {
        this.getLogger().severe(message);
        if (!this.derpFakeExceptionSent) {
            // show a fake exception, and get the users to hopefully notice this poor error
            (new Throwable("You made a mistake with your config. This is an error to get your attention. Don't report bugs for this.")).printStackTrace();
            this.derpFakeExceptionSent = true;
        }
    }

    /***************************
     * Bukkit stuff
     ***************************/

    @Override
    public void onEnable() {
        try {
            //Checking if the configuration file exists and imports the default one from the .jar if it doesn't
            final File configFile = new File(this.getDataFolder(), "config.yml");
            if (!configFile.exists()) {
                this.saveDefaultConfig();
                this.autoDisable();
                return;
            }
            this.derpFakeExceptionSent = false;
            this.configuration = new Configuration(configFile);
            this.configuration.load();
            this.cancelChat = this.configuration.getBoolean("settings.cancel-chat", false);

            this.endpoints = new HashMap<String, EndPoint>();
            this.tags = new HashMap<EndPoint, String>();
            this.irccmds = new HashMap<String, CommandEndPoint>();
            this.taggroups = new HashMap<String, List<String>>();

            this.bots = new ArrayList<ConfigurationNode>(this.configuration.getNodeList("bots", null));
            this.channodes = new HashMap<Integer, List<ConfigurationNode>>();
            for (int botID = 0; botID < this.bots.size(); botID++) {
                this.channodes.put(botID, new ArrayList<ConfigurationNode>(this.bots.get(botID).getNodeList("channels", null)));
            }

            this.colormap = new ArrayList<ConfigurationNode>(this.configuration.getNodeList("colormap", null));

            this.paths = new HashMap<Path, ConfigurationNode>();
            for (final ConfigurationNode path : this.configuration.getNodeList("paths", new LinkedList<ConfigurationNode>())) {
                final Path identifier = new Path(path.getString("source"), path.getString("target"));
                if (!identifier.getSourceTag().equals(identifier.getTargetTag()) && !this.paths.containsKey(identifier)) {
                    this.paths.put(identifier, path);
                }
            }
            if (this.cAutoPaths() && this.paths.size() > 0) {
                this.logDerp("Auto-paths are enabled but there are paths defined in the paths section of the config - this may cause unexpected behavior!");
            }

            //Replace filters
            this.replaceFilters = new HashMap<String, Map<String, String>>();
            try {
                for (String key : this.configuration.getNode("filters").getKeys()) {
                    //Map key to regex pattern, value to replacement.
                    Map<String, String> replaceMap = new HashMap<String, String>();
                    this.replaceFilters.put(key, replaceMap);
                    for (ConfigurationNode fieldNode : this.configuration.getNodeList("filters." + key, null)) {
                        Map<String, Object> patterns = fieldNode.getAll();
                        if (patterns != null)
                            for (String pattern : patterns.keySet())
                                replaceMap.put(pattern, patterns.get(pattern).toString());
                    }

                    //Also supports non-map entries.
                    for (String unMappedEntry : this.configuration.getStringList("filters." + key, null))
                        if (unMappedEntry.length() > 0 && unMappedEntry.charAt(0) != '{') //mapped toString() begins with {, but regex can't begin with {.
                            replaceMap.put(unMappedEntry, "");
                }
            } catch (NullPointerException e) {
            }

            //Retry timers
            this.retryTimer = new Timer();

            //Event listeners
            this.getServer().getPluginManager().registerEvents(new CraftIRCListener(this), this);
            this.getServer().getPluginManager().registerEvents(new ConsoleListener(this), this);

            //Native endpoints!
            if ((this.cMinecraftTag() != null) && !this.cMinecraftTag().equals("")) {
                this.registerEndPoint(this.cMinecraftTag(), new MinecraftPoint(this, this.getServer())); //The minecraft server, no bells and whistles
                for (final String cmd : this.cCmdWordSay(null)) {
                    this.registerCommand(this.cMinecraftTag(), cmd);
                }
                for (final String cmd : this.cCmdWordPlayers(null)) {
                    this.registerCommand(this.cMinecraftTag(), cmd);
                }
                if (!this.cMinecraftTagGroup().equals("")) {
                    this.groupTag(this.cMinecraftTag(), this.cMinecraftTagGroup());
                }
            } else {
                this.logDerp("No minecraft tag defined in the config file (settings.minecraft-tag)");
            }
            if ((this.cCancelledTag() != null) && !this.cCancelledTag().equals("")) {
                this.registerEndPoint(this.cCancelledTag(), new MinecraftPoint(this, this.getServer())); //Handles cancelled chat
                if (!this.cMinecraftTagGroup().equals("")) {
                    this.groupTag(this.cCancelledTag(), this.cMinecraftTagGroup());
                }
            }
            if ((this.cConsoleTag() != null) && !this.cConsoleTag().equals("")) {
                this.registerEndPoint(this.cConsoleTag(), new ConsolePoint(this, this.getServer())); //The minecraft console
                for (final String cmd : this.cCmdWordCmd(null)) {
                    this.registerCommand(this.cConsoleTag(), cmd);
                }
                if (!this.cMinecraftTagGroup().equals("")) {
                    this.groupTag(this.cConsoleTag(), this.cMinecraftTagGroup());
                }
            }

            //Create bots
            if (this.bots.size() == 0) {
                this.logDerp("No bots defined in the 'bots' section of the config file");
            }

            this.firstChannelTag = null;

            this.instances = new ArrayList<Minebot>();
            for (int i = 0; i < this.bots.size(); i++) {
                this.instances.add(new Minebot(this, i, this.cDebug()));
                if (this.channodes.get(i).size() == 0) {
                    this.logDerp("No channels defined for bot '" + this.cBotNickname(i) + "'. Check the config.");
                } else if (this.firstChannelTag == null) {
                    this.firstChannelTag = this.channodes.get(i).get(0).getString("tag");
                }
            }

            this.loadTagGroups();

            //Give these default values if they aren't defined
            //Ugly but there is no better way with this non-bukkit config
            this.configuration.getString("settings.formatting.from-game.players-list", "Online (%playerCount%/%maxPlayers%): %message%");
            this.configuration.getString("settings.formatting.from-game.players-nobody", "Nobody is minecrafting right now.");
            this.configuration.getString("settings.formatting.from-game.command-reply",
                this.configuration.getString("settings.formatting.from-game.generic", "%message%"));
            this.configuration.getBoolean("default-attributes.notices.admin", true);
            this.configuration.getBoolean("default-attributes.notices.private", true);

            if (this.configuration.getBoolean("default-attributes.disable", false)) {
                this.logDerp("All communication paths disabled because the 'disable' attribute was found. Check the config.");
            } else {
                this.log("Enabled.");
            }

            //Hold timers
            this.hold = new HashMap<HoldType, Boolean>();
            this.holdTimer = new Timer();
            if (this.cHold("chat") > 0) {
                this.hold.put(HoldType.CHAT, true);
                this.holdTimer.schedule(new RemoveHoldTask(this, HoldType.CHAT), this.cHold("chat"));
            } else {
                this.hold.put(HoldType.CHAT, false);
            }
            if (this.cHold("joins") > 0) {
                this.hold.put(HoldType.JOINS, true);
                this.holdTimer.schedule(new RemoveHoldTask(this, HoldType.JOINS), this.cHold("joins"));
            } else {
                this.hold.put(HoldType.JOINS, false);
            }
            if (this.cHold("quits") > 0) {
                this.hold.put(HoldType.QUITS, true);
                this.holdTimer.schedule(new RemoveHoldTask(this, HoldType.QUITS), this.cHold("quits"));
            } else {
                this.hold.put(HoldType.QUITS, false);
            }
            if (this.cHold("kicks") > 0) {
                this.hold.put(HoldType.KICKS, true);
                this.holdTimer.schedule(new RemoveHoldTask(this, HoldType.KICKS), this.cHold("kicks"));
            } else {
                this.hold.put(HoldType.KICKS, false);
            }
            if (this.cHold("bans") > 0) {
                this.hold.put(HoldType.BANS, true);
                this.holdTimer.schedule(new RemoveHoldTask(this, HoldType.BANS), this.cHold("bans"));
            } else {
                this.hold.put(HoldType.BANS, false);
            }
            if (this.cHold("deaths") > 0) {
                this.hold.put(HoldType.DEATHS, true);
                this.holdTimer.schedule(new RemoveHoldTask(this, HoldType.DEATHS), this.cHold("deaths"));
            } else {
                this.hold.put(HoldType.DEATHS, false);
            }

            if (CraftIRC.this.getServer().getPluginManager().isPluginEnabled("Vault")) {
                this.loadVault();
            }

            this.setDebug(this.cDebug());
        } catch (final Exception e) {
            e.printStackTrace();
        }
        try {
            new Metrics(this).start();
        } catch (final IOException e) {
            //Meh.
        }
    }

    private void loadVault() {
        RegisteredServiceProvider<Chat> rsp = CraftIRC.this.getServer().getServicesManager().getRegistration(Chat.class);
        if (rsp != null) {
            this.vault = rsp.getProvider();
        }
    }

    private void autoDisable() {
        this.log("Auto-disabling...");
        this.getServer().getPluginManager().disablePlugin(this);
    }

    @Override
    public void onDisable() {
        try {
            this.retryTimer.cancel();
            this.holdTimer.cancel();
            //Disconnect bots
            if (this.bots != null) {
                for (int i = 0; i < this.bots.size(); i++) {
                    this.instances.get(i).disconnect();
                    this.instances.get(i).dispose();
                }
            }
            this.log("Disabled.");
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }

    /***************************
     * Minecraft command handling
     ***************************/

    @Override
    public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) {
        final String commandName = command.getName().toLowerCase();

        try {
            if (commandName.equals("ircsay")) {
                if (!sender.hasPermission("craftirc." + commandName)) {
                    return false;
                }
                return this.cmdMsgSay(sender, args);
            }
            if (commandName.equals("ircmsg")) {
                if (!sender.hasPermission("craftirc." + commandName)) {
                    return false;
                }
                return this.cmdMsgToTag(sender, args);
            } else if (commandName.equals("ircmsguser")) {
                if (!sender.hasPermission("craftirc." + commandName)) {
                    return false;
                }
                return this.cmdMsgToUser(sender, args);
            } else if (commandName.equals("ircusers")) {
                if (!sender.hasPermission("craftirc." + commandName)) {
                    return false;
                }
                return this.cmdGetUserList(sender, args);
            } else if (commandName.equals("admins!")) {
                if (!sender.hasPermission("craftirc.admins")) {
                    return false;
                }
                return this.cmdNotifyIrcAdmins(sender, args);
            } else if (commandName.equals("ircraw")) {
                if (!sender.hasPermission("craftirc." + commandName)) {
                    return false;
                }
                return this.cmdRawIrcCommand(sender, args);
            } else if (commandName.equals("ircreload")) {
                if (!sender.hasPermission("craftirc." + commandName)) {
                    return false;
                }
                this.getServer().getPluginManager().disablePlugin(this);
                this.getServer().getPluginManager().enablePlugin(this);
                return true;
            } else {
                return false;
            }
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean cmdMsgSay(CommandSender sender, String[] args) {
        if (args.length == 0) {
            return false;
        }
        try {
            RelayedMessage msg = this.newMsg(this.getEndPoint(this.cMinecraftTag()), null, "chat");
            if (msg == null) {
                return false;
            }
            String senderName = sender.getName();
            String world = "";
            String prefix = "";
            String suffix = "";
            if (sender instanceof Player) {
                Player player = (Player) sender;
                senderName = player.getDisplayName();
                world = player.getWorld().getName();
                prefix = this.getPrefix(player);
                suffix = this.getSuffix(player);
            }
            msg.setField("sender", senderName);
            msg.setField("message", Util.combineSplit(0, args, " "));
            msg.setField("world", world);
            msg.setField("realSender", sender.getName());
            msg.setField("prefix", prefix);
            msg.setField("suffix", suffix);
            msg.doNotColor("message");
            msg.post();
            return true;
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean cmdMsgToTag(CommandSender sender, String[] args) {
        try {
            if (this.isDebug()) {
                this.log("CraftIRCListener cmdMsgToAll()");
            }
            if (args.length < 2) {
                return false;
            }
            final String msgToSend = Util.combineSplit(1, args, " ");
            final RelayedMessage msg = this.newMsg(this.getEndPoint(this.cMinecraftTag()), this.getEndPoint(args[0]), "chat");
            if (msg == null) {
                return true;
            }
            if (sender instanceof Player) {
                msg.setField("sender", ((Player) sender).getDisplayName());
            } else {
                msg.setField("sender", sender.getName());
            }
            msg.setField("message", msgToSend);
            msg.doNotColor("message");
            msg.post();
            sender.sendMessage("Message sent.");
            return true;
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean cmdMsgToUser(CommandSender sender, String[] args) {
        try {
            if (args.length < 3) {
                return false;
            }
            final String msgToSend = Util.combineSplit(2, args, " ");
            final RelayedMessage msg = this.newMsg(this.getEndPoint(this.cMinecraftTag()), this.getEndPoint(args[0]), "private");
            if (msg == null) {
                return true;
            }
            if (sender instanceof Player) {
                msg.setField("sender", ((Player) sender).getDisplayName());
            } else {
                msg.setField("sender", sender.getName());
            };
            msg.setField("message", msgToSend);
            msg.doNotColor("message");
            boolean sameEndPoint = this.getEndPoint(this.cMinecraftTag()).equals(this.getEndPoint(args[0]));
            //Don't actually deliver the message if the user is invisible to the sender.
            if (sameEndPoint && sender instanceof Player) {
                Player recipient = getServer().getPlayer(args[1]);
                if (recipient != null && recipient.isOnline() && ((Player) sender).canSee(recipient))
                    msg.postToUser(args[1]);
            } else
                msg.postToUser(args[1]);
            sender.sendMessage("Message sent.");
            return true;
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean cmdGetUserList(CommandSender sender, String[] args) {
        try {
            final String tag = (args.length == 0) ? this.firstChannelTag : args[0];
            final List<String> userlists = this.ircUserLists(tag);
            if (userlists == null) {
                sender.sendMessage("Unknown tag");
                return false;
            }
            sender.sendMessage("Users in " + tag + " (" + userlists.size() + "):");

            StringBuilder builder = new StringBuilder();
            boolean first = true;

            for (final String string : userlists) {
                if (!first) {
                    builder.append(", ");
                }
                builder.append(string);
                first = false;
            }
            sender.sendMessage(builder.toString());
            return true;
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean cmdNotifyIrcAdmins(CommandSender sender, String[] args) {
        try {
            if (this.isDebug()) {
                this.log("CraftIRCListener cmdNotifyIrcAdmins()");
            }
            if ((args.length == 0) || !(sender instanceof Player)) {
                if (this.isDebug()) {
                    this.log("CraftIRCListener cmdNotifyIrcAdmins() - args.length == 0 or Sender != player ");
                }
                return false;
            }
            final RelayedMessage msg = this.newMsg(this.getEndPoint(this.cMinecraftTag()), null, "admin");
            if (msg == null) {
                return true;
            }
            msg.setField("sender", ((Player) sender).getDisplayName());
            msg.setField("message", Util.combineSplit(0, args, " "));
            msg.setField("world", ((Player) sender).getWorld().getName());
            msg.doNotColor("message");
            msg.post(true);
            sender.sendMessage("Admin notice sent.");
            return true;
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private boolean cmdRawIrcCommand(CommandSender sender, String[] args) {
        try {
            if (this.isDebug()) {
                this.log("cmdRawIrcCommand(sender=" + sender.toString() + ", args=" + Util.combineSplit(0, args, " "));
            }
            if (args.length < 2) {
                return false;
            }
            this.sendRawToBot(Util.combineSplit(1, args, " "), Integer.parseInt(args[0]));
            return true;
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /***************************
     * Endpoint and message interface (to be used by CraftIRC and external plugins)
     ***************************/

    /**
     * Null target: Sends message through all possible paths.
     *
     * @param source
     * @param target
     * @param eventType
     * @return
     */
    public RelayedMessage newMsg(EndPoint source, EndPoint target, String eventType) {
        if (source == null) {
            return null;
        }
        if ((target == null) || this.cPathExists(this.getTag(source), this.getTag(target))) {
            return new RelayedMessage(this, source, target, eventType);
        } else {
            if (this.isDebug()) {
                this.log("Failed to prepare message: " + this.getTag(source) + " -> " + this.getTag(target) + " (missing path)");
            }
            return null;
        }
    }

    public RelayedMessage newMsgToTag(EndPoint source, String target, String eventType) {
        if (source == null) {
            return null;
        }
        EndPoint targetpoint = null;
        if (target != null) {
            if (this.cPathExists(this.getTag(source), target)) {
                targetpoint = this.getEndPoint(target);
                if (targetpoint == null) {
                    this.log("The requested target tag '" + target + "' isn't registered.");
                }
            } else {
                return null;
            }
        }
        return new RelayedMessage(this, source, targetpoint, eventType);
    }

    public RelayedCommand newCmd(EndPoint source, String command) {
        if (source == null) {
            return null;
        }
        final CommandEndPoint target = this.irccmds.get(command);
        if (target == null) {
            return null;
        }
        if (!this.cPathExists(this.getTag(source), this.getTag(target))) {
            return null;
        }
        final RelayedCommand cmd = new RelayedCommand(this, source, target);
        cmd.setField("command", command);
        return cmd;
    }

    public boolean registerEndPoint(String tag, EndPoint ep) {
        if (!this.isEnabled()) {
            this.getLogger().log(Level.WARNING, "CraftIRC EndPoints cannot be registered while CraftIRC is disabled", new Throwable());
            return false;
        }
        if (this.isDebug()) {
            this.log("Registering endpoint: " + tag);
        }
        if (tag == null) {
            this.log("Failed to register endpoint - No tag!");
            return false;
        }
        if ((this.endpoints.get(tag) != null) || (this.tags.get(ep) != null)) {
            this.log("Couldn't register an endpoint tagged '" + tag + "' because either the tag or the endpoint already exist.");
            return false;
        }
        if (tag == "*") {
            this.log("Couldn't register an endpoint - the character * can't be used as a tag.");
            return false;
        }
        this.endpoints.put(tag, ep);
        this.tags.put(ep, tag);
        return true;
    }

    public boolean endPointRegistered(String tag) {
        return this.endpoints.get(tag) != null;
    }

    public EndPoint getEndPoint(String tag) {
        return this.endpoints.get(tag);
    }

    public String getTag(EndPoint ep) {
        return this.tags.get(ep);
    }

    public boolean registerCommand(String tag, String command) {
        if (this.isDebug()) {
            this.log("Registering command: " + command + " to endpoint:" + tag);
        }
        final EndPoint ep = this.getEndPoint(tag);
        if (ep == null) {
            this.log("Couldn't register the command '" + command + "' at the endpoint tagged '" + tag + "' because there is no such tag.");
            return false;
        }
        if (!(ep instanceof CommandEndPoint)) {
            this.log("Couldn't register the command '" + command + "' at the endpoint tagged '" + tag + "' because it's not capable of handling commands.");
            return false;
        }
        if (this.irccmds.containsKey(command)) {
            this.log("Couldn't register the command '" + command + "' at the endpoint tagged '" + tag + "' because that command is already registered.");
            return false;
        }
        this.irccmds.put(command, (CommandEndPoint) ep);
        return true;
    }

    public boolean unregisterCommand(String command) {
        if (!this.irccmds.containsKey(command)) {
            return false;
        }
        if (this.isDebug()) {
            this.log("Unregistering command: " + command);
        }
        this.irccmds.remove(command);
        return true;
    }

    public boolean unregisterEndPoint(String tag) {
        final EndPoint ep = this.getEndPoint(tag);
        if (ep == null) {
            return false;
        }
        if (this.isDebug()) {
            this.log("Unregistering endpoint: " + tag);
        }
        this.endpoints.remove(tag);
        this.tags.remove(ep);
        this.ungroupTag(tag);
        if (ep instanceof CommandEndPoint) {
            final CommandEndPoint cep = (CommandEndPoint) ep;
            for (final String cmd : this.irccmds.keySet()) {
                if (this.irccmds.get(cmd) == cep) {
                    this.irccmds.remove(cmd);
                }
            }
        }
        return true;
    }

    public boolean groupTag(String tag, String group) {
        if (this.getEndPoint(tag) == null) {
            return false;
        }
        List<String> tags = this.taggroups.get(group);
        if (tags == null) {
            tags = new ArrayList<String>();
            this.taggroups.put(group, tags);
        }
        tags.add(tag);
        return true;
    }

    public void ungroupTag(String tag) {
        for (final String group : this.taggroups.keySet()) {
            this.taggroups.get(group).remove(tag);
        }
    }

    public void clearGroup(String group) {
        this.taggroups.remove(group);
    }

    public boolean checkTagsGrouped(String tagA, String tagB) {
        for (final String group : this.taggroups.keySet()) {
            if (this.taggroups.get(group).contains(tagA) && this.taggroups.get(group).contains(tagB)) {
                return true;
            }
        }
        return false;
    }

    /***************************
     * Heart of the beast! Unified method with no special cases that replaces the old sendMessage
     ***************************/

    boolean delivery(RelayedMessage msg) {
        return this.delivery(msg, null, null, RelayedMessage.DeliveryMethod.STANDARD);
    }

    boolean delivery(RelayedMessage msg, List<EndPoint> destinations) {
        return this.delivery(msg, destinations, null, RelayedMessage.DeliveryMethod.STANDARD);
    }

    boolean delivery(RelayedMessage msg, List<EndPoint> knownDestinations, String username) {
        return this.delivery(msg, knownDestinations, username, RelayedMessage.DeliveryMethod.STANDARD);
    }

    /**
     * Only successful if all known targets (or if there is none at least one possible target) are successful!
     *
     * @param msg
     * @param knownDestinations
     * @param username
     * @param dm
     * @return
     */
    boolean delivery(RelayedMessage msg, List<EndPoint> knownDestinations, String username, RelayedMessage.DeliveryMethod dm) {
        final String sourceTag = this.getTag(msg.getSource());
        msg.setField("source", sourceTag);
        List<EndPoint> destinations;
        if (this.isDebug()) {
            this.log("X->" + (knownDestinations.size() > 0 ? knownDestinations.toString() : "*") + ": " + msg.toString());
        }
        //If we weren't explicitly given a recipient for the message, let's try to find one (or more)
        if (knownDestinations.size() < 1) {
            //Use all possible destinations (auto-targets)
            destinations = new LinkedList<EndPoint>();
            for (final String targetTag : this.cPathsFrom(sourceTag)) {
                final EndPoint ep = this.getEndPoint(targetTag);
                if (ep == null) {
                    continue;
                }
                if ((ep instanceof SecuredEndPoint) && SecuredEndPoint.Security.REQUIRE_TARGET.equals(((SecuredEndPoint) ep).getSecurity())) {
                    continue;
                }
                if (!this.cPathAttribute(sourceTag, targetTag, "attributes." + msg.getEvent())) {
                    continue;
                }
                if ((dm == RelayedMessage.DeliveryMethod.ADMINS) && !this.cPathAttribute(sourceTag, targetTag, "attributes.admin")) {
                    continue;
                }
                destinations.add(ep);
            }
            //Default paths to unsecured destinations (auto-paths)
            if (this.cAutoPaths()) {
                for (final EndPoint ep : this.endpoints.values()) {
                    if (ep == null) {
                        continue;
                    }
                    if (msg.getSource().equals(ep) || destinations.contains(ep)) {
                        continue;
                    }
                    if ((ep instanceof SecuredEndPoint) && !SecuredEndPoint.Security.UNSECURED.equals(((SecuredEndPoint) ep).getSecurity())) {
                        continue;
                    }
                    final String targetTag = this.getTag(ep);
                    if (this.checkTagsGrouped(sourceTag, targetTag)) {
                        continue;
                    }
                    if (!this.cPathAttribute(sourceTag, targetTag, "attributes." + msg.getEvent())) {
                        continue;
                    }
                    if ((dm == RelayedMessage.DeliveryMethod.ADMINS) && !this.cPathAttribute(sourceTag, targetTag, "attributes.admin")) {
                        continue;
                    }
                    if (this.cPathAttribute(sourceTag, targetTag, "disable")) {
                        continue;
                    }
                    destinations.add(ep);
                }
            }
        } else {
            destinations = new LinkedList<EndPoint>(knownDestinations);
        }
        if (destinations.size() < 1) {
            return false;
        }
        //Deliver the message
        boolean success = true;
        for (final EndPoint destination : destinations) {
            final String targetTag = this.getTag(destination);
            if (targetTag.equals(this.cCancelledTag())) {
                continue;
            }
            msg.setField("target", targetTag);

            //Whether the event should be sent as a NOTICE on irc endpoints or not (Ignored in others)
            msg.setFlag("notice", this.cPathAttribute(sourceTag, targetTag, "notices." + msg.getEvent()));

            //Check against path filters
            if (this.matchesFilter(msg, this.cPathFilters(sourceTag, targetTag))) {
                if (knownDestinations != null) {
                    success = false;
                }
                continue;
            }
            //Finally deliver!
            if (this.isDebug()) {
                this.log("-->X: " + msg.toString());
            }
            if (username != null) {
                success = success && destination.userMessageIn(username, msg);
            } else if (dm == RelayedMessage.DeliveryMethod.ADMINS) {
                success = destination.adminMessageIn(msg);
            } else if (dm == RelayedMessage.DeliveryMethod.COMMAND) {
                if (!(destination instanceof CommandEndPoint)) {
                    continue;
                }
                ((CommandEndPoint) destination).commandIn((RelayedCommand) msg);
            } else {
                destination.messageIn(msg);
            }
        }
        return success;
    }

    boolean matchesFilter(RelayedMessage msg, List<ConfigurationNode> filters) {
        if (filters == null) {
            return false;
        }
        newFilter: for (final ConfigurationNode filter : filters) {
            for (final String key : filter.getKeys()) {
                final Pattern condition = Pattern.compile(filter.getString(key, ""));
                if (condition == null) {
                    continue newFilter;
                }
                final String subject = msg.getField(key);
                if (subject == null) {
                    continue newFilter;
                }
                final Matcher check = condition.matcher(subject);
                if (!check.find()) {
                    continue newFilter;
                }
            }
            return true;
        }
        return false;
    }

    /***************************
     * Auxiliary methods
     ***************************/

    public Minebot getBot(int bot) {
        return this.instances.get(bot);
    }

    public int getNumBots() {
        return this.instances.size();
    }

    public void sendRawToBot(String rawMessage, int bot) {
        if (this.isDebug()) {
            this.log("sendRawToBot(bot=" + bot + ", message=" + rawMessage);
        }
        final Minebot targetBot = this.instances.get(bot);
        targetBot.sendRawLineViaQueue(rawMessage);
    }

    public void sendMsgToTargetViaBot(String message, String target, int bot) {
        final Minebot targetBot = this.instances.get(bot);
        targetBot.sendMessage(target, message);
    }

    public List<String> ircUserLists(String tag) {
        final EndPoint endpoint = this.getEndPoint(tag);
        if (endpoint != null) {
            return endpoint.listDisplayUsers();
        } else {
            return null;
        }
    }

    void setDebug(boolean d) {
        this.debug = d;

        for (int i = 0; i < this.bots.size(); i++) {
            this.instances.get(i).setVerbose(d);
        }

        this.log("DEBUG [" + (d ? "ON" : "OFF") + "]");
    }

    public String getPrefix(Player p) {
        String result = "";
        if (this.vault != null) {
            try {
                result = this.vault.getPlayerPrefix(p);
            } catch (final Exception e) {

            }
        }
        return result;
    }

    public String getSuffix(Player p) {
        String result = "";
        if (this.vault != null) {
            try {
                result = this.vault.getPlayerSuffix(p);
            } catch (final Exception e) {

            }
        }
        return result;
    }

    public boolean isDebug() {
        return this.debug;
    }

    boolean checkPerms(Player pl, String path) {
        return pl.hasPermission(path);
    }

    boolean checkPerms(String pl, String path) {
        final Player pit = this.getServer().getPlayer(pl);
        if (pit != null) {
            return pit.hasPermission(path);
        }
        return false;
    }

    protected void enqueueConsoleCommand(String cmd) {
        try {
            this.getServer().dispatchCommand(this.getServer().getConsoleSender(), cmd);
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * If the channel is null it's a reconnect, otherwise a rejoin
     *
     * @param bot
     * @param channel
     */
    void scheduleForRetry(Minebot bot, String channel) {
        this.retryTimer.schedule(new RetryTask(this, bot, channel), this.cRetryDelay());
    }

    /***************************
     * Read stuff from config
     ***************************/

    private ConfigurationNode getChanNode(int bot, String channel) {
        for (final ConfigurationNode chan : this.channodes.get(bot)) {
            if (chan.getString("name").equalsIgnoreCase(channel)) {
                return chan;
            }
        }
        return Configuration.getEmptyNode();
    }

    public boolean cLog() {
        return this.configuration.getBoolean("settings.log", true);
    }

    public List<ConfigurationNode> cChannels(int bot) {
        return this.channodes.get(bot);
    }

    private ConfigurationNode getPathNode(String source, String target) {
        ConfigurationNode result = this.paths.get(new Path(source, target));
        if (result == null) {
            return this.configuration.getNode("default-attributes");
        }
        ConfigurationNode basepath;
        if (result.getKeys().contains("base") && ((basepath = result.getNode("base")) != null)) {
            final ConfigurationNode basenode = this.paths.get(new Path(basepath.getString("source", ""), basepath.getString("target", "")));
            if (basenode != null) {
                result = basenode;
            }
        }
        return result;
    }

    public String cMinecraftTag() {
        return this.configuration.getString("settings.minecraft-tag", "minecraft");
    }

    public String cCancelledTag() {
        return this.configuration.getString("settings.cancelled-tag", "cancelled");
    }

    public String cConsoleTag() {
        return this.configuration.getString("settings.console-tag", "console");
    }

    public String cMinecraftTagGroup() {
        return this.configuration.getString("settings.minecraft-group-name", "minecraft");
    }

    public String cIrcTagGroup() {
        return this.configuration.getString("settings.irc-group-name", "irc");
    }

    public boolean cAutoPaths() {
        return this.configuration.getBoolean("settings.auto-paths", false);
    }

    public boolean cCancelChat() {
        return cancelChat;
    }

    public boolean cDebug() {
        return this.configuration.getBoolean("settings.debug", false);
    }

    public String cStoppedRespondingMessage() {
        return this.configuration.getString("settings.stopped-responding-message", "The server appears to have stopped responding.");
    }

    public ArrayList<String> cConsoleCommands() {
        return new ArrayList<String>(this.configuration.getStringList("settings.console-commands", null));
    }

    public int cHold(String eventType) {
        return this.configuration.getInt("settings.hold-after-enable." + eventType, 0);
    }

    public String cFormatting(String eventType, RelayedMessage msg) {
        return this.cFormatting(eventType, msg, null);
    }

    public String cFormatting(String eventType, RelayedMessage msg, EndPoint realTarget) {
        final String source = this.getTag(msg.getSource()), target = this.getTag(realTarget != null ? realTarget : msg.getTarget());
        if ((source == null) || (target == null)) {
            this.logWarn("Attempted to obtain formatting for invalid path " + source + " -> " + target + " .");
            return this.cDefaultFormatting(eventType, msg);
        }
        final ConfigurationNode pathConfig = this.paths.get(new Path(source, target));
        if ((pathConfig != null) && (pathConfig.getString("formatting." + eventType, null) != null)) {
            return pathConfig.getString("formatting." + eventType, null);
        } else {
            return this.cDefaultFormatting(eventType, msg);
        }
    }

    public String cDefaultFormatting(String eventType, RelayedMessage msg) {
        String source;
        switch (msg.getSource().getType()) {
            case MINECRAFT:
                source = "game";
                break;
            case IRC:
                source = "irc";
                break;
            default:
                source = "plain";
        }
        String lookup = "settings.formatting.from-" + source + "." + eventType;
        String result = this.configuration.getString(lookup);

        if (result == null) {
            this.logWarn("Could not find record " + lookup);
            result = "Error: See CraftIRC console";
        }
        return result;
    }

    public String cColorIrcNormalize(String color) {
        //Forces sending two digit colour codes.
        //As a function because it's more handy to use like this.
        return (color.length() == 1 ? "0" : "") + color;
    }

    public String cColorIrcFromGame(String game) {
        ConfigurationNode color;
        final Iterator<ConfigurationNode> it = this.colormap.iterator();
        String c = null;
        while (it.hasNext()) {
            color = it.next();
            if (color.getString("game").equals(game)) {
                c = this.cColorIrcNormalize(color.getString("irc", this.cColorIrcFromName("foreground")));
                break;
            }
        }
        if (c == null) {
            c = this.cColorIrcFromName("foreground");
        }
        return c.equals("-1") ? Colors.NORMAL : "\u0003" + c;
    }

    public String cColorIrcFromName(String name) {
        ConfigurationNode color;
        final Iterator<ConfigurationNode> it = this.colormap.iterator();
        while (it.hasNext()) {
            color = it.next();
            if (color.getString("name").equalsIgnoreCase(name) && (color.getProperty("irc") != null)) {
                return this.cColorIrcNormalize(color.getString("irc", "01"));
            }
        }
        if (name.equalsIgnoreCase("foreground")) {
            return "01";
        } else {
            return this.cColorIrcFromName("foreground");
        }
    }

    public String cColorGameFromIrc(String irc) {
        irc = this.cColorIrcNormalize(irc);
        ConfigurationNode color;
        final Iterator<ConfigurationNode> it = this.colormap.iterator();
        while (it.hasNext()) {
            color = it.next();
            //Enforce two digit comparisons.
            if (color.getString("irc", "").equals(irc) || "0".concat(color.getString("irc", "")).equals(irc)) {
                return color.getString("game", this.cColorGameFromName("foreground"));
            }
        }
        return this.cColorGameFromName("foreground");
    }

    public String cColorGameFromName(String name) {
        ConfigurationNode color;
        final Iterator<ConfigurationNode> it = this.colormap.iterator();
        while (it.hasNext()) {
            color = it.next();
            if (color.getString("name").equalsIgnoreCase(name) && (color.getProperty("game") != null)) {
                return color.getString("game", "\u00C2\u00A7f");
            }
        }
        if (name.equalsIgnoreCase("foreground")) {
            return "\u00C2\u00A7f";
        } else {
            return this.cColorGameFromName("foreground");
        }
    }

    public String cBindLocalAddr() {
        return this.configuration.getString("settings.bind-address", "");
    }

    public int cRetryDelay() {
        return this.configuration.getInt("settings.retry-delay", 10) * 1000;
    }

    public String cBotEncoding(int bot) {
        return this.bots.get(bot).getString("encoding", "UTF-8");
    }

    public String cBotNickname(int bot) {
        return this.bots.get(bot).getString("nickname", "CraftIRCbot");
    }

    public String cBotServer(int bot) {
        return this.bots.get(bot).getString("server", "localhost");
    }

    public int cBotPort(int bot) {
        return this.bots.get(bot).getInt("port", 6667);
    }

    public int cBotBindPort(int bot) {
        return this.bots.get(bot).getInt("bind-port", 0);
    }

    public String cBotLogin(int bot) {
        return this.bots.get(bot).getString("userident", "");
    }

    public String cBotPassword(int bot) {
        return this.bots.get(bot).getString("serverpass", "");
    }

    public boolean cBotSsl(int bot) {
        return this.bots.get(bot).getBoolean("ssl", false);
    }

    public int cBotMessageDelay(int bot) {
        return this.bots.get(bot).getInt("message-delay", 1000);
    }

    public int cBotQueueSize(int bot) {
        return this.bots.get(bot).getInt("queue-size", 5);
    }

    public String cCommandPrefix(int bot) {
        return this.bots.get(bot).getString("command-prefix", this.configuration.getString("settings.command-prefix", "."));
    }

    public List<String> cCmdWordCmd(Integer bot) {
        return this.cCmdWord(bot, "cmd");
    }

    public List<String> cCmdWordSay(Integer bot) {
        return this.cCmdWord(bot, "say");
    }

    public List<String> cCmdWordPlayers(Integer bot) {
        return this.cCmdWord(bot, "players");
    }

    public List<String> cCmdWord(Integer bot, String command) {
        final List<String> result = this.cCmdWord(command);
        if (bot != null) {
            return this.bots.get(bot).getStringList("irc-commands." + command, result);
        }
        return result;
    }

    public List<String> cCmdWord(String command) {
        final List<String> init = new ArrayList<String>();
        init.add(command);
        return this.configuration.getStringList("settings.irc-commands." + command, init);
    }

    public boolean cCmdPrivate(String command) {
        return this.configuration.getBoolean("settings.private-commands." + command, false);
    }

    public ArrayList<String> cBotAdminPrefixes(int bot) {
        return new ArrayList<String>(this.bots.get(bot).getStringList("admin-prefixes", null));
    }

    public ArrayList<String> cBotIgnoredUsers(int bot) {
        return new ArrayList<String>(this.bots.get(bot).getStringList("ignored-users", null));
    }

    public String cBotAuthMethod(int bot) {
        return this.bots.get(bot).getString("auth.method", "nickserv");
    }

    public String cBotAuthUsername(int bot) {
        return this.bots.get(bot).getString("auth.username", "");
    }

    public String cBotAuthPassword(int bot) {
        return this.bots.get(bot).getString("auth.password", "");
    }

    public int cBotAuthDelay(int bot) {
        int delay = this.bots.get(bot).getInt("auth.delay", 0);
        if (delay < 0) {
            delay = 0;
        }
        return delay;
    }

    public ArrayList<String> cBotOnConnect(int bot) {
        return new ArrayList<String>(this.bots.get(bot).getStringList("on-connect", null));
    }

    public boolean cChanForceColors(int bot, String channel) {
        return this.getChanNode(bot, channel).getBoolean("force-colors", false);
    }

    public String cChanName(int bot, String channel) {
        return this.getChanNode(bot, channel).getString("name", "#changeme");
    }

    public String cChanTag(int bot, String channel) {
        return this.getChanNode(bot, channel).getString("tag", String.valueOf(bot) + "_" + channel);
    }

    public String cChanPassword(int bot, String channel) {
        return this.getChanNode(bot, channel).getString("password", "");
    }

    public ArrayList<String> cChanOnJoin(int bot, String channel) {
        return new ArrayList<String>(this.getChanNode(bot, channel).getStringList("on-join", null));
    }

    public List<String> cPathsFrom(String source) {
        final List<String> results = new LinkedList<String>();
        for (final Path path : this.paths.keySet()) {
            if (!path.getSourceTag().equals(source)) {
                continue;
            }
            if (this.paths.get(path).getBoolean("disable", false)) {
                continue;
            }
            results.add(path.getTargetTag());
        }
        return results;
    }

    List<String> cPathsTo(String target) {
        final List<String> results = new LinkedList<String>();
        for (final Path path : this.paths.keySet()) {
            if (!path.getTargetTag().equals(target)) {
                continue;
            }
            if (this.paths.get(path).getBoolean("disable", false)) {
                continue;
            }
            results.add(path.getSourceTag());
        }
        return results;
    }

    public boolean cPathExists(String source, String target) {
        final ConfigurationNode pathNode = this.getPathNode(source, target);
        return (pathNode != null) && !pathNode.getBoolean("disable", false);
    }

    public boolean cPathAttribute(String source, String target, String attribute) {
        final ConfigurationNode node = this.getPathNode(source, target);
        if (node.getProperty(attribute) != null) {
            return node.getBoolean(attribute, false);
        } else {
            return this.configuration.getNode("default-attributes").getBoolean(attribute, false);
        }
    }

    public List<ConfigurationNode> cPathFilters(String source, String target) {
        return this.getPathNode(source, target).getNodeList("filters", new ArrayList<ConfigurationNode>());
    }

    public Map<String, Map<String, String>> cReplaceFilters() {
        return this.replaceFilters;
    }

    void loadTagGroups() {
        final List<String> groups = this.configuration.getKeys("settings.tag-groups");
        if (groups == null) {
            return;
        }
        for (final String group : groups) {
            for (final String tag : this.configuration.getStringList("settings.tag-groups." + group, new ArrayList<String>())) {
                this.groupTag(tag, group);
            }
        }
    }

    boolean cUseMapAsWhitelist(int bot) {
        return this.bots.get(bot).getBoolean("use-map-as-whitelist", false);
    }

    public String cIrcDisplayName(int bot, String nickname) {
        return this.bots.get(bot).getString("irc-nickname-map." + nickname, nickname);
    }

    public boolean cNicknameIsInIrcMap(int bot, String nickname) {
        return this.bots.get(bot).getString("irc-nickname-map." + nickname) != null;
    }

    public enum HoldType {
        CHAT,
        JOINS,
        QUITS,
        KICKS,
        BANS,
        DEATHS
    }

    class RemoveHoldTask extends TimerTask {
        private final CraftIRC plugin;
        private final HoldType ht;

        protected RemoveHoldTask(CraftIRC plugin, HoldType ht) {
            super();
            this.plugin = plugin;
            this.ht = ht;
        }

        @Override
        public void run() {
            this.plugin.hold.put(this.ht, false);
        }
    }

    public boolean isHeld(HoldType ht) {
        return this.hold.get(ht);
    }

    public List<ConfigurationNode> getColorMap() {
        return this.colormap;
    }

    public String processAntiHighlight(String input) {
        String delimiter = this.configuration.getString("settings.anti-highlight");

        if (delimiter != null && !delimiter.isEmpty()) {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < input.length(); i++) {
                char c = input.charAt(i);
                builder.append(c);
                if (c != '\u00A7') {
                    builder.append(delimiter);
                }
            }
            return builder.toString();
        } else {
            return input;
        }
    }
}
TOP

Related Classes of com.ensifera.animosity.craftirc.CraftIRC$RemoveHoldTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.