import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.lang3.tuple.ImmutablePair; import org.pircbotx.PircBotX; import org.pircbotx.ShockyBot; import org.pircbotx.hooks.Event; import org.pircbotx.hooks.events.ActionEvent; import org.pircbotx.hooks.events.JoinEvent; import org.pircbotx.hooks.events.KickEvent; import org.pircbotx.hooks.events.MessageEvent; import org.pircbotx.hooks.events.ModeEvent; import org.pircbotx.hooks.events.PartEvent; import org.pircbotx.hooks.events.QuitEvent; import org.pircbotx.hooks.events.TopicEvent; import org.pircbotx.hooks.events.UserModeEvent; import org.pircbotx.hooks.types.GenericMessageEvent; import pl.shockah.FileLine; import pl.shockah.shocky.Module; import pl.shockah.shocky.Shocky; import pl.shockah.shocky.cmds.Command; import pl.shockah.shocky.cmds.CommandCallback; import pl.shockah.shocky.cmds.Parameters; import pl.shockah.shocky.events.ActionOutEvent; import pl.shockah.shocky.events.MessageOutEvent; import pl.shockah.shocky.lines.Line; import pl.shockah.shocky.lines.LineAction; import pl.shockah.shocky.lines.LineEnterLeave; import pl.shockah.shocky.lines.LineKick; import pl.shockah.shocky.lines.LineMessage; import pl.shockah.shocky.lines.LineOther; public class ModuleControllerAlert extends Module { protected Command cmd; protected List<ImmutablePair<String,Alert>> alerts = Collections.synchronizedList(new ArrayList<ImmutablePair<String,Alert>>()); public String name() {return "alert";} public boolean isListener() {return true;} public void onEnable(File dir) { Command.addCommands(this, cmd = new CmdAlert()); ArrayList<String> lines = FileLine.read(new File(dir,"alerts.cfg")); for (int i = 0; i < lines.size(); i += 2) alerts.add(new ImmutablePair<String,Alert>(lines.get(i),Alert.newAlert(lines.get(i+1)))); } public void onDisable() { Command.removeCommands(cmd); } public void onDataSave(File dir) { ArrayList<String> lines = new ArrayList<String>(); for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); lines.add(pair.left); lines.add(pair.right.toString()); } FileLine.write(new File(dir,"alerts.cfg"),lines); } public void onMessage(MessageEvent<ShockyBot> event) { for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: ["+event.getChannel().getName()+"] <"+event.getUser().getNick()+"> "+event.getMessage()); if (!pair.right.cont) alerts.remove(i--); } } } public void onAction(ActionEvent<ShockyBot> event) { for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: ["+event.getChannel().getName()+"] * "+event.getUser().getNick()+" "+event.getMessage()); if (!pair.right.cont) alerts.remove(i--); } } } public void onTopic(TopicEvent<ShockyBot> event) { for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: ["+event.getChannel().getName()+"] "+event.getUser().getNick()+" has changed the topic to: "+event.getTopic()); if (!pair.right.cont) alerts.remove(i--); } } } public void onKick(KickEvent<ShockyBot> event) { for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: ["+event.getChannel().getName()+"] "+event.getSource().getNick()+" kicked "+event.getRecipient().getNick()+" ("+event.getReason()+")"); if (!pair.right.cont) alerts.remove(i--); } } } public void onJoin(JoinEvent<ShockyBot> event) { for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: ["+event.getChannel().getName()+"] "+event.getUser().getNick()+" has joined"); if (!pair.right.cont) alerts.remove(i--); } } } public void onPart(PartEvent<ShockyBot> event) { for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: ["+event.getChannel().getName()+"] "+event.getUser().getNick()+" has left"); if (!pair.right.cont) alerts.remove(i--); } } } public void onQuit(QuitEvent<ShockyBot> event) { for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: "+event.getUser().getNick()+" has quit ("+event.getReason()+")"); if (!pair.right.cont) alerts.remove(i--); } } } public void onMode(ModeEvent<ShockyBot> event) { String mode = event.getMode(); if (mode.charAt(0) == ' ') mode = "+"+mode.substring(1); for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: ["+event.getChannel().getName()+"] * "+event.getUser().getNick()+" sets mode "+mode); if (!pair.right.cont) alerts.remove(i--); } } } public void onUserMode(UserModeEvent<ShockyBot> event) { String mode = event.getMode(); if (mode.charAt(0) == ' ') mode = "+"+mode.substring(1); for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.right.matches(event)) { Shocky.sendNotice(event.getBot(),Shocky.getUser(pair.left),"Alert: "+pair.right+"\n" +"Line: * "+event.getSource().getNick()+" sets mode "+mode+" "+event.getTarget().getNick()); if (!pair.right.cont) alerts.remove(i--); } } } public class CmdAlert extends Command { public String command() {return "alert";} public String help(Parameters params) { StringBuilder sb = new StringBuilder(); sb.append("[r:controller] alert - lists set alerts"); sb.append("[r:controller] alert add {parameters} - alerts you of specific events"); sb.append("[r:controller] alert remove {n} - removes an alert"); sb.append("\nparameters:"); sb.append("\n-channel {text} | specify the channel to monitor"); sb.append("\n-unick {text} | -unickserv {text} | -ulogin {text} | -uhost {text} | specify the user to monitor"); sb.append("\n-type {text} | specify the event type ([m]essage/[a]ction/[e]nterleave/[k]ick/[o]ther)"); sb.append("\n-regex {text} | the regex for [m]essage and [a]ction types"); sb.append("\n-cont {boolean} | if the alert should continue after first occurence"); return sb.toString(); } public void doCommand(Parameters params, CommandCallback callback) { callback.type = EType.Notice; if (params.tokenCount == 0) { int i2 = 1; StringBuilder sb = new StringBuilder(); for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.left.equals(params.sender.getNick())) { if (sb.length() != 0) sb.append("\n"); sb.append(""+(i2++)+": "+pair.right); } } callback.append(sb.length() == 0 ? "No alerts set" : sb.toString()); return; } else if (params.tokenCount >= 2) { String method = params.nextParam(); if (method.equalsIgnoreCase("remove")) { String idString = params.nextParam(); int i2 = 1, toRemove = Integer.parseInt(idString); for (int i = 0; i < alerts.size(); i++) { ImmutablePair<String,Alert> pair = alerts.get(i); if (pair.left.equals(params.sender.getNick()) && i2++ == toRemove) { alerts.remove(i); callback.append("Removed"); return; } } callback.append("No such index"); return; } else if (method.equalsIgnoreCase("add")) { Alert alert = Alert.newAlert(params.getParams(0)); if (alert.isProper()) { alerts.add(new ImmutablePair<String,Alert>(params.sender.getNick(),alert)); callback.append("Added"); return; } } } callback.append(help(params)); return; } } protected static class Alert { protected final String channel, uNick, uNickServ, uLogin, uHost, regex; protected final Class<? extends Line> type; protected final boolean cont; protected static Alert newAlert(String args) { String[] a = args.split(" "); ArrayList<String> l = new ArrayList<String>(); for (int i = 0; i < a.length; i++) { if (!a[i].startsWith("\"")) l.add(a[i]); else { StringBuilder sb = new StringBuilder(a[i]); while (++i < a.length) { sb.append(" "+a[i]); if (a[i].charAt(a[i].length()-1) == '"' && a[i].charAt(a[i].length()-2) != '\\') { sb.deleteCharAt(0); sb.deleteCharAt(sb.length()-1); break; } } l.add(sb.toString()); } } return new Alert(l.toArray(new String[l.size()])); } protected Alert(String[] args) { String _channel = null, _uNick = null, _uNickServ = null, _uLogin = null, _uHost = null, _type = null, _regex = null, _cont = null; for (int i = 0; i < args.length; i++) { String s = args[i].toLowerCase(); if (s.equals("-channel") && i+1 < args.length) {_channel = args[++i].toLowerCase(); continue;} if (s.equals("-unick") && i+1 < args.length) {_uNick = args[++i].toLowerCase(); continue;} if (s.equals("-unickserv") && i+1 < args.length) {_uNickServ = args[++i].toLowerCase(); continue;} if (s.equals("-ulogin") && i+1 < args.length) {_uLogin = args[++i].toLowerCase(); continue;} if (s.equals("-uhost") && i+1 < args.length) {_uHost = args[++i]; continue;} if (s.equals("-type") && i+1 < args.length) {_type = args[++i]; continue;} if (s.equals("-regex") && i+1 < args.length) {_regex = args[++i]; continue;} if (s.equals("-cont") && i+1 < args.length) {_cont = args[++i]; continue;} } channel = _channel; uNick = _uNick; uNickServ = _uNickServ; uLogin = _uLogin; uHost = _uHost; regex = _regex; cont = _cont == null ? false : (_cont.equals("1") || _cont.equals("t") || _cont.equals("true")); if (_type == null) type = Line.class; else if (_type.charAt(0) == 'm') type = LineMessage.class; else if (_type.charAt(0) == 'a') type = LineAction.class; else if (_type.charAt(0) == 'e') type = LineEnterLeave.class; else if (_type.charAt(0) == 'k') type = LineKick.class; else if (_type.charAt(0) == 'o') type = LineOther.class; else type = Line.class; } protected boolean isProper() { return !(channel == null && uNick == null && uNickServ == null && uLogin == null && uHost == null && regex == null); } @SuppressWarnings("unchecked") protected boolean matches(Event<ShockyBot> event) { boolean matches = true; if (matches && type != Line.class) { if ((event instanceof MessageEvent || event instanceof MessageOutEvent) && type != LineMessage.class) matches = false; if ((event instanceof ActionEvent || event instanceof ActionOutEvent) && type != LineAction.class) matches = false; if ((event instanceof JoinEvent || event instanceof PartEvent || event instanceof QuitEvent) && type != LineEnterLeave.class) matches = false; if (event instanceof KickEvent && type != LineKick.class) matches = false; if (matches && type != LineOther.class) matches = false; } if (matches && channel != null) { try { Method m = event.getClass().getMethod("getChannel"); if (m == null) matches = false; else { m.setAccessible(true); String eChannel = (String)m.invoke(event); if (!eChannel.toLowerCase().equals(eChannel)) matches = false; } } catch (Exception e) {e.printStackTrace();} } if (matches && uNick != null) { String eNick = null; if (event instanceof MessageEvent || event instanceof ActionEvent) eNick = ((GenericMessageEvent<PircBotX>)event).getUser().getNick().toLowerCase(); if (event instanceof MessageOutEvent || event instanceof ActionOutEvent) eNick = ((GenericMessageEvent<PircBotX>)event).getBot().getNick().toLowerCase(); if (event instanceof KickEvent) matches = ((KickEvent<ShockyBot>)event).getSource().getNick().toLowerCase().equals(uNick) || ((KickEvent<ShockyBot>)event).getRecipient().getNick().toLowerCase().equals(uNick); if (matches && (eNick == null || !eNick.equals(uNick))) matches = false; } if (matches && uNickServ != null) { String eNickServ = null; if (event instanceof MessageEvent || event instanceof ActionEvent) eNickServ = Shocky.getLogin(((GenericMessageEvent<PircBotX>)event).getUser()).toLowerCase(); if (event instanceof MessageOutEvent || event instanceof ActionOutEvent) eNickServ = Shocky.getLogin(((GenericMessageEvent<PircBotX>)event).getBot().getUserBot()).toLowerCase(); if (event instanceof KickEvent) matches = Shocky.getLogin(((KickEvent<ShockyBot>)event).getSource()).toLowerCase().equals(uNickServ) || Shocky.getLogin(((KickEvent<ShockyBot>)event).getRecipient()).toLowerCase().equals(uNickServ); if (matches && (eNickServ == null || !eNickServ.equals(uNickServ))) matches = false; } if (matches && uLogin != null) { String eLogin = null; if (event instanceof MessageEvent || event instanceof ActionEvent) eLogin = ((GenericMessageEvent<PircBotX>)event).getUser().getLogin().toLowerCase(); if (event instanceof MessageOutEvent || event instanceof ActionOutEvent) eLogin = ((GenericMessageEvent<PircBotX>)event).getBot().getLogin().toLowerCase(); if (event instanceof KickEvent) matches = ((KickEvent<ShockyBot>)event).getSource().getLogin().toLowerCase().equals(uLogin) || ((KickEvent<ShockyBot>)event).getRecipient().getLogin().toLowerCase().equals(uLogin); if (matches && (eLogin == null || !eLogin.equals(uLogin))) matches = false; } if (matches && uHost != null) { String eHost = null; if (event instanceof MessageEvent || event instanceof ActionEvent) eHost = ((GenericMessageEvent<PircBotX>)event).getUser().getHostmask(); if (event instanceof MessageOutEvent || event instanceof ActionOutEvent) eHost = ((GenericMessageEvent<PircBotX>)event).getBot().getUserBot().getHostmask(); if (event instanceof KickEvent) matches = ((KickEvent<ShockyBot>)event).getSource().getHostmask().equals(uHost) || ((KickEvent<ShockyBot>)event).getRecipient().getHostmask().equals(uHost); if (matches && (eHost == null || !eHost.equals(uHost))) matches = false; } if (matches && regex != null && (type == Line.class || type == LineMessage.class || type == LineAction.class)) { if (event instanceof GenericMessageEvent) if (!((GenericMessageEvent<PircBotX>)event).getMessage().matches(regex)) matches = false; } return matches; } public String toString() { ArrayList<String> args = new ArrayList<String>(); if (channel != null) args.add("-channel "+channel); if (uNick != null) args.add("-unick "+uNick); if (uNickServ != null) args.add("-unickserv "+uNickServ); if (uLogin != null) args.add("-ulogin "+uLogin); if (uHost != null) args.add("-uhost "+uHost); if (regex != null) args.add("-regex "+(regex.contains(" ") ? "\""+regex.replace("\"","\\\"")+"\"" : regex)); if (cont) args.add("-cont 1"); if (type == LineMessage.class) args.add("-type m"); else if (type == LineAction.class) args.add("-type a"); else if (type == LineEnterLeave.class) args.add("-type e"); else if (type == LineKick.class) args.add("-type k"); else if (type == LineOther.class) args.add("-type o"); StringBuilder sb = new StringBuilder(); for (String s : args) { if (sb.length() != 0) sb.append(" "); sb.append(s); } return sb.toString(); } } }