/** * Copyright Paul James Mutton, 2001-2009, http://www.jibble.org/ * * Copyright 2013 JogAmp Community. All rights reserved. * * This software is licensed under the GNU General Public License (GPL) Version 3. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ package org.jogamp.jabot.irc; import java.io.PrintStream; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Locale; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jibble.pircbot.Colors; import org.jibble.pircbot.PircBot; import org.jogamp.jabot.util.TimeTool; public class LogBot extends PircBot { public static final String GREEN = "irc-green"; public static final String BLACK = "irc-black"; public static final String BROWN = "irc-brown"; public static final String NAVY = "irc-navy"; public static final String BRICK = "irc-brick"; public static final String RED = "irc-red"; private static final Pattern urlPattern = Pattern.compile("(?i:\\b((http|https|ftp|irc|file)://[^\\s]+))"); private static String ANONYMOUS = "anon"; private final boolean showHostname; private String joinMessage; private final Calendar calendar; private final Object timeSync = new Object(); private final boolean reconnectOnDisconnect; private final boolean xmlOut; private final Object outSync = new Object(); private PrintStream out; private int lineCount; private long lastTS; private Runnable postConnectAction; public LogBot(boolean showHostname, String joinMessage, boolean xmlOut, boolean reconnectOnDisconnect) { this(showHostname, joinMessage, TimeTool.getNearZuluTimeZone(), Locale.getDefault(), System.out, xmlOut, reconnectOnDisconnect); } public LogBot(boolean showHostname, String joinMessage, TimeZone timeZone, Locale locale, PrintStream out, boolean xmlOut, boolean reconnectOnDisconnect) { this.showHostname = showHostname; this.calendar = new GregorianCalendar(timeZone, locale); this.xmlOut = xmlOut; this.out = out; this.joinMessage = joinMessage; this.lineCount = 0; this.postConnectAction = null; this.lastTS = System.currentTimeMillis(); this.reconnectOnDisconnect = reconnectOnDisconnect; } @Override protected void handleLine(String line) { lastTS = System.currentTimeMillis(); super.handleLine(line); } public void sendPing() { this.sendRawLine("PING :" + getNick()); } /** Returns the last timestamp as set by ctor or receiving a line from server. */ public final long getLastTS() { return lastTS; } public final void setJoinMessage(String joinMessage) { this.joinMessage = joinMessage; } public final String getJoinMessage() { return joinMessage; } /** *

* Sets the internal login of the Bot. This should be set before joining * any servers. *

*

* Sets the internal nick of the bot. This is only to be called by the * PircBot class in response to notification of nick changes that apply * to us. *

*/ public final void setLoginAndNick(String login, String nick) { super.setLogin(login); super.setName(nick); } /** Sets the action to be performed after each connect, incl. reconnect. */ public final void setPostConnectAction(Runnable action) { this.postConnectAction = action; } public final Calendar getCalendar() { return calendar; } /** Returns timestamp of internal Calendar: YYYYMMDD HH:MM:SS (TMZ) */ public final String getTimeStamp() { return TimeTool.getTimeStamp(calendar, true, true); } public final String getTimeStamp(long millis) { final String ts; synchronized(timeSync) { calendar.setTimeInMillis(millis); ts = TimeTool.getTimeStamp(calendar, true, true); calendar.setTimeInMillis(System.currentTimeMillis()); } return ts; } /** Updates internal Calendar w/ current time and returns it.*/ public final Calendar tick() { synchronized(timeSync) { calendar.setTimeInMillis(System.currentTimeMillis()); return calendar; } } public PrintStream getOut() { synchronized(outSync) { return out; } } public PrintStream setOut(PrintStream newOut, boolean resetLineCount) { synchronized(outSync) { final PrintStream old = out; out = newOut; if( resetLineCount ) { lineCount = 0; } return old; } } public int getLineCount() { return lineCount; } public void resetLineCount() { synchronized(outSync) { lineCount = 0; } } public void append(String color, String line) { tick(); lineCount++; if(xmlOut) { line = Colors.removeFormattingAndColors(line); line = line.replaceAll("&", "&"); line = line.replaceAll("<", "<"); line = line.replaceAll(">", ">"); Matcher matcher = urlPattern.matcher(line); line = matcher.replaceAll("$1"); } synchronized(outSync) { if(xmlOut) { // 20130117 21:06:04 out.println("" + getTimeStamp() + " " + line + "
"); } else { out.println(getTimeStamp()+" "+line); } out.flush(); } } /** * Log a notice * * @param notice The notice to log. */ public final void logNotice(String notice) { append(BROWN, "-" + getNick() + "- " + notice); } /** * Sends a logged notice to the channel or to a user. * * @param target The name of the channel or user nick to send to. * @param notice The notice to send. */ public final void sendLoggedNotice(String target, String notice) { super.sendNotice(target, notice); append(BROWN, "-" + getNick() + "- " + notice); } public void onAction(String sender, String login, String hostname, String target, String action) { append(BRICK, "* " + sender + " " + action); } public void onJoin(String channel, String sender, String login, String hostname) { append(GREEN, "* " + sender + " (" + login + "@" + ( showHostname ? hostname : ANONYMOUS ) + ") has joined " + channel); if (sender.equals(getNick())) { sendNotice(channel, joinMessage); } else { sendNotice(sender, joinMessage); } } public void onMessage(String channel, String sender, String login, String hostname, String message) { append(BLACK, "<" + sender + "> " + message); message = message.toLowerCase(); if (message.startsWith(getNick().toLowerCase()) && message.indexOf("help") > 0) { sendMessage(channel, joinMessage); } } public void onMode(String channel, String sourceNick, String sourceLogin, String sourceHostname, String mode) { append(GREEN, "* " + sourceNick + " sets mode " + mode); } public void onNickChange(String oldNick, String login, String hostname, String newNick) { append(GREEN, "* " + oldNick + " is now known as " + newNick); } public void onNotice(String sourceNick, String sourceLogin, String sourceHostname, String target, String notice) { append(BROWN, "-" + sourceNick + "- " + notice); } public void onPart(String channel, String sender, String login, String hostname) { append(GREEN, "* " + sender + " (" + login + "@" + ( showHostname ? hostname : ANONYMOUS ) + ") has left " + channel); } public void onPing(String sourceNick, String sourceLogin, String sourceHostname, String target, String pingValue) { append(RED, "[" + sourceNick + " PING]"); } public void onPrivateMessage(String sender, String login, String hostname, String message) { append(BLACK, "<- *" + sender + "* " + message); } public void onQuit(String sourceNick, String sourceLogin, String sourceHostname, String reason) { append(NAVY, "* " + sourceNick + " (" + sourceLogin + "@" + ( showHostname ? sourceHostname : ANONYMOUS ) + ") Quit (" + reason + ")"); } public void onTime(String sourceNick, String sourceLogin, String sourceHostname, String target) { append(RED, "[" + sourceNick + " TIME]"); } public void onTopic(String channel, String topic, String setBy, long date, boolean changed) { if (changed) { append(GREEN, "* " + setBy + " changes topic to '" + topic + "'"); } else { append(GREEN, "* Topic is '" + topic + "'"); append(GREEN, "* Set by " + setBy + " on " + getTimeStamp(date)); } } public void onVersion(String sourceNick, String sourceLogin, String sourceHostname, String target) { append(RED, "[" + sourceNick + " VERSION]"); } public void onKick(String channel, String kickerNick, String kickerLogin, String kickerHostname, String recipientNick, String reason) { append(GREEN, "* " + recipientNick + " was kicked from " + channel + " by " + kickerNick); if (recipientNick.equalsIgnoreCase(getNick())) { joinChannel(channel); } } @Override public void onConnect() { if( null != postConnectAction ) { postConnectAction.run(); } } @Override public void onDisconnect() { append(NAVY, "* Disconnected."); if( reconnectOnDisconnect ) { while (!isConnected()) { try { reconnect(); } catch (Exception e) { try { Thread.sleep(10000); } catch (Exception anye) { // Do nothing. } } } } } @Override public String toString() { return "Version{" + this.getVersion() + "}" + " Connected{" + this.isConnected() + "}" + " Server{" + this.getServer() + "}" + " Port{" + this.getPort() + "}" + " Password{" + (null != this.getPassword() ) + "}"; } }