r1ch.net forums
* Home Help Search Login Register
r1ch.net  |  r1ch.net stuff  |  Bitchbot  |  Topic: BitchBot log displayer
Pages: [1]
Print
Author Topic: BitchBot log displayer  (Read 5093 times)
[hiop]Peanut
Guest
« on: July 09, 2003, 03:09:36 pm »

Hello!
Installed bitchbot for my clan IRC channel for a bit of fun, noticed it's writing a nice log, so added two more lines in bitch.pl so it also logs JOIN's and NICK's, and wrote a wee script to display this so's you can filter/read/search the log.
Interested to hear if you try it, like it, can improve it! :)
(yes - I did nab some of the disclaimers from r1ch!)

Code:
#!/usr/bin/perl -w
#########################################################################
#
# bitchlog: a script to display bitchbott log files online with filtering
# capabilities.
#
# Author:  Robin Clarke
#
# Date: 09.07.2003
#
# Purpose: so regulars of an IRC channel can read'n'filter stuff that
# happened when they weren't online (god-forbid! ;) )
#
# It's not very pretty, but it's simple and practical.
# Also, please note THIS SOURCE IS PROBABLY NOT 100% SECURE AND/OR WORKING.
#
# If you know ANYTHING about Perl I'm sure (and hopeful) you'll find 101
# ways to optomise/improve the code, and will tell me!
# email any comments to bitchlog@robinclarke.net
#
# see http://www.r1ch.net/projects/bitchbot/ for more details on bitchbot
#
#
#########################################################################
#
# Copyright (C) 2003 Robin Clarke
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#    View the license online at http://www.gnu.org/copyleft/gpl.html
#
#########################################################################

### Vars to set up program
my $version = "0.34";
my $defaultShow = 50;        # number of lines to show by default
my $timeCol = "#339933";     # colour of time stamp
my $dateCol = "#FF6666";     # colour of date stamp
my $nickCol = "#333399";     # colour of nicks
my $wrap = 110;               # at what lenght to wrap lines

# just so we're working on same data as the bitch is
do "/home/clarke/progs/bitchbot/bitch.conf" or die "$!\n";

### Start program
use Time::Local;
use POSIX qw(strftime);
my $debug = undef;
my $errors = undef;
my %input = &getQuery();
my $totalLines = "0";

my $title = "chatlog of $channel on $server heard by $botname : bitchlog $version";
my $textTime = "" . nicetime( time() );

my $from = undef;
my $to = undef;
if( $input->{from} ){
    $errors .= "From time/date was not in a valid format... it has been ignored.\n"
        unless ( $from = parseDate( $input->{from} ) );
}
if( $input->{to} ){
    $errors .= "To time/date was not in a valid format... it has been ignored.\n"
        unless ( $to = parseDate( $input->{to} ) );
}

my $show = ( $input->{show} ? $input->{show} : $defaultShow );  # how many lines to display
my $nick = ( $input->{nick} ? $input->{nick} : "" );         # only display messages from this nick
my $filter = ( $input->{filter} ? $input->{filter} : "" );   # filter text to display only lines containing this
my $hlnick = ( $input->{hlnick} ? $input->{hlnick} : "" );   # text from this nick should be highlighted

# unbuffer output and start sending page...
$| = 1;
print <<EOM;
Content-type: text/html

<HTML>
<HEAD>
  <TITLE>$title</TITLE>
</HEAD>
<BODY>
<H2>$title</H2>
<FORM METHOD='GET'>
<TABLE BORDER='1'>
<TR>
  <TH>From</TH><TH>Untill</TH><TH>Show</TH><TH>Nick Filter</TH><TH>Text Filter</TH><TH>HL Nick</TH><TH></TH>
</TR>
<TR>
  <TD><INPUT TYPE="text" SIZE="19" NAME="from" VALUE="$input->{from}"></TD>
  <TD><INPUT TYPE="text" SIZE="19" NAME="to" VALUE="$input->{to}"></TD>
  <TD><INPUT TYPE="text" SIZE="5" NAME="show" VALUE="$show"></TD>
  <TD><INPUT TYPE="text" SIZE="15" NAME="nick" VALUE="$nick"></TD>
  <TD><INPUT TYPE="text" SIZE="15" NAME="filter" VALUE="$filter"></TD>
  <TD><INPUT TYPE="text" SIZE="15" NAME="hlnick" VALUE="$hlnick"></TD>
  <TD><INPUT TYPE="submit" VALUE="Filter"></TD>
