Google Blogoscoped

Sunday, February 13, 2005

Logging IRC

Google searches a lot, but so far they won’t touch IRC, the Internet Relay Chat network*. Here, people meet and talk all day long, and of course, they produce a lot of content doing so. But how do you track what’s important to you in that content?

*Though a while ago, there were rumors of a Google spider crawling chat channels, no Google tool has surfaced yet. If nothing else there may be huge privacy issues.

Over at CodeDemons.net a tutorial shows you how to build an IRC bot, and how it can also be used to log what’s being said while you’re away. I modified the file and was surprised how easy it is to log IRC.

If you installed PHP you can download my modified PHP script:

<?php

error_reporting(E_ERROR | E_PARSE);

$CONFIG = array();
$CONFIG['server'] = 'graz2.at.eu.undernet.org'; // server (i.e. irc.gamesnet.net)
$CONFIG['nick'] = 'littleboy'; // nick (i.e. demonbot)
$CONFIG['port'] = 6662; // port (standard: 6667)
$CONFIG['channel'] = '#AllNiteCafe'; // channel  (i.e. #php)
$CONFIG['name'] = 'littleboy'; // bot name (i.e. demonbot)
$CONFIG['admin_pass'] = 'asus123';
$CONFIG['log_type'] = "file"; // options: none, file, mysql
$CONFIG['file_name'] = "C:\bot\log.txt"; // the name of the file to log the chat to

$SQL['server'] = "localhost";
$SQL['username'] = "root";
$SQL['password'] = "";
$SQL['database'] = "codedemons";
$SQL['table'] = "irc_logs"; // the table to log chat to

/*
mysql_connect($SQL['server'], $SQL['username'], $SQL['password']) 
    or die ("Could not connect to database server. ". mysql_error());
mysql_select_db($SQL['database'])
    or die ("Could not select database. ". mysql_error());    
*/

set_time_limit(0);
$con = array();

init();

function init()
{
    global $con, $CONFIG;
    $firstTime = true;
    
    $con['socket'] = fsockopen($CONFIG['server'], $CONFIG['port']);
    
    if (!$con['socket']) {
        print ("Could not connect to: ". $CONFIG['server'] ." on port ". $CONFIG['port']);
    } else {
        cmd_send("USER ". $CONFIG['nick'] ." codedemons.net codedemons.net :". $CONFIG['name']);
        cmd_send("NICK ". $CONFIG['nick'] ." codedemons.net");
        
        while (!feof($con['socket']))
        {
            $con['buffer']['all'] = trim(fgets($con['socket'], 4096));

            print date("[d/m @ H:i]")."<- ".$con['buffer']['all'] ."\n";
            
            if(substr($con['buffer']['all'], 0, 6) == 'PING :') {
                cmd_send('PONG :'.substr($con['buffer']['all'], 6));
                if ($firstTime == true){
                    cmd_send("JOIN ". $CONFIG['channel']);
                    $firstTime = false;
                }
            }
            else if ($old_buffer != $con['buffer']['all'])
            {
                if ($CONFIG['log_type'] == "file")
                {
                    $to_log = "[". date("d-j-y@H:i:s") ."]";
                    $to_log .= " ". $con['buffer']['username'];
                    $to_log .= ": ". $con['buffer']['text'] ."\r\n";
                    log_to_file($to_log);
                }
                else if ($CONFIG['log_type'] == "mysql")
                {
                    log_to_mysql($con['buffer']['channel'], $con['buffer']['username'], $con['buffer']['text']);
                }
                parse_buffer();
                process_commands();
            }
            $old_buffer = $con['buffer']['all'];
        }
    }
}

function cmd_send($command)
{
    global $con, $time, $CONFIG;
    fputs($con['socket'], $command."\n\r");
    print (date("[d/m @ H:i]") ."-> ". $command. "\n\r");
    
}

function log_to_file ($data, $important = false)
{
    if ($important)
    {
        global $CONFIG;
    
        if ($fp = fopen($CONFIG['file_name'], "ab"))
        {
            if ( (fwrite($fp, $data) === FALSE) )
            {
                echo "Could not write to file " . $CONFIG['file_name'] . ".\r\n";
            }
        }
        else
        {
            echo "File " . $CONFIG['file_name'] . "could not be opened.\r\n";
        }
    }
}

function log_to_mysql($channel, $username, $test)
{
    global $CONFIG;
    
    $query = "INSERT INTO ". $CONFIG['table'] ." (time, channel, username, text) 
        VALUES ('". time() ."', '". $channel ."', '". $username ."', '". $test ."')";
    mysql_query($query);
}

