From e4a25a8d84b1991aac8921ff48fef4088e9fdbf3 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 17 Jan 2013 07:03:43 +0100 Subject: Added html+css out; Merge features of LogBot; Added logrotate .. etc --- assets/footer.html | 13 ++ assets/header.html | 22 ++++ assets/style.css | 73 +++++++++++ scripts/jogamp-log01.sh | 7 +- scripts/jogamp-log02.sh | 13 ++ src/org/jogamp/jabot/irc/CatOut.java | 173 ++++++++++++++++++------- src/org/jogamp/jabot/irc/LogBot.java | 219 ++++++++++++++++++++++++++++++++ src/org/jogamp/jabot/util/TimeTool.java | 32 ++++- 8 files changed, 499 insertions(+), 53 deletions(-) create mode 100644 assets/footer.html create mode 100644 assets/header.html create mode 100755 assets/style.css create mode 100755 scripts/jogamp-log02.sh create mode 100644 src/org/jogamp/jabot/irc/LogBot.java diff --git a/assets/footer.html b/assets/footer.html new file mode 100644 index 0000000..145b935 --- /dev/null +++ b/assets/footer.html @@ -0,0 +1,13 @@ + + + + + + diff --git a/assets/header.html b/assets/header.html new file mode 100644 index 0000000..2f31829 --- /dev/null +++ b/assets/header.html @@ -0,0 +1,22 @@ + + + + + + + + JogAmp IRC Chat Logs + + +
+ + +
+
diff --git a/assets/style.css b/assets/style.css new file mode 100755 index 0000000..fe3f3e0 --- /dev/null +++ b/assets/style.css @@ -0,0 +1,73 @@ + +body {padding:15px 20px; margin:0; background: #f5f5f5; font-family: "Trebuchet MS", arial, verdana, helvetica, sans-serif;} + +#container {/*background-color:#ffffff;*/ padding:0px; min-width:700px;} + +#header {height:90px; background-color:#ffffff;} +#logo {font-size:40px; padding:25px 0 0 30px;} +#logo a {color:#444444; text-decoration:none; } +#logo img { margin-top: -10px; border-style:none; } +#slogan {float:right; font-size:18px; color:#444444; padding:65px 15px 0 0;} + +/*webside theme colors*/ +#menu, #menu li, #sidebar li a:hover, #footer {background-color:#c9e2ff;} +#menu a, #footer a, #footer {color: #3b4d4f} + +#menu {height:40px; margin-top:5px;} +#menu ul {margin:0; padding:0;} +#menu li {list-style:none; float:left;} +#menu a {float:left; height:20px; padding:10px 20px; font-size:15px; font-weight:bold; text-decoration:none; font-family:Arial, Helvetica, sans-serif;} +#menu a:hover {color:#444444; background-color: #ffffff;} + +#main {float:left; width:100%; height:100%; margin:5px 0; background-color: #FFFFFF; font-size:13px; line-height:120%;} +#main a {color:#111111; border-style:none;} +#main a:hover {color:#000000; background-color: #eeeeee;} +#main br {line-height:8px;} +#main img { padding: 5px; border-style:none; } +#main img:hover {background-color:white;} + +.rss {background:url(images/feed-icon-10x10.png) no-repeat scroll 2px 50% !important; padding:0px 0px 0px 15px;} +.fill {margin-right:0 !important;} +.centered {margin-left: auto; margin-right: auto;} +.clear {clear: both} +.column {float: left; padding-left: 25px; padding-right: 50px} + +.irc-date {font-family: Courier New, Courier, mono;} +.irc-green {color: #009200;} +.irc-black {color: #000000;} +.irc-brown {color: #7b0000;} +.irc-navy {color: #00007b;} +.irc-brick {color: #9c009c;} +.irc-red {color: #ff0000;} + +#text ul { margin-left:0em; padding-left:0.2em; margin-bottom:1em; } +#text ul li { background:url(images/bullet.gif) 0em 0.3em no-repeat; padding-left: 0.8em; list-style: none; } +#text ul li { background-image:url(images/bullet_child.gif); } +#text ul li { margin-bottom:0.5em; } +#text ol { margin-left:1.5em; padding-left:0px; } +#text ol li { list-style:decimal; background-image:none; padding-left:0em; } + +#sidebar {width:160px; height: auto; float: right; padding:0 30px 30px 30px; } +#sidebar h3 {font-size:17px; font-weight:normal; margin:20px 0 5px 0;} +#sidebar ul {margin:0; padding:0; /*border-top:1px solid #e6e6ff;*/} +#sidebar li {list-style:none; /*border-bottom:1px solid #e6e6ff;*/} +#sidebar li a {color:#111111; text-decoration:none; padding:3px; display:block;} + +#text {margin-right:225px; padding:10px 30px 30px 30px; border-right: 5px solid #F5F5F5;} +#text h1 {font-size:22px; font-weight:normal; margin:20px 0 10px 0;} +#text h2 {font-size:19px; font-weight:normal; margin:20px 0 10px 0;} +#text ol, #text ul {padding:0; margin:8px 0;} +#text li {margin-left:40px;} + +#footer {height:40px; font-size:11px; clear:both;} +#footer a:hover {color:#444444;} +#footer_left {float:left; padding:5px 0 0 5px;} +#footer_left img {float: left; margin-right: 5px;} + +#footer_right {float:right; padding:13px 30px 0 0;} + +td.streams_text { text-align: left; vertical-align: middle; } +td.streams_thumbs { width:400px; } +#streams img { width:120px; height:90px; } + + diff --git a/scripts/jogamp-log01.sh b/scripts/jogamp-log01.sh index f9013f5..5dc3762 100755 --- a/scripts/jogamp-log01.sh +++ b/scripts/jogamp-log01.sh @@ -1,5 +1,8 @@ #! /bin/bash -LOGFILE=irc_jogamp_`date -u +%Y%m%d%H%M`.txt +LOGFILE=irc_jogamp_CatOut_slog_`date -u +%Y%m%d%H%M`.txt -java -cp build/jabot.jar org.jogamp.jabot.irc.CatOut -login jogamp -name CatOut -server irc.freenode.net -channel "#jogamp" >& $LOGFILE +java -cp build/jabot.jar org.jogamp.jabot.irc.CatOut \ + -login jogamp -name CatOut \ + -server irc.freenode.net -channel jogamp \ + >& $LOGFILE diff --git a/scripts/jogamp-log02.sh b/scripts/jogamp-log02.sh new file mode 100755 index 0000000..870ec5f --- /dev/null +++ b/scripts/jogamp-log02.sh @@ -0,0 +1,13 @@ +#! /bin/bash + +LOGFILE=irc_jogamp_CatOut_slog_`date -u +%Y%m%d%H%M`.log + +java -cp build/jabot.jar org.jogamp.jabot.irc.CatOut \ + -login jogamp -name CatOut \ + -server irc.freenode.net -channel jogamp \ + -logrotate 10000 \ + -logprefix "irclogs/irc_" \ + -htmlHeader assets/header.html \ + -htmlFooter assets/footer.html \ + >& $LOGFILE + diff --git a/src/org/jogamp/jabot/irc/CatOut.java b/src/org/jogamp/jabot/irc/CatOut.java index af2f04d..c7888b3 100644 --- a/src/org/jogamp/jabot/irc/CatOut.java +++ b/src/org/jogamp/jabot/irc/CatOut.java @@ -1,59 +1,53 @@ +/** + * 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.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.Locale; -import java.util.TimeZone; import org.jibble.pircbot.PircBot; import org.jogamp.jabot.util.TimeTool; public class CatOut extends PircBot { - private final TimeZone timeZone; - private final Locale locale; - private final Calendar calendar; + private static final String HASH = "#"; - public CatOut() { - this(TimeTool.getNearZuluTimeZone(), Locale.getDefault()); - } - - public CatOut(TimeZone timeZone, Locale locale) { - this.timeZone = timeZone; - this.locale = locale; - calendar = new GregorianCalendar(timeZone, locale); - } - - public final TimeZone getTimeZone() { return timeZone; } - public final Locale getLocale() { return locale; } - - /** Returns timestamp of internal Calendar: YYYYMMDD HH:MM:SS (TMZ) */ - public final String getTimeStamp() { - return TimeTool.getTimeStamp(calendar); - } - - public final void setLoginAndName(String login, String nick) { - super.setLogin(login); - super.setName(nick); - } - - /** Updates internal Calendar w/ current time */ - public final void tick() { - calendar.setTimeInMillis(System.currentTimeMillis()); - } - - public void onMessage(String channel, String sender, - String login, String hostname, String message) { - tick(); - System.out.println(getTimeStamp()+" <"+sender+"/"+login+">: "+message); + private static long atol(String str, long def) { + try { + return Long.parseLong(str); + } catch (Exception ex) { + ex.printStackTrace(); + } + return def; } public static void main(String[] args) throws Exception { - final String login, name, server, channel; + final String joinMessage = "This channel is logged"; + final String login, name, server, channelNoHash; final boolean verbose; + final long logrotate; + final String logprefix; + final boolean htmlOut; + final File htmlHeader, htmlFooter; { - String _login=null, _name=null, _server=null, _channel=null; + String _login=null, _name=null, _server=null, _channelNoHash=null; boolean _verbose=false; + long _logrotate = 0; + String _logprefix=""; + boolean _htmlOut = false; + String _htmlHeader = null, _htmlFooter=null; for(int i=0; i= logrotate ) { + // bot.sendRawLine("NAMES "+HASH+channelNoHash); // FIXME ? + } else { + PrintStream fout = null; + long t0 = System.currentTimeMillis(); + int sendNamesCount = 0; + while(true) { // forever ! + // Swap Logfiles: Open and set new logfile, then close old one. + { + final Calendar calendar = bot.tick(); + final String suffix = htmlOut ? ".html" : ".txt" ; + final String logfilename = logprefix+channelNoHash+"_"+name+"_"+TimeTool.getTimeStamp(calendar, true, false)+suffix; + final File _file = new File(logfilename); + final PrintStream _fout = new PrintStream(new FileOutputStream(_file)); + if(htmlOut) { + cat(htmlHeader, _fout); + htmlHead(HASH+channelNoHash+" @ "+server+" - "+bot.getTimeStamp()+" ("+calendar.getTimeZone().getID()+")", + _fout); + } + bot.setOut(_fout); + // bot.sendRawLine("NAMES "+HASH+channelNoHash); // FIXME ? + if(null != fout) { + if(htmlOut) { + cat(htmlFooter, fout); + } + fout.close(); // implies flush + } + fout = _fout; + } + final long t1 = System.currentTimeMillis(); + long td = 0; + while ( td < logrotate ) { + try { + Thread.sleep(FLUSH_INTERVAL); + } catch (Exception e) { } + fout.flush(); + final long t2 = System.currentTimeMillis(); + td = t2 - t1; + if ( sendNamesCount < ( t2 - t0 ) / SEND_NAMES ) { + // bot.sendRawLine("NAMES "+HASH+channelNoHash); // FIXME ? + sendNamesCount++; + } + } + } + } } + public static final long FLUSH_INTERVAL = 60*1000; // every minute + public static final long SEND_NAMES = 10*60*1000; // every 10 minutes + + public static void cat(File source, PrintStream out) throws IOException { + final BufferedInputStream input = new BufferedInputStream(new FileInputStream(source)); + int bytesRead = 0; + byte[] buffer = new byte[1024]; + while ((bytesRead = input.read(buffer, 0, buffer.length)) != -1) { + out.write(buffer, 0, bytesRead); + } + out.flush(); + input.close(); + } + public static void htmlHead(String head, PrintStream out) { + out.println("

"+head+"

"); + out.println("
"); + } } diff --git a/src/org/jogamp/jabot/irc/LogBot.java b/src/org/jogamp/jabot/irc/LogBot.java new file mode 100644 index 0000000..4afee5d --- /dev/null +++ b/src/org/jogamp/jabot/irc/LogBot.java @@ -0,0 +1,219 @@ +/** + * 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 { + + private static final Pattern urlPattern = Pattern.compile("(?i:\\b((http|https|ftp|irc)://[^\\s]+))"); + + 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 final Calendar calendar; + private final Object timeSync = new Object(); + + private final boolean xmlOut; + private final Object outSync = new Object(); + private PrintStream out; + + private String joinMessage; + + public LogBot(String joinMessage, boolean xmlOut) { + this(joinMessage, TimeTool.getNearZuluTimeZone(), Locale.getDefault(), System.out, xmlOut); + } + + public LogBot(String joinMessage, TimeZone timeZone, Locale locale, PrintStream out, boolean xmlOut) { + calendar = new GregorianCalendar(timeZone, locale); + this.xmlOut = xmlOut; + this.out = out; + this.joinMessage = joinMessage; + } + + public final void setLoginAndName(String login, String nick) { + super.setLogin(login); + super.setName(nick); + } + + 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) { + synchronized(outSync) { + final PrintStream old = out; + out = newOut; + return old; + } + } + + public void append(String color, String line) { + tick(); + + 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) { + out.println("[" + getTimeStamp() + "] " + line + "
"); + } else { + out.println(getTimeStamp()+" "+line); + } + out.flush(); + } + + } + + 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 + "@" + hostname + ") 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 + "@" + hostname + ") 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 + "@" + sourceHostname + ") 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); + } + } + + public void onDisconnect() { + append(NAVY, "* Disconnected."); + while (!isConnected()) { + try { + reconnect(); + } + catch (Exception e) { + try { + Thread.sleep(10000); + } + catch (Exception anye) { + // Do nothing. + } + } + } + } +} diff --git a/src/org/jogamp/jabot/util/TimeTool.java b/src/org/jogamp/jabot/util/TimeTool.java index de90361..23f527a 100644 --- a/src/org/jogamp/jabot/util/TimeTool.java +++ b/src/org/jogamp/jabot/util/TimeTool.java @@ -1,3 +1,12 @@ +/** + * 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.util; import java.util.Calendar; @@ -37,8 +46,15 @@ public class TimeTool { return tz; } - /** Returns timestamp of internal Calendar: YYYYMMDD HH:MM:SS (TMZ) */ - public static String getTimeStamp(final Calendar calendar) { + /** + * Returns timestamp of internal Calendar: YYYYMMDD HH:MM:SS + * + * @param calendar Calendar providing current time + * @param withHour if true includes daytime w/ or w/o spacing, otherwise just YYYYMMDD + * @param withSpacing if true provides spacing, otherwise just YYYYMMDDHHMMSS + * @return + */ + public static String getTimeStamp(final Calendar calendar, boolean withHour, boolean withSpacing) { final int year, month, day, hour, minute, seconds; { year = calendar.get(Calendar.YEAR); @@ -48,8 +64,16 @@ public class TimeTool { minute = calendar.get(Calendar.MINUTE); seconds = calendar.get(Calendar.SECOND); } - return String.format("%04d%02d%02d %02d:%02d:%02d (%s)", - year, month, day, hour, minute, seconds, calendar.getTimeZone().getID()); + if( !withHour ) { + return String.format("%04d%02d%02d", year, month, day); + } else { + if( !withSpacing ) { + return String.format("%04d%02d%02d%02d%02d%02d", + year, month, day, hour, minute, seconds); + } else { + return String.format("%04d%02d%02d %02d:%02d:%02d", year, month, day, hour, minute, seconds); + } + } } } -- cgit v1.2.3