</TR>
</TABLE>

</FORM>
<PRE>
EOM

print "$debug\n\n" if( $debug );
print "$errors\n\n" if( $errors );

if( $log = &gimmeLog() ){
    print $log;
}else{
    print "No log to display meeting your criteria";
}

# finish off the page
print "\n\nLocal time here/now is $textTime\nThere are $totalLines lines in the log\n";
print "I applied following filters:\n" if( $nick || $filter || $from || $to );
print "Nickname had to contain <B>" . lc( $nick ) . "</B>\n" if ( $nick );
print "Text had to contain <B>" . lc( $filter ) . "</B>\n" if ( $filter );
print "Message had to be <I>after</I> <B>" . nicetime( $from ) . "</B>\n" if( $from );
print "Message had to be <I>before</I> <B>" . nicetime( $to ) . "</B>\n" if( $to );
print "</PRE>\n</BODY>\n</HTML>";

exit;

### Subroutines
# gets all appropriate log lines
sub gimmeLog{
    my $log;
    return $! unless ( open( LOG, "<$logfile" ) );
    my( $lastD, $lastM, $lastY );
    my @lines = <LOG>;
    close LOG;
    $totalLines = scalar( @lines );
    my $lineCount = 0;     # counts the number of lines parsed
    my $displayCount = 0;  # counts the number of lines displayed
  LINE:
    while( $displayCount < $show && $lineCount < $totalLines ) {
        $lineCount++;
        ($lTime, $lAction, $lNick, $lText) = split ("\001", $lines[ $totalLines - $lineCount ] );
        ( $sec, $min, $hour, $day, $month, $year, undef ) = localtime( $lTime );
        $year += 1900;  $month++;
       
        # skip this line if any of the filters entered by the user say-so
        next LINE unless( !$nick || $lNick =~ m/$nick/i );
        next LINE unless( !$filter || $lText =~ m/$filter/i );
        next LINE unless( !$from || $lTime > $from );
        next LINE unless( !$to || $lTime < $to );
        $displayCount++;
       
       
        # add in the date to the log if we've traversed to a new day
        unless( $lastD && $lastM && $lastY && ( $lastD == $day && $lastM == $month && $lastY == $year ) ){
            $log .= "<FONT SIZE='+1' COLOR='$dateCol'><B>" . sprintf( "%02d", $day ) . "." . sprintf( "%02d", $month ) .
                "." . sprintf( "%02d", $year ) . "</B></FONT>\n";
            $lastD = $day;
            $lastM = $month;
            $lastY = $year;
        }
       
        # I like some of the text to appear in different colours...
        $tCol = undef;
        if( $lAction == 1 ){ $tCol = "#ff33ff"; }
        elsif( $lAction == 2 || $lAction == 6 || $lAction == 7 || $lNick eq $botname ){ $tCol = "#999999"; }

        # don't display secret lines
        $lText = "-- something secret was said! --\n" if $lText =~ m/^:s/i;

        # wrap text
        if( ( length( $lText ) + length( $lNick ) ) > $wrap ){
            $lText = wrap( $lText, length( $lNick ) );
        }
       
        # HighLight a line if is lines Nick matches hlnick, and then print the line to the log
        $hl = ( $hlnick && $lNick =~ m/$hlnick/i ? 1 : undef );
        $log .= "<B>" if( $hl );
        $log .= "<FONT COLOR='$timeCol'>[" . sprintf( "%02d", $hour ) . ":" . sprintf( "%02d", $min ) . ":" .
            sprintf( "%02d", $sec ) .  "]</FONT><FONT COLOR='$nickCol'>" . "$lNick</FONT>: " .
            ( $tCol ? "<FONT COLOR='$tCol'>$lText</FONT>" : $lText ) ;
        $log .= "</B>" if( $hl );
    }
    return ( $log ? $log : "Nothing to display meeting your criteria through $totalLines lines...\n" );
}

