I tend to hang out a lot on the #ltsp IRC channel, and I found myself remembering some interesting things that were said, but since there are no logs on the web, there was no way to review the chat histories. The only option was to set up a irc log bot and create a webpage that would stream the content of the irc logbot to it. I found a great little php logobot, which after some tweaking worked quite well. The main issue with it is that it requires a frontend to be created for it that pulls all the logged data from a mysql database in some way. There are many ways to do this, including using various php frameworks, or even another language entirely, but for now, I decided to code something later on down the line that includes an archive of the logs including paginations and the like.
To run the bot, one requires the NET_SmartIRC pear class, which can be installed doing:
pear install NET_SmartIRC
The bot requires an SQL import (you can do that with phpmyadmin for example) with the following:
DROP TABLE IF EXISTS `irc_log`;
CREATE TABLE IF NOT EXISTS `irc_log` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`datetime` timestamp NOT NULL default CURRENT_TIMESTAMP,
`nick` varchar(32) NOT NULL default '',
`ident` varchar(64) NOT NULL default '',
`host` varchar(254) NOT NULL default '',
`type` varchar(4) NOT NULL default '',
`from` varchar(254) NOT NULL default '',
`channel` varchar(32) NOT NULL default '',
`message` text NOT NULL,
PRIMARY KEY (`id`),
FULLTEXT KEY `nick_msg` (`nick`,`message`)
)DEFAULT CHARSET=utf8;
Here is the code for the bot. This was created by someone else, but I changed a couple of things so it will run on Debian. Remember to change the user and channel details in the beggining and end of the script and then run by doing:
php irclogbot.php
'<'?php /**="" *="" an="" irc="" logbot="" based="" on="" pear::net_smartirc="" logs="" channel="" to="" a="" mysql="" database,="" triggered="" by="" "actionhandler"s="" as="" implemented="" in="" smartirc.="" actionhandler="" values="" are="" defined="" net_smartirc/smartirc/defines.php="" normal="" conversation="" can="" be="" caught="" smartirc_type_channel,="" /me="" is="" smartirc_type_action="" there="" currently="" no="" logging="" for="" joins/quits/etc.="" this="" script="" has="" been="" written="" server="" with="" php="" version="" 4.4.0-4="" and="" 4.1.15="" @author="" chris="" prior=""
*
*/
//include the pear class (doesn't need an include_path for that dir)
include_once('/usr/share/php/Net/SmartIRC.php');
class irclogbot extends Net_SmartIRC
{
var $hasDbConn=false;
var $mysql_host='localhost';
var $mysql_user='changeme';
var $mysql_password='changeme';
var $mysql_db='changeme';
var $mysql_table='irc_log';
var $log_obj;
var $stats_obj;
var $loggables=array('nick','ident','host','type','from','channel','message');
var $logfileIfMysqlError='errorMysqlINSERT.log';
//function irclogbot(&$log_obj,&$stats_obj2){
//}
/*
* overwriting existing function
*/
function _nicknameinuse()
{
$newnickname = $this->_nick.'_';
$this->changeNick($newnickname, SMARTIRC_CRITICAL);
$this->_register();
}
//unused
function _register()
{
$this->_send('/msg NickServ IDENTIFY changeme', SMARTIRC_CRITICAL);
}
/*
* Basic MySQL auth
*/
function connect_database()
{
$link = @mysql_connect($this->mysql_host, $this->mysql_user, $this->mysql_password)
or die("Keine Verbindung möglich: " . mysql_error());
$this->hasDbConn = @mysql_select_db($this->mysql_db) or die("db select failed.");
}
/*
* the workhorse logging method
*
* Checks for content of $data-> object as returned from PEAR class,
* constructs a SQL statement and inserts with connection check
* Outputs some stuff to stdout
* Don't confuse the 2 stdout sources: parent::setDebug also does it!
*
* never change the methodname to 'log', incompatible to the PEAR class!
*
*/
function my_log(&$irc='',&$data='')
{
$doit=true;
//quick hack to filter out server msg marked S*_TYPE_CHANNEL
foreach($this->loggables as $v){
if (!isset($data->$v)) $doit=false;
//else echo "$v has " . $data->$v."\n"; //debug
}
if($doit){
//there is an 'ACTION' prefix for the message, I strip it.
//To recognize a type `action` I still have the value 256 in the col `type`
if(256==$data->type) {
$data->message = substr($data->message,8);
$data->message = substr($data->message,0,strlen($data->message)-1);
}//end if type 256 == action
/**
* The following does not work if there is no db link,
* so I use mysql_real_escape_string selectively.
* This leaves the error log unescaped!!!
*
*/
//split for original debugging as above, could be merged into one foreach
foreach($this->loggables as $v) {
//http://php.net/manual/en/function.stripslashes.php#51390
if (get_magic_quotes_gpc())
$data->$v = stripslashes($data->$v);
//can't use it on the ready query as it would return
// *VALUES '\'myNickName\',*
if(!is_numeric($data->$v) AND $this->hasDbConn )
$data->$v = @mysql_real_escape_string($data->$v);
}
}//end if $doit
//no linebreaks or mysql_real_escape_string breaks the statement!
$sql = sprintf("INSERT INTO %s "
. "(`nick`, `ident`, `host`, `type`, `from`, `channel`, `message` ) "
. " VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s');",
$this->mysql_table,
$data->nick,
$data->ident,
$data->host,
$data->type,
$data->from,
$data->channel,
$data->message
);
//echos to stdout
echo $sql;
/**
* Now we are fighting hard to preserve the log
*/
//the mysql INSERT query
if(!$this->hasDbConn){
$irc->connect_database();
if(!$this->hasDbConn){
$this->logInsertIfMysqlError($sql);
}
}
//new if, not elseif, so a success above triggers
if($this->hasDbConn == true AND $doit)
{
//echo "hasDbConn\n";
$result = @mysql_query($sql);
if (!$result) {
echo('invalid query: ' . mysql_error());
$this->logInsertIfMysqlError($sql);
}
}//end if hasDbConn*
else {
$this->logInsertIfMysqlError($sql);
echo "\n WARNING! Has no DB connection! WARNING!\n";
}
echo "\n\n";
}
/**
* Fallback if no MySQL conn
*
* I got an 'invalid query: MySQL server has gone away' after long a silence.
* This is to preserve the INSERT statements for later addition to the db.
*/
function logInsertIfMysqlError($content){
echo "Trying to log into error logfile ".$this->logfileIfMysqlError."\n";
if(!file_exists($this->logfileIfMysqlError)){
if (touch($this->logfileIfMysqlError) === false){
echo "cannot touch the non-existing file!"."\n";
continue;
}
}
if (!is_writable($this->logfileIfMysqlError)) {
if (!chmod($this->logfileIfMysqlError, 0666)) {
echo "Cannot change the mode of file ($this->logfileIfMysqlError)"."\n";
continue;
};
}
if (!$fp = @fopen($this->logfileIfMysqlError, "a")) {
echo "Cannot open file ($this->logfileIfMysqlError)"."\n";
continue;
}
if (fwrite($fp, $content."\n") === FALSE) {
echo "Cannot write to file ($this->logfileIfMysqlError)"."\n";
continue;
}
else echo "ERROR LOGGED! Wrote into ".$this->logfileIfMysqlError."\n";
if (!fclose($fp)) {
echo "Cannot close file ($this->logfileIfMysqlError)"."\n";
continue;
}
}//end function
/**
* Calling this at startup might catch the worst scenario and
* renders the above logInsertIfMysqlError($str) useless in many respects
*/
function testForErrorLogfile(){
if (!$fp = @fopen($this->logfileIfMysqlError, "a")) {
echo "Cannot open file ($this->logfileIfMysqlError)"."\n";
exit;
}
}//end function
//doesn't work as expected, but I don't care
function my_quit(&$this, &$ircdata)
{
echo 'FooBar';
$this->quit("The Bot has quit.");
}
}//end class ######################################
$irc = &new irclogbot();
$irc->testForErrorLogfile();
//$irc->connect_database();
//pear/Net_SmartIRC/SmartIRC/defines.php
$irc->setDebug(SMARTIRC_DEBUG_NOTICE|SMARTIRC_DEBUG_CONNECTION|SMARTIRC_TYPE_ACTION|SMARTIRC_TYPE_CHANNEL);
$irc->setUseSockets(TRUE);
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, '^sfLog: !quit',
$irc, 'my_quit');
//pear/Net_SmartIRC/SmartIRC/defines.php
//SMARTIRC_TYPE_CHANNEL is defined as `2` and this gets inserted into the db
//never change the methodname to 'log', as it is incompatible to the PEAR class
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, '^.?', $irc, 'my_log');
//type channel does not catch /me et al.
$irc->registerActionhandler(SMARTIRC_TYPE_ACTION, '^.?', $irc, 'my_log');
$irc->connect('irc.freenode.com', 6667);
//Usage: login(nick, realname, usermode, username, password);
$irc->login('editme', 'ltsp logger');
$irc->join(array('#editme'));
$irc->listen();
$irc->disconnect();
?>
Rate It! (Average 0, 0 votes)