function process_commands()
{
    global $con, $CONFIG;

    $said = $con['buffer']['text'];
    $lsaid = strtolower($said);
    $thisdate = date( "F j, Y, g:i a", time() );
    $break = "\r\n";

    if ( !( strpos($lsaid, 'google') === false ) || !( strpos($lsaid, 'search') === false ) )
    {
        logline('[Google ' . $thisdate . '] ' . $break . $said);
        // say("Gotcha.");
    }

    if ( !( strpos($lsaid, 'boyboy') === false ) )
    {
        // logline('[Self ' . $thisdate . '] ' . $break . $said);
        // say("I'm dreaming...");
    }
}

function logline($s)
{
    log_to_file($s . "\r\n\r\n", true);
}

function say($s)
{
    cmd_send( prep_text($s) );
}

function parse_buffer()
{
    global $con, $CONFIG;
        
    $buffer = $con['buffer']['all'];
    $buffer = explode(" ", $buffer, 4);
    
    $buffer['username'] = substr($buffer[0], 1, strpos($buffer['0'], "!")-1);
    
    $posExcl = strpos($buffer[0], "!");
    $posAt = strpos($buffer[0], "@");
    $buffer['identd'] = substr($buffer[0], $posExcl+1, $posAt-$posExcl-1); 
    $buffer['hostname'] = substr($buffer[0], strpos($buffer[0], "@")+1);
    
    $buffer['user_host'] = substr($buffer[0],1);
    
    switch (strtoupper($buffer[1]))
    {
        case "JOIN":
               $buffer['text'] = "*JOINS: ". $buffer['username']." ( ".$buffer['user_host']." )";
            $buffer['command'] = "JOIN";
            $buffer['channel'] = $CONFIG['channel'];
               break;
        case "QUIT":
               $buffer['text'] = "*QUITS: ". $buffer['username']." ( ".$buffer['user_host']." )";
            $buffer['command'] = "QUIT";
            $buffer['channel'] = $CONFIG['channel'];
               break;
        case "NOTICE":
               $buffer['text'] = "*NOTICE: ". $buffer['username'];
            $buffer['command'] = "NOTICE";
            $buffer['channel'] = substr($buffer[2], 1);
               break;
        case "PART":
              $buffer['text'] = "*PARTS: ". $buffer['username']." ( ".$buffer['user_host']." )";
            $buffer['command'] = "PART";
            $buffer['channel'] = $CONFIG['channel'];
              break;
        case "MODE":
              $buffer['text'] = $buffer['username']." sets mode: ".$buffer[3];
            $buffer['command'] = "MODE";
            $buffer['channel'] = $buffer[2];
        break;
        case "NICK":
            $buffer['text'] = "*NICK: ".$buffer['username']." => ".substr($buffer[2], 1)." ( ".$buffer['user_host']." )";
            $buffer['command'] = "NICK";
            $buffer['channel'] = $CONFIG['channel'];
        break;
        
        default:
            $buffer['command'] = $buffer[1];
            $buffer['channel'] = $buffer[2];
            $buffer['text'] = substr($buffer[3], 1);    
        break;    
    }
    $con['buffer'] = $buffer;
}

function prep_text($message)
{
    global $con;
    return ('PRIVMSG ' . $con['buffer']['channel'] . ' :' . $message);
}

?>

Change the configuration settings at the top – your bot’s name, the server and channel, and the log file path – and run it via the command line by entering e.g. C:\php5\php.exe C:\bot\irc.php. I suggest to join the channel yourself using a program like mIRC to check everything’s working. (You can also use mIRC to find out about popular servers and chat rooms.)

Now whenever someone mentions “Google” or “search”, your log file will have a new line with what has been said. The script I’ve got running on my machine logged the following in the past half hour:

[Google February 13, 2005, 6:05 pm] 
put "ravana" on search  on google

Of course you can track any other keyword too. Search the PHP file for “google” and you will see the “process_commands” function. This function can either do a “logline” to add something to the log file, or execute the “say” command to say something in the channel.

The “process_commands” function can also be used to do anything else PHP (and the chat network guidelines) allows you to. You can connect to a database to perform calculations or track words. You can check the Google page-count of words said, and track rare words mentioned often (the hot topics du jour). By parsing what’s being said in the channel, your bot can also join the conversation and react to other people. A bot type popular in some channels, for example, listens to the “google” command and will dynamically execute a Google search and return the result in the channel for everyone to click on.

Advertisement

 
Blog  |  Forum     more >> Archive | Feed | Google's blogs | About
Advertisement

 

This site unofficially covers Google™ and more with some rights reserved. Join our forum!