# parses the entries from the query
sub getQuery{
    my $query = undef;
    unless( $ENV{ "REQUEST_METHOD" } ){
        return undef;
    }
    if( $ENV{ "REQUEST_METHOD" } eq "GET" ){
        $query = $ENV{ "QUERY_STRING" };
    } elsif( $ENV{ "REQUEST_METHOD" } eq "POST" ){
        read( STDIN, $query, $ENV{ "CONTENT_LENGTH" } );
    }
#    $debug .= "$ENV{ REMOTE_ADDR }:$query\n";

    my (%input, @elements, $element, $key, $value );
    @elements = split /&/, $query;
    for $element( @elements ){
        $element =~ tr/+/ /;    # decode '+' to spaces
        ($key, $value) = split( /=/, $element );
        $key   =~ s/%([\dA-Fa-f]{2})/pack("C",hex($1))/ge;   # decode key
        $value =~ s/%([\dA-Fa-f]{2})/pack("C",hex($1))/ge;   # decode value
        if( defined $input->{ $key } ){
            $input->{ $key } .= "\0$value";
        } else {
            $input->{ $key } = $value;
        }
    }
    %input;
}

# wraps a text line
sub wrap{
    my $in = shift;
    my $lbuff = shift;
    $lbuff += 12;  # 12 chars for time
    my $out = undef;
    my $rWrap = ( $wrap - $lbuff > 0 ? $wrap - $lbuff : 10 );
    return $in unless( index( $in, " " ) > 0 );
    while( length( $in ) > $rWrap ){
        $index = 0; $try = 0;
        while( ( $try = index( $in, " ", $index + 1 ) ) > 0 && $try < $rWrap ){ $index = $try; } # find last space
        $index = ( $try > 0 ? $try : length( $in ) - 1  ) if( $index == 0 );
        $out .= "" . ( $out ? ( " " x $lbuff ) : "" ) .  substr( $in, 0, $index ) . "\n";
        $in = substr( $in, $index + 1 ); # add one to remove the space you've just stopped at.
    }
    $out .= ( " " x $lbuff ) . $in if( length( $in ) > 0 ); # don't forget to add erst of line
    return $out;
}

# various formats of text entry into from/until fields are parsed here to a fully qualified time
# [number]d = [number] days ago (to the second)
# [number]h = [number] hours ago (to the second)
# [number]m = [number] minutes ago (to the second)
# hh:mm:ss-DD.MM.YYYY is the way to define a static date.      
sub parseDate{
    my $in = shift;
    if( $in =~ m/^(\d*)D$/i ){
        return time() - ( $1 * 86400 );
    }elsif( $in =~ m/^(\d*)H$/i ){
        return time() - ( $1 * 3600 );
    }elsif( $in =~ m/^(\d*)M$/i ){
        return time() - ( $1 * 60 );
    }elsif( $in =~ /^(\d{2}):(\d{2}):(\d{2})-(\d{2})\.(\d{2})\.(\d{4})$/ ){
        $temp = $5 - 1;
        return timelocal( $3, $2, $1, $4, $temp, $6 );
    }
    return undef;
}

# this is the time format /I/ likes
sub nicetime{
    $in = shift;
    return strftime( "%a %d.%b.%Y %H:%M:%S", localtime( $in ) );
}
[/code]
Logged
R1CH who doesn't log in
Guest
« Reply #1 on: July 30, 2003, 10:01:12 pm »

Wow, first contributed script Smiley. If you don't mind I'll include this with the next bitchbot release (if/when that ever happens...)
Logged
[hiop]Peanut
Guest
« Reply #2 on: August 24, 2003, 06:36:55 pm »

Most excelent! Smiley
Download the latest version (more functions, nicer display) at http://robinclarke.net/scripts.html
Logged
Pages: [1]
Print
r1ch.net  |  r1ch.net stuff  |  Bitchbot  |  Topic: BitchBot log displayer
Jump to:  

Powered by SMF 1.1.19 | SMF © 2013, Simple Machines