From 88b119acea1ea849ea3a9b7f7a970513b6f2d089 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Tue, 29 Jan 2019 01:28:11 +0300 Subject: [PATCH] v0.5 rolling. CTCP support added to ChannelCommander. --- .../ChannelScripts/srv#lpr.csv | 25 ++++ pom.xml | 2 +- .../InnaIrcBot/Commanders/CTCPHelper.java | 132 ++++++++++++++++++ .../Commanders/ChanelCommander.java | 73 +++++++--- .../Commanders/JoinFloodHandler.java | 2 +- src/main/java/InnaIrcBot/GlobalData.java | 2 +- .../ProvidersConsumers/StreamProvider.java | 6 +- .../ProvidersConsumers/SystemConsumer.java | 39 +++++- 8 files changed, 251 insertions(+), 30 deletions(-) create mode 100644 ConfigurationExamples/ChannelScripts/srv#lpr.csv create mode 100644 src/main/java/InnaIrcBot/Commanders/CTCPHelper.java diff --git a/ConfigurationExamples/ChannelScripts/srv#lpr.csv b/ConfigurationExamples/ChannelScripts/srv#lpr.csv new file mode 100644 index 0000000..4373eff --- /dev/null +++ b/ConfigurationExamples/ChannelScripts/srv#lpr.csv @@ -0,0 +1,25 @@ +# NOTE: Filename should be servername#channel OR servernamechannel (is started not from '#'). It MUST have .csv extension and hold tab-separated-values. This example works for server='srv' and channel='#lpr' +#Join Flood Control Number of events Time Frame in seconds +JoinFloodControl 5 10 +#event regexp command message_or_command message_or_command message_or_ N+1 +msg ^!help(.+)? \chanmsg Ничего не знаю! +join ^Мерзавец(.+)?!.* \kickban requested +join ^Мальчиш_плохишь!.* \kick плохой! +join ^Мальчиш_плохишь!.* \ban \privmsg не возвращайся! +nick ^Мимикрирую_под.* \chanmsg перестань! + +#event regexp to trigger CTCP (send to chan/privmsg) message printed if not found +msg ^cci.* \cclientinfo (^.+(\s|\t)+) нет таких: +msg ^cf.* \cfinger (^.+(\s|\t)+) не понятно кто это: +msg ^cp.* \cping (^.+(\s|\t)+) ололо +msg ^cs.* \csource (^.+(\s|\t)+) пыщ -пыщ : +msg ^ct.* \ctime (^.+(\s|\t)+) ыыы: +msg ^cui.* \cuserinfo (^.+(\s|\t)+) ыыыыы ы: +msg ^cv.* \cversion (^.+(\s|\t)+) +msg ^pci.* \pclientinfo (^.+(\s|\t)+) ололо: +msg ^pf.* \pfinger (^.+(\s|\t)+) нет таких: +msg ^pp.* \pping (^.+(\s|\t)+) нету: +msg ^ps.* \psource (^.+(\s|\t)+) хаха: +msg ^pt.* \ptime (^.+(\s|\t)+) олол: +msg ^pu.* \puserinfo (^.+(\s|\t)+) пиу-пиу: +msg ^pv.* \pversion (^.+(\s|\t)+) \chanmsg отправлено! diff --git a/pom.xml b/pom.xml index 4ef9c4e..148eb92 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 loper InnaIrcBot - 0.4-SNAPSHOT + 0.5-SNAPSHOT jar InnaIrcBot diff --git a/src/main/java/InnaIrcBot/Commanders/CTCPHelper.java b/src/main/java/InnaIrcBot/Commanders/CTCPHelper.java new file mode 100644 index 0000000..6619b14 --- /dev/null +++ b/src/main/java/InnaIrcBot/Commanders/CTCPHelper.java @@ -0,0 +1,132 @@ +package InnaIrcBot.Commanders; + +import InnaIrcBot.ProvidersConsumers.StreamProvider; + +import java.time.LocalDateTime; +import java.util.*; + +//TODO: Consider using as thread + +public class CTCPHelper { + private static final CTCPHelper instance = new CTCPHelper(); + public static CTCPHelper getInstance(){ return instance; } + + + private HashMap> waitersQueue = new HashMap<>(); + + void registerRequest(String requesterServer, String requesterChanelOrUser, String ctcpType, String targetObject, String notFoundMessage){ + /* + System.out.println("Server:|"+requesterServer+"|"); + System.out.println("Chanel:|"+requesterChanelOrUser+"|"); + System.out.println("Type :|"+ctcpType+"|"); + System.out.println("Regexp:|"+targetObject+"|"); + System.out.println("NF_mes:|"+notFoundMessage+"|\n"); // could be empty + */ + if (!waitersQueue.containsKey(requesterServer)){ // TODO: meeeeeeeehh.. looks bad + waitersQueue.put(requesterServer, new ArrayList<>()); + } + + switch (ctcpType){ + case "VERSION": + case "CLIENTINFO": + case "FINGER": + case "SOURCE": + case "TIME": + case "USERINFO": + waitersQueue.get(requesterServer).add(new CtcpRequest(requesterChanelOrUser, targetObject, notFoundMessage, ctcpType)); + StreamProvider.writeToStream(requesterServer, "PRIVMSG "+targetObject+" :\u0001"+ctcpType+"\u0001"); + break; + case "PING": // TODO + waitersQueue.get(requesterServer).add(new CtcpRequest(requesterChanelOrUser, targetObject, notFoundMessage, ctcpType)); + StreamProvider.writeToStream(requesterServer, "PRIVMSG "+targetObject+" :\u0001PING inna\u0001"); + break; + } + } + + public void handleCtcpReply(String serverReplied, String whoReplied, String whatReplied){ + //System.out.println("Reply serv:|"+serverReplied+"|\nwho:|"+whoReplied+"|\nwhat:|"+whatReplied+"|"); + LocalDateTime currentTime = LocalDateTime.now(); + if (waitersQueue.containsKey(serverReplied)){ + ListIterator iterator = waitersQueue.get(serverReplied).listIterator(); + CtcpRequest current; + String chanelOrUser; + while (iterator.hasNext()){ + current = iterator.next(); + if (current.isValid(currentTime)){ + chanelOrUser = current.getRequesterChanelOrUser(whoReplied); + if ( chanelOrUser != null && current.getType().equals(whatReplied.replaceAll("\\s.*$", ""))) { + StreamProvider.writeToStream(serverReplied, "PRIVMSG " + chanelOrUser + " :" + whoReplied + ": " + whatReplied); + iterator.remove(); + } + } + else{ + //System.out.println("Drop outdated user"); + iterator.remove(); + } + } + } + } + + public void handleErrorReply(String serverReplied, String whoNotFound){ + //System.out.println("Reply serv:|"+serverReplied+"|\nwho:|"+whoNotFound+"|\n"); + LocalDateTime currentTime = LocalDateTime.now(); + if (waitersQueue.containsKey(serverReplied)){ + ListIterator iterator = waitersQueue.get(serverReplied).listIterator(); + CtcpRequest current; + String chanelOrUser; + String notFoundMessage; + while (iterator.hasNext()){ + current = iterator.next(); + if (current.isValid(currentTime)){ + chanelOrUser = current.getRequesterChanelOrUser(whoNotFound); + if ( chanelOrUser != null) { + notFoundMessage = current.getNotFoundMessage(whoNotFound); + if ( notFoundMessage != null) { + System.out.println(serverReplied + " PRIVMSG " + chanelOrUser + " :" + notFoundMessage + whoNotFound); + StreamProvider.writeToStream(serverReplied, "PRIVMSG " + chanelOrUser + " :" + notFoundMessage + whoNotFound); + } + iterator.remove(); + } + } + else{ + //System.out.println("Drop outdated user: 401"); + iterator.remove(); + } + } + } + } +} + +class CtcpRequest { + private String requesterChanelOrUser; + private String userResponding; + private LocalDateTime initiatedTime; + private String notFoundMessage; + private String CTCPtype; + CtcpRequest (String whoIsAsking, String userResponding, String notFoundMessage, String CTCPType){ + this.initiatedTime = LocalDateTime.now(); + this.requesterChanelOrUser = whoIsAsking; + this.userResponding = userResponding; + this.notFoundMessage = notFoundMessage; + this.CTCPtype = CTCPType; + } + String getType(){ return CTCPtype; } + String getRequesterChanelOrUser(String userResponds){ // return channel name + if (userResponding.equals(userResponds)) + return requesterChanelOrUser; + else + return null; + } + boolean isValid(LocalDateTime currentTime){ + return currentTime.isBefore(initiatedTime.plusSeconds(5)); + } + String getNotFoundMessage(String userResponds){ + if (this.userResponding.equals(userResponds)) + if (notFoundMessage.isEmpty()) + return null; + else + return notFoundMessage; + else + return null; + } +} diff --git a/src/main/java/InnaIrcBot/Commanders/ChanelCommander.java b/src/main/java/InnaIrcBot/Commanders/ChanelCommander.java index 8d2e7c7..bb61cb0 100644 --- a/src/main/java/InnaIrcBot/Commanders/ChanelCommander.java +++ b/src/main/java/InnaIrcBot/Commanders/ChanelCommander.java @@ -94,48 +94,84 @@ public class ChanelCommander implements Runnable { for (String pattern : map.keySet()) if (Pattern.matches(pattern, arg1)){ // NOTE: validation based on new nick //TODO: parse here String[] cmdOrMsg = map.get(pattern); + + StringBuilder whatToSendStringBuilder; + ArrayList whatToSendList; for (int i = 0; i whatToSend; switch (cmdOrMsg[i]) { case "\\chanmsg": - whatToSend = new ArrayList<>(); + whatToSendList = new ArrayList<>(); for (i++; (i < cmdOrMsg.length) && !(cmdOrMsg[i].startsWith("\\")); i++) - whatToSend.add(cmdOrMsg[i]); - msgAction(whatToSend.toArray(new String[0]), arg2, false); + whatToSendList.add(cmdOrMsg[i]); + msgAction(whatToSendList.toArray(new String[0]), arg2, false); break; case "\\privmsg": - whatToSend = new ArrayList<>(); + whatToSendList = new ArrayList<>(); for (i++; (i < cmdOrMsg.length) && !(cmdOrMsg[i].startsWith("\\")); i++) - whatToSend.add(cmdOrMsg[i]); - msgAction(whatToSend.toArray(new String[0]), arg2, true); + whatToSendList.add(cmdOrMsg[i]); + msgAction(whatToSendList.toArray(new String[0]), arg2, true); break; case "\\ban": banAction(arg2); i++; break; case "\\kick": - whatToSend = new ArrayList<>(); + whatToSendList = new ArrayList<>(); for (i++; (i < cmdOrMsg.length) && !(cmdOrMsg[i].startsWith("\\")); i++) - whatToSend.add(cmdOrMsg[i]); - kickAction(whatToSend.toArray(new String[0]), arg2); + whatToSendList.add(cmdOrMsg[i]); + kickAction(whatToSendList.toArray(new String[0]), arg2); break; case "\\kickban": - whatToSend = new ArrayList<>(); + whatToSendList = new ArrayList<>(); for (i++; (i < cmdOrMsg.length) && !(cmdOrMsg[i].startsWith("\\")); i++) - whatToSend.add(cmdOrMsg[i]); + whatToSendList.add(cmdOrMsg[i]); banAction(arg2); - kickAction(whatToSend.toArray(new String[0]), arg2); + kickAction(whatToSendList.toArray(new String[0]), arg2); break; case "\\raw": - StringBuilder whatToSendRaw = new StringBuilder(); + whatToSendStringBuilder = new StringBuilder(); for (i++; (i < cmdOrMsg.length) && !(cmdOrMsg[i].startsWith("\\")); i++) - whatToSendRaw.append(cmdOrMsg[i]); - StreamProvider.writeToStream(server, whatToSendRaw.toString()); //TODO + whatToSendStringBuilder.append(cmdOrMsg[i]); + StreamProvider.writeToStream(server, whatToSendStringBuilder.toString()); //TODO break; //todo: add script case "\\whois": // result will be noted in 'system' log whoisAction(arg2); i++; + break; + case "\\cclientinfo": // NOTE: All this handled by CTCPHelper instance + case "\\cfinger": // C - publish request result to chan + case "\\cping": + case "\\csource": + case "\\ctime": + case "\\cuserinfo": + case "\\cversion": + case "\\pclientinfo": // P - reply to privmsg + case "\\pfinger": + case "\\pping": + case "\\psource": + case "\\ptime": + case "\\puserinfo": + case "\\pversion": + String CTCPType = cmdOrMsg[i]; + String objectRegexp = null; + whatToSendStringBuilder = new StringBuilder(); + + for (i++; (i < cmdOrMsg.length) && !(cmdOrMsg[i].startsWith("\\")); i++){ + if (objectRegexp == null && !cmdOrMsg[i].trim().isEmpty()) + objectRegexp = cmdOrMsg[i].trim(); + else + whatToSendStringBuilder.append(cmdOrMsg[i]); + } + if (objectRegexp != null) { + String objectToCtcp = arg1.trim().replaceAll(objectRegexp, ""); // note: trim() ? + if (!objectToCtcp.isEmpty()){ + if (CTCPType.startsWith("\\c")) + CTCPHelper.getInstance().registerRequest(server, chanel, CTCPType.substring(2).toUpperCase(), objectToCtcp, whatToSendStringBuilder.toString()); + else + CTCPHelper.getInstance().registerRequest(server, simplifyNick(arg2), CTCPType.substring(2).toUpperCase(), objectToCtcp, whatToSendStringBuilder.toString()); + } + } + break; default: i++; @@ -147,6 +183,7 @@ public class ChanelCommander implements Runnable { private void whoisAction(String who){ // TODO: maybe we have to extend functionality to reuse received information. StreamProvider.writeToStream(server, "WHOIS "+simplifyNick(who)); } + private void msgAction(String[] messages, String who, boolean sendToPrivate){ StringBuilder executiveStr = new StringBuilder(); executiveStr.append("PRIVMSG "); @@ -164,7 +201,7 @@ public class ChanelCommander implements Runnable { for (int i = 0; i < messages.length; i++){ if ( ! messages[i].startsWith("\\")) executiveStr.append(messages[i]); - else if (messages[i].equals("\\time")) + else if (messages[i].equals("\\time")) // TODO: remove this shit executiveStr.append(LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))); } //System.out.println(executiveStr.toString()); //TODO: debug diff --git a/src/main/java/InnaIrcBot/Commanders/JoinFloodHandler.java b/src/main/java/InnaIrcBot/Commanders/JoinFloodHandler.java index 4e9875b..a22ffd6 100644 --- a/src/main/java/InnaIrcBot/Commanders/JoinFloodHandler.java +++ b/src/main/java/InnaIrcBot/Commanders/JoinFloodHandler.java @@ -25,7 +25,7 @@ public class JoinFloodHandler { if(usersOnChanel.containsKey(userNick)){ LocalDateTime timeOfFirstEvent = usersOnChanel.get(userNick).addLastGetFirst(); if (timeOfFirstEvent.isAfter(LocalDateTime.now().minusSeconds(timeFrameInSeconds))) { // If first event in the queue happened after 'timeFrameSeconds ago from now' - StreamProvider.writeToStream(server, "PRIVMSG "+chanel+" :"+userNick+": join flood ("+eventBufferSize+" connections in "+timeFrameInSeconds+"seconds).\n"+ + StreamProvider.writeToStream(server, "PRIVMSG "+chanel+" :"+userNick+": join flood ("+eventBufferSize+" connections in "+timeFrameInSeconds+" seconds).\n"+ "MODE "+chanel+" +b "+userNick+"!*@*"); // Shut joins-liker down. By nick TODO: consider other ban methods usersOnChanel.remove(userNick); // Delete viewing history (in case op/hop decided to unban) } diff --git a/src/main/java/InnaIrcBot/GlobalData.java b/src/main/java/InnaIrcBot/GlobalData.java index 55f9691..556bdbb 100644 --- a/src/main/java/InnaIrcBot/GlobalData.java +++ b/src/main/java/InnaIrcBot/GlobalData.java @@ -1,7 +1,7 @@ package InnaIrcBot; public class GlobalData { - private static final String version = "InnaIrcBot v0.4 \"Карские Ворота\""; + private static final String version = "InnaIrcBot v0.5 \"Шикотан\""; public static synchronized String getAppVersion(){ return version; } diff --git a/src/main/java/InnaIrcBot/ProvidersConsumers/StreamProvider.java b/src/main/java/InnaIrcBot/ProvidersConsumers/StreamProvider.java index c858d03..b9945df 100644 --- a/src/main/java/InnaIrcBot/ProvidersConsumers/StreamProvider.java +++ b/src/main/java/InnaIrcBot/ProvidersConsumers/StreamProvider.java @@ -17,12 +17,12 @@ public class StreamProvider { srvStreamMap.get(server).flush(); //System.out.println("W:"+message); // If this application says something, then pass it into system consumer thread to handle - if (message.startsWith("PRIVMSG")) { + if (message.startsWith("PRIVMSG ")) { srvSysConsumersMap.get(server).println("INNA "+message); srvSysConsumersMap.get(server).flush(); } } catch (java.io.IOException e){ - System.out.println("Internal issue: StreamProvider->writeToStream() caused I/O exception."); + System.out.println("Internal issue: StreamProvider->writeToStream() caused I/O exception:\n\t"+e); } } public static synchronized boolean setStream(String server, Socket socket){ @@ -31,7 +31,7 @@ public class StreamProvider { srvStreamMap.put(server, new OutputStreamWriter(outStream)); return true; } catch (java.io.IOException e){ - System.out.println("Internal issue: StreamProvider->setStream() caused I/O exception."); + System.out.println("Internal issue: StreamProvider->setStream() caused I/O exception:\n\t"+e); return false; } } diff --git a/src/main/java/InnaIrcBot/ProvidersConsumers/SystemConsumer.java b/src/main/java/InnaIrcBot/ProvidersConsumers/SystemConsumer.java index b6fc6cb..beb2be5 100644 --- a/src/main/java/InnaIrcBot/ProvidersConsumers/SystemConsumer.java +++ b/src/main/java/InnaIrcBot/ProvidersConsumers/SystemConsumer.java @@ -1,5 +1,6 @@ package InnaIrcBot.ProvidersConsumers; +import InnaIrcBot.Commanders.CTCPHelper; import InnaIrcBot.Commanders.PrivateMsgCommander; import InnaIrcBot.Config.StorageFile; import InnaIrcBot.GlobalData; @@ -29,7 +30,6 @@ public class SystemConsumer implements Runnable{ private PrivateMsgCommander commander; SystemConsumer(BufferedReader streamReader, String userNick, Map map, StorageFile storage) { - //this.writerWorker = BotDriver.getWorker(storage.getServerName(), "system"); this.writerWorker = BotDriver.getSystemWorker(storage.getServerName()); this.nick = userNick; this.serverName = storage.getServerName(); @@ -77,6 +77,7 @@ public class SystemConsumer implements Runnable{ if (dataStrings[0].equals("PRIVMSG") && dataStrings[2].indexOf("\u0001") < dataStrings[2].lastIndexOf("\u0001")) { replyCTCP(simplifyNick(dataStrings[1]), dataStrings[2].substring(dataStrings[2].indexOf(":") + 1)); + //System.out.println("|"+dataStrings[1]+"|"+dataStrings[2].substring(dataStrings[2].indexOf(":") + 1)+"|"); } else if (Pattern.matches("(^[0-9]{3}$)|(^NICK$)|(^JOIN$)|(^QUIT$)", dataStrings[0])){ handleNumeric(dataStrings[0], dataStrings[1], dataStrings[2]); @@ -85,6 +86,10 @@ public class SystemConsumer implements Runnable{ commander.receiver(dataStrings[1], dataStrings[2].replaceAll("^.+?:", "").trim()); writerWorker.logAdd("[system]", "PRIVMSG from "+dataStrings[1]+" received: ", dataStrings[2].replaceAll("^.+?:", "").trim()); } + else if (dataStrings[0].equals("NOTICE")) { + handleNotice(dataStrings[1], dataStrings[2].replaceAll("^.+?:", "").trim()); + } + else if (dataStrings[0].equals("INNA")) { String[] splitter; if (dataStrings.length > 2){ // Don't touch 'cuz it's important @@ -104,9 +109,12 @@ public class SystemConsumer implements Runnable{ } } private boolean getProxy(String eventNum, String sender, String message){ //TODO: if can't join: like channel with password - if (eventNum.equals("353")) + if (eventNum.equals("353")) { + //writerWorker.logAdd("[proxy]", "catch: "+eventNum+" from: "+sender+" :",message); return false; // never mind and let it flows as usual. + } else { + //writerWorker.logAdd("[proxy]", "catch: "+eventNum+" from: "+sender+" :",message); String chan = message.replaceAll("(\\s.?$)|(\\s.+?$)", ""); if (eventNum.equals("QUIT") || eventNum.equals("NICK")) { @@ -127,7 +135,6 @@ public class SystemConsumer implements Runnable{ if (message.equals("\u0001VERSION\u0001")){ StreamProvider.writeToStream(serverName,"NOTICE "+sender+" :\u0001VERSION "+ GlobalData.getAppVersion()+"\u0001"); writerWorker.logAdd("[system]", "catch/handled CTCP VERSION from", sender); - //System.out.println(sender+" "+message); //System.out.println("NOTICE "+sender+" \u0001VERSION "+ GlobalData.getAppVersion()+"\u0001"); } else if (message.startsWith("\u0001PING ") && message.endsWith("\u0001")){ @@ -136,7 +143,7 @@ public class SystemConsumer implements Runnable{ //System.out.println(":"+sender+" NOTICE "+sender.substring(0,sender.indexOf("!"))+" "+message); } else if (message.equals("\u0001CLIENTINFO\u0001")){ - StreamProvider.writeToStream(serverName,"NOTICE "+sender+" :\u0001CLIENTINFO ACTION PING VERSION TIME CLIENTINFO\u0001"); + StreamProvider.writeToStream(serverName,"NOTICE "+sender+" :\u0001CLIENTINFO ACTION PING VERSION TIME CLIENTINFO SOURCE\u0001"); writerWorker.logAdd("[system]", "catch/handled CTCP CLIENTINFO from", sender); //System.out.println(":"+sender+" NOTICE "+sender.substring(0,sender.indexOf("!"))+" \u0001CLIENTINFO ACTION PING VERSION TIME CLIENTINFO\u0001"); } @@ -145,12 +152,21 @@ public class SystemConsumer implements Runnable{ writerWorker.logAdd("[system]", "catch/handled CTCP TIME from", sender); //System.out.println(":"+sender+" NOTICE "+sender.substring(0,sender.indexOf("!"))+" \u0001TIME "+ ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME)+"\u0001"); } + else if (message.equals("\u0001SOURCE\u0001")){ + StreamProvider.writeToStream(serverName,"NOTICE "+sender+" :\u0001SOURCE https://github.com/developersu/InnaIrcBot\u0001"); + writerWorker.logAdd("[system]", "catch/handled CTCP TIME from", sender); + //System.out.println(":"+sender+" NOTICE "+sender.substring(0,sender.indexOf("!"))+" \u0001SOURCE "+ ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME)+"\u0001"); + } else writerWorker.logAdd("[system]", "catch unknown CTCP request \""+message+"\" from ", sender); } - + private String simplifyNick(String nick){ return nick.replaceAll("!.*$",""); } + private void handleNotice(String sender, String message){ + writerWorker.logAdd("[system]", "NOTICE from "+sender+" received: ", message); + CTCPHelper.getInstance().handleCtcpReply(serverName, simplifyNick(sender), message); + } private void handleSpecial(String event, String chanel, String message){ //System.out.println("|"+event+"|"+chanel+"|"+message+"|"); @@ -167,6 +183,7 @@ public class SystemConsumer implements Runnable{ writerWorker.logAdd("[system]", "catch/handled:", eventNum+" [nickname already in use]"); break; case "353": + writerWorker.logAdd("[system]", "catch/handled:", eventNum+" [RPL_NAMREPLY]"); String chan = message.substring(message.indexOf(" ")+3); chan = chan.substring(0, chan.indexOf(" ")); if (proxyAList.containsKey(chan)) { @@ -206,7 +223,7 @@ public class SystemConsumer implements Runnable{ case "NICK": if (sender.startsWith(nick+"!")) { nick = message.trim(); - writerWorker.logAdd("[system]", "catch own NICK change from:", sender+" to: "+message); + writerWorker.logAdd("[system]", "catch own NICK change:", sender+" to: "+message); } break; case "JOIN": @@ -217,6 +234,16 @@ public class SystemConsumer implements Runnable{ writerWorker.logAdd("[system]", "joined to channel ", message); } break; + case "401": // No such nick/channel + //System.out.println("|"+message.replaceAll("^(\\s)?.+?(\\s)|((\\s)?:No such nick/channel)","")+"|"); + CTCPHelper.getInstance().handleErrorReply(serverName, message.replaceAll("^(\\s)?.+?(\\s)|((\\s)?:No such nick/channel)","")); + writerWorker.logAdd("[system]", "catch: "+eventNum+" from: "+sender+" :",message+" [ok]"); + break; + /* + case "NOTICE": + writerWorker.logAdd("[system]", eventNum+" from: "+sender+" received: ",message); + break; + */ default: writerWorker.logAdd("[system]", "catch: "+eventNum+" from: "+sender+" :",message); // TODO: QUIT comes here. Do something. break;