I've written a log proxy that will log each channel separately and produce one log file per channel per day.
The log format is like IRC "eggdrop", so you should have no problems generating channel statistics with programs like pisg or mIRCstats.
Just one thing to remember if you run a multilingual site:
Channel NOTICES will always be in the current client user's language, i.e. "Gast84 kommt in den Raum English" instead of "Gast84 joins English", so you WILL have to tell your statistics software ALL the different strings for the same events! (This is possible with most stats packages so shouldn't be much of a problem.)
Since users might be allowed to create their own channels (or you might be using non-ASCII languages for channel names) and I cannot know if your filesystem is UTF-8-safe, I decided to make logfile names ASCII only. You might want to change that if your filesystem can handle UTF-8 filenames.
So, we CANNOT create a nice-looking channel name for the stats package out of the file name. This is why I "invented" a special NOTICE that will ALWAYS be the first line in the logfile and tell you (or the stats package) the "real" channel name. It looks like this (and it will always be in English):
- Code: Select all
[06:12] -NOTICE- This channel is called 'Русский'
Logfiles are held in the usual place and the directory might look like this:
- Code: Select all
20080201.______________.log
20080201.Deutsch.log
20080201.English.log
20080201.MyNewRoom.log
You can see that this can easily be parsed by a stats package. Filenames are of format
- Code: Select all
YYYYMMDD.channelname.log
The filename above with the many underscores is from the 'Русский' channel (these characters can't be shown in ASCII).
A typical log looks like this ('20080201.English.log' from above):
- Code: Select all
[06:07] -NOTICE- This channel is called 'English'
[06:07] <admin> Good morning!
[06:08] -NOTICE- Gast84 kommt in den Raum English
[06:09] <Gast84> A guest enters the room English
[06:09] Action: Gast84 is quite happy about the new pisg statistics
If you DISABLE the standard 'log' proxy and enable this 'egglog' proxy, you will also have the additional advantage that you will NOT log any private messages between chat users, so it's easier to comply with some countries' personal data and privacy protection acts.
Installation:
1. Copy the source below and save it to the 'src/proxies' folder of your chat installation as egglog.class.php.
2. Add egglog to your parameter 'post_proxies'.
3. Add log to your parameter 'skip_proxies'. This will disable the built-in log that logs everything (including private communication) into the file chat.log.
4. Do a /rehash.
Everything should be running now. Enjoy!
And Stéphane (kerphi) is of course more than welcome to include this in his next version!
After talking at length, here is now the code:
- Code: Select all
<?php
/**
* egglog.class.php
* $Id: egglog.class.php 42 2008-02-01 06:08:29Z matthias $
*
* Copyright © 2008 Matthias C. Hormann (aka Moonbase) <moonbase (at) quantentunnel.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
require_once dirname(__FILE__)."/../pfci18n.class.php";
require_once dirname(__FILE__)."/../pfcuserconfig.class.php";
require_once dirname(__FILE__)."/../pfcproxycommand.class.php";
/**
* pfcProxyCommand_egglog
* this proxy will log channels and NO private messages with daily log files
* more like an eggdrop log, format can easily be used by pisg or mIRCstats
* @author Matthias C. Hormann (aka Moonbase) <moonbase@quantentunnel.de>
*/
class pfcProxyCommand_egglog extends pfcProxyCommand
{
function sanitizeFilename($fname, $default)
{
// needed for security since channel names can be user-generated
// assume ASCII-only file system, since we don't know if it's UFT-8-safe
$fname = trim($fname, " tnr\0x0B."); // get rid of leading and trailing dots and others
// the following is "brute force" but safe
// if your filesystem allows UTF-8, you might want to change this
// but be aware of the numerous UTF-8 "illegal character" hacker attacks!
$fname = preg_replace("/[^0-9A-Za-z()_.-]/", "_", $fname); // allow ASCII, replace anything else with "_"
if (empty($fname))
{
$fname = $default; // default name
}
return $fname;
}
function run(&$xml_reponse, $p)
{
$cmdtocheck = array("send", "me", "notice");
if ( in_array($this->name, $cmdtocheck) )
{
$clientid = $p["clientid"];
$param = $p["param"];
$sender = $p["sender"];
$recipient = $p["recipient"];
$recipientid = $p["recipientid"];
$c =& pfcGlobalConfig::Instance();
$u =& pfcUserConfig::Instance();
$date = date("Ymd");
$channel = (substr($recipient,0,3) == 'ch_' ? substr($recipient,3) : '');
if ($channel != '')
{
// only log channels, no private communication (denoted by 'pv_...')
$logpath = ($c->proxies_cfg[$this->proxyname]["path"] == "" ? $c->data_private_path."/logs" :
$c->proxies_cfg[$this->proxyname]["path"]);
$logpath .= "/".$c->getId();
if (!file_exists($logpath)) @mkdir_r($logpath);
if (file_exists($logpath) && is_writable($logpath))
{
$logfile = $logpath."/".$date.".".$this->sanitizeFilename($channel, "chat").".log";
if (is_writable($logpath))
{
// Since we can't take the real channel name from the (sanitized) file name,
// we write it into the first line of every log file.
// Thus, a statistics program can show the "real" channel name.
// I "disguise" it as a NOTICE -- anyone got a better idea?
if (!file_exists($logfile))
{
$log = "[".date("H:i")."] -NOTICE- This channel is called '".$channel."'n";
file_put_contents($logfile, $log, FILE_APPEND | LOCK_EX);
}
$log = "[".date("H:i")."] ";
switch ($this->name)
{
case "me":
$log .= "Action: ".$sender." ".$param;
break;
case "notice":
$log .= "-NOTICE- ".$param;
break;
case "send":
$log .= "<".$sender."> ".$param;
break;
}
$log .= "n";
file_put_contents($logfile, $log, FILE_APPEND | LOCK_EX);
}
}
}
}
// forward the command to the next proxy or to the final command
return $this->next->run($xml_reponse, $p);
}
}
?>