#!/usr/bin/perl
##########################################################################
-# onis 0.7.2 2005-01-21 #
+# onis 0.8.0 2005-04-17 #
#---=============--------------------------------------------------------#
# Language: Perl #
# Purpose: Generating statistics #
# Input: IRC-Logfiles #
# Output: One HTML file #
-# Version: 0.7.2 (unstable) #
+# Version: 0.8.0 (unstable) #
# License: GPL #
# Homepage: http://verplant.org/onis/ #
# Authors: Florian octo Forster <octo@verplant.org> #
use strict;
use warnings;
+use vars qw/$VERSION $REVISION/;
use Onis::Config qw/get_config parse_argv read_config/;
use File::Basename qw/dirname/;
use Fcntl qw/:flock/;
-use vars qw/$VERSION/;
+=head1 NAME
-$VERSION = '0.7.2';
+onis - onis not irs stats
-our $FILEINFO;
-our $PURGE_LOGS = 0;
+=head1 SYNOPSIS
-print STDERR $/, __FILE__, ': $Id: onis,v 1.18 2005/01/21 18:59:59 octo Exp $' if ($::DEBUG);
+B<onis> [I<options>] I<logfile>...
+
+=head1 DESCRIPTION
+
+onis is a script that converts IRC logfiles into an HTML statistics page. It
+provides information about daily channel usage, user activity, and channel
+trivia. It provides a configurable customization and supports Dancer,
+dircproxy, eggdrop, irssi, mIRC, and XChat logs. Persistent data (history
+files) and automatic log purging make onis applicable for a large number of
+logfiles. It also features a powerful translation infrastructure.
+
+=cut
+
+$VERSION = '';
+$REVISION = '$LastChangedRevision$';
+
+if (!$VERSION)
+{
+ $VERSION = $REVISION;
+ $VERSION =~ s/^\D*(\d+).*/r$1/;
+}
+
+our $FileInfo;
+our $PurgeLogs = 0;
+
+print STDERR $/, __FILE__, ': $Id$' if ($::DEBUG);
parse_argv (@ARGV);
-read_config (get_config ('config') ? get_config ('config') : 'config');
+read_config (get_config ('config') ? get_config ('config') : 'onis.conf');
read_config (scalar get_config ('theme')) if (get_config ('theme'));
my $output = get_config ('output');
if (!get_config ('input'))
{
+ # TODO: Make a complete (!) lsit..
print STDERR <<EOF;
Usage: $0 [options] <logfile> [logfile logfile ..]
require "Onis/Parser/$logtype.pm";
require Onis::Parser::Persistent;
require Onis::Data::Persistent;
-import Onis::Parser qw/parse last_date/;
-import Onis::Parser::Persistent qw#newfile#;
-import Onis::Data::Persistent qw#init#;
+import Onis::Parser (qw(parse last_date));
+import Onis::Parser::Persistent (qw(newfile));
+import Onis::Data::Persistent ();
-$FILEINFO = init ('$FILEINFO', 'hash');
+$FileInfo = Onis::Data::Persistent->new ('FileInfo', 'inode', qw(mtime));
if (get_config ('purge_logs'))
{
my $temp = lc (get_config ('purge_logs'));
if (($temp eq 'truncate') or ($temp eq 'shorten'))
{
- $PURGE_LOGS = 1;
+ $PurgeLogs = 1;
}
elsif (($temp eq 'delete') or ($temp eq 'remove')
or ($temp eq 'del'))
{
- $PURGE_LOGS = 2;
+ $PurgeLogs = 2;
}
}
}
else
{
+ my ($old_mtime) = $FileInfo->get ($inode);
+
print STDERR $/, __FILE__, ": ``$file'': " if ($::DEBUG & 0x200);
- if (defined ($FILEINFO->{$inode}{'mtime'}))
+
+ if (defined ($old_mtime))
{
- if ($FILEINFO->{$inode}{'mtime'} == $mtime)
+ if ($old_mtime == $mtime)
{
print STDERR "File did not change. Skipping." if ($::DEBUG & 0x200);
next;
}
- elsif ($FILEINFO->{$inode}{'mtime'} < $mtime)
+ elsif ($old_mtime < $mtime)
{
print STDERR "File changed. Reading it again." if ($::DEBUG & 0x200);
}
{
print STDERR "File appears to be new. Reading it." if ($::DEBUG & 0x200);
}
- $FILEINFO->{$inode}{'mtime'} = $mtime;
+ $FileInfo->put ($inode, $mtime);
}
# truncate
- if ($PURGE_LOGS == 1)
+ if ($PurgeLogs == 1)
{
unless (open ($logfile, '+< ' . $file))
{
}
}
- if ($PURGE_LOGS)
+ if ($PurgeLogs)
{
unless (flock ($logfile, LOCK_EX))
{
}
}
- newfile ($FILEINFO->{$inode});
+ newfile ($FileInfo->{$inode});
while (<$logfile>)
{
s/\n|\r//g;
}
}
- if ($PURGE_LOGS and (($status == 1)
+ if ($PurgeLogs and (($status == 1)
or ($status == 2)
or ($status == 3)))
{
- if (($PURGE_LOGS > 1)
+ if (($PurgeLogs > 1)
#and (($position + 1) >= $size)
)
{
{
print STDERR $/, __FILE__, ": Unable to delete empty file ``$file'': $!";
}
- delete ($FILEINFO->{$inode});
+ delete ($FileInfo->{$inode});
}
else
{
{
print $/ if ($::DEBUG);
}
+
+=head1 OPTIONS
+
+=head2 Core options
+
+=over 4
+
+=item B<config>: I<file>;
+
+Load the config from this file. B<(command line only)>
+
+=item B<users_config>: I<file>;
+
+Sets the file from which to read the user configuration.
+
+=item B<language_file>: I<file>;
+
+Sets the language file/translation to use.
+
+=item B<plugin>: I<string>;
+
+Sets the plugins to load. The plugin B<Core> will always be loaded.
+
+=item B<input>: I<file>;
+
+Read and parse this file(s). B<(config file only)>
+
+=item B<logtype>: I<string>;
+
+Sets the parser to use for parsing the input file.
+
+=item B<output>: I<file>;
+
+Write the generated output to this file.
+
+=item B<overwrite>: I<bool>;
+
+Sets wether or not to overwrite the output-file if it exists.
+
+=item B<purge_logs>: "I<false>" | "I<truncate>" | "I<delete>";
+
+Sets wether logs should be truncated or even removes after they have been
+parsed.
+
+=item B<user>: I<string>;
+
+Sets the user generating the stats if it's not detected right.
+
+=item B<channel>: I<string>;
+
+Sets the name of the channel being parsed. Normally this is auto-detected.
+
+=item B<unsharp>: "I<none>" | "I<light>" | "I<medium>" | "I<hard>";
+
+Sets how to do unsharping. What each setting actually does is described in the
+readme and in L<Onis::Data::Core>.
+
+=back
+
+=head2 Appearance
+
+=over 4
+
+=item B<theme>: I<file>;
+
+Theme file to load.
+
+=item B<stylesheet>: I<file>;
+
+Sets the stylesheet (.css file) to use. This should be set in a theme file.
+
+=item B<color_codes>: I<bool>;
+
+Wether to print mIRC color-codes or filter them.
+
+=item B<display_images>: I<bool>;
+
+Sets if user-images should be displayed.
+
+=item B<default_image>: I<file>;
+
+Sets the default image to use if no user-defined image is available.
+
+=item B<display_lines>: "I<none>" | "I<number>" | "I<bar>" | "I<both>";
+
+=item B<display_words>: "I<none>" | "I<number>" | "I<bar>" | "I<both>";
+
+=item B<display_chars>: "I<none>" | "I<number>" | "I<bar>" | "I<both>";
+
+Sets if and how lines, words and/or characters should be displayed.
+
+=item B<sort_by>: "I<lines>" | "I<words>" | "I<chars>";
+
+Sets wether to sort by lines, words or characters written.
+
+=item B<display_times>: I<bool>;
+
+Wether or not to display a fixed width bar that shows when a user is most
+active.
+
+=item B<bar_height>: I<number>;
+
+=item B<bar_width>: I<number>;
+
+Sets the width of horizontal bars and the height of vertical bars.
+
+=item B<horizontal_images>: I<file>, I<file>, I<file>, I<file>;
+
+=item B<vertical_images>: I<file>, I<file>, I<file>, I<file>;
+
+Sets the images to use for horizontal and vertical bars. This should be used in
+the theme-file.
+
+=item B<encoding>: I<string>;
+
+Sets the encoding for the output file. This is merely the string that will be
+included in the generated HTML file.
+
+=item B<public_page>: I<bool>;
+
+Wether or not this is a public page. Public pages may be linked on the onis
+homepage at some point in the fututre..
+
+=back
+
+=head2 Storage / Persistency
+
+=over 4
+
+=item B<storage_module>: I<string>;
+
+Sets the storage-module to use.
+
+=item B<storage_dir>: I<directory>;
+
+Sets the directory to store persistency information under.
+
+=item B<storage_file>: I<file>;
+
+Sets the file to write persistency data to, if applicable by the
+storage-module.
+
+=back
+
+=head2 Plugins
+
+=over 4
+
+=item B<min_word_length>: I<number>;
+
+Substring containing only word-characters needs to be this long to be
+considered a word.
+
+=item B<plugin_max>: I<number>;
+
+Sets the number of "most referenced nicks", "most used words" and the like to
+be displayed. This option will be removed in the future.
+
+=item B<longlines>: I<number>;
+
+=item B<shortlines>: I<number>;
+
+The number of lines in the big and the small table. While in the big table one
+line is dedicated for one person the small table displays six persons per line.
+
+=item B<quote_cache_size>: I<number>;
+
+Sets how many quotes are to be cached for each nick. At the end of the run one
+of the quotes in the cache will be chosen at random and displayed.
+
+=item B<quote_min>: I<number>;
+
+=item B<quote_max>: I<number>;
+
+Sets the minimum and maximum length of a quote. Too short quotes may be not
+very typical for a person, too long quotes may clutter the layout.
+
+=item B<soliloquies_count>: I<number>;
+
+Sets how many lines without interruption are considered a soliloquy.
+
+=item B<longterm_days>: I<number>;
+
+=item B<userdetails_longterm_days>: I<number>;
+
+Sets the number of days shown in the longterm-plugin (or the longter-section of
+the userdetails-plugin).
+
+=item B<ignore_words>: I<number>;
+
+The Words-Plugin will ignore words with less than this characters.
+
+=back
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octo at verplant.orgE<gt>
+
+=cut