CodeDemons PHP IRC bot

From S23Wiki

An example of a PHP-based IRC bot by codedemons from a tutorial which is unfortunately not online anymore and can only be fetched from archive.org.

[edit] README.txt

You can use this code however you please. Just 
remember to put in a good word for CodeDemons, 
and our tutorials ;)
By: Jordan Smith
For: http://www.codedemons.net/

Both PHP files in this archive are working 
examples of a bot.

skeleton_bot.php
---------------
This bot only connects to the channel. Adding 
features is up to you. This is the bot that is 
created in the tutorial.

complete_bot.php
---------------
This bot does everything skeleton_bot.php does, 
but also includes examples of functions, such as 
.time (to display the current time), .nick (to 
change the bot's nick), and some more. Perfect 
if you want to see the bot in action, and add a 
few more features. There is also a BASIC logging 
function.

This bot also includes some more functions such as
prep_text(), parse_buffer(), process_commands().

[edit] skeleton_bot.php


<?php
/*
demonbot - a demonstation for codedemons.net
*/

/* Variables that determine server, channel, etc */
$CONFIG = array();
$CONFIG['server'] = 'irc.gamesurge.net'; // server (i.e. irc.gamesnet.net)
$CONFIG['nick'] = 'demonbot'; // nick (i.e. demonbot
$CONFIG['port'] = 6667; // port (standard: 6667)
$CONFIG['channel'] = '#php'; // channel  (i.e. #php)
$CONFIG['name'] = 'demonbot'; // bot name (i.e. demonbot)
$CONFIG['admin_pass'] = 'pass'; // admin pass (to change settings remotely)

/* Let it run forever (no timeouts) */
set_time_limit(0);

/* The connection */
$con = array();

/* start the bot... */
init();

function init()
{
        global $con, $CONFIG;
        /* We need this to see if we need to JOIN (the channel) during
        the first iteration of the main loop */
        $firstTime = true;

        /* Connect to the irc server */
        $con['socket'] = fsockopen($CONFIG['server'], $CONFIG['port']);

        /* Check that we have connected */
        if (!$con['socket']) {
                print ("Could not connect to: ". $CONFIG['server'] ." on port ". $CONFIG['port']);
        } else {
                /* Send the username and nick */
                cmd_send("USER ". $CONFIG['nick'] ." codedemons.net codedemons.net :". $CONFIG['name']);
                cmd_send("NICK ". $CONFIG['nick'] ." codedemons.net");

                /* Here is the loop. Read the incoming data (from the socket connection) */
                while (!feof($con['socket']))
                {
                        /* Think of $con['buffer']['all'] as a line of chat messages.
                        We are getting a 'line' and getting rid of whitespace around it. */
                        $con['buffer']['all'] = trim(fgets($con['socket'], 4096));

                        /* Pring the line/buffer to the console
                        I used <- to identify incoming data, -> for outgoing. This is so that
                        you can identify messages that appear in the console. */
                        print date("[d/m @ H:i]")."<- ".$con['buffer']['all'] ."\n";

                        /* If the server is PINGing, then PONG. This is to tell the server that
                        we are still here, and have not lost the connection */
                        if(substr($con['buffer']['all'], 0, 6) == 'PING :') {
                                /* PONG : is followed by the line that the server
                                sent us when PINGing */
                                cmd_send('PONG :'.substr($con['buffer']['all'], 6));
                                /* If this is the first time we have reached this point,
                                then JOIN the channel */
                                if ($firstTime == true){
                                        cmd_send("JOIN ". $CONFIG['channel']);
                                        /* The next time we get here, it will NOT be the firstTime */
                                        $firstTime = false;
                                }
                                /* Make sure that we have a NEW line of chats to analyse. If we don't,
                                there is no need to parse the data again */
                        } elseif ($old_buffer != $con['buffer']['all']) {
                                /* Determine the patterns to be passed
                                to parse_buffer(). buffer is in the form:
                                :username!~identd@hostname JOIN :#php
                                :username!~identd@hostname PRIVMSG #PHP :action text
                                :username!~identd@hostname command channel :text */

                                /*
                                Right now this bot does nothing. But this is where you would
                                add some conditions, or see what is being said in the chat, and then
                                respond. Before you try doing that you should become familiar with
                                how commands are send over IRC. Just read the console when you run this
                                script, and then you will see the patterns in chats, i.e. where the username
                                occurs, where the hostmask is, etc. All you need is functions such as
                                preg_replace_callback(), or perhaps your own function that checks for patterns
                                in the text.

                                Good Luck.
                                */

                        }
                        $old_buffer = $con['buffer']['all'];
                }
        }
}

/* Accepts the command as an argument, sends the command
to the server, and then displays the command in the console
for debugging */
function cmd_send($command)
{
        global $con, $time, $CONFIG;
        /* Send the command. Think of it as writing to a file. */
        fputs($con['socket'], $command."\n\r");
        /* Display the command locally, for the sole purpose
        of checking output. (line is not actually not needed) */
        print (date("[d/m @ H:i]") ."-> ". $command. "\n\r");

}
?>

[edit] complete_bot.php


<?php
/*
demonbot - a demonstation for codedemons.net
*/

/* Variables that determine server, channel, etc */
$CONFIG = array();
$CONFIG['server'] = 'irc.gamesurge.net'; // server (i.e. irc.gamesnet.net)
$CONFIG['nick'] = 'demonbot'; // nick (i.e. demonbot
$CONFIG['port'] = 6667; // port (standard: 6667)
$CONFIG['channel'] = '#bot_test'; // channel  (i.e. #php)
$CONFIG['name'] = 'demonbot'; // bot name (i.e. demonbot)
$CONFIG['admin_pass'] = 'asus';

/* Let it run forever (no timeouts) */
set_time_limit(0);

/* The connection */
$con = array();

/* start the bot... */
init();

function init()
{
        global $con, $CONFIG;
        /* We need this to see if we need to JOIN (the channel) during
        the first iteration of the main loop */
        $firstTime = true;

        /* Connect to the irc server */
        $con['socket'] = fsockopen($CONFIG['server'], $CONFIG['port']);

        /* Check that we have connected */
        if (!$con['socket']) {
                print ("Could not connect to: ". $CONFIG['server'] ." on port ". $CONFIG['port']);
        } else {
                /* Send the username and nick */
                cmd_send("USER ". $CONFIG['nick'] ." codedemons.net codedemons.net :". $CONFIG['name']);
                cmd_send("NICK ". $CONFIG['nick'] ." codedemons.net");

                /* Here is the loop. Read the incoming data (from the socket connection) */
                while (!feof($con['socket']))
                {
                        /* Think of $con['buffer']['all'] as a line of chat messages.
                        We are getting a 'line' and getting rid of whitespace around it. */
                        $con['buffer']['all'] = trim(fgets($con['socket'], 4096));

                        /* Pring the line/buffer to the console
                        I used <- to identify incoming data, -> for outgoing. This is so that
                        you can identify messages that appear in the console. */
                        print date("[d/m @ H:i]")."<- ".$con['buffer']['all'] ."\n";

                        /* If the server is PINGing, then PONG. This is to tell the server that
                        we are still here, and have not lost the connection */
                        if(substr($con['buffer']['all'], 0, 6) == 'PING :') {
                                /* PONG : is followed by the line that the server
                                sent us when PINGing */
                                cmd_send('PONG :'.substr($con['buffer']['all'], 6));
                                /* If this is the first time we have reached this point,
                                then JOIN the channel */
                                if ($firstTime == true){
                                        cmd_send("JOIN ". $CONFIG['channel']);
                                        /* The next time we get here, it will NOT be the firstTime */
                                        $firstTime = false;
                                }
                                /* Make sure that we have a NEW line of chats to analyse. If we don't,
                                there is no need to parse the data again */
                        } elseif ($old_buffer != $con['buffer']['all']) {
                                /* Determine the patterns to be passed
                                to parse_buffer(). buffer is in the form:
                                :username!~identd@hostname JOIN :#php
                                :username!~identd@hostname PRIVMSG #PHP :action text
                                :username!~identd@hostname command channel :text */

                                /*
                                Right now this bot does nothing. But this is where you would
                                add some conditions, or see what is being said in the chat, and then
                                respond. Before you try doing that you should become familiar with
                                how commands are send over IRC. Just read the console when you run this
                                script, and then you will see the patterns in chats, i.e. where the username
                                occurs, where the hostmask is, etc. All you need is functions such as
                                preg_replace_callback(), or perhaps your own function that checks for patterns
                                in the text.

                                Good Luck.
                                */
                                // log the buffer to "log.txt" (file must have
                                // already been created).
                                // log_to_file($con['buffer']['all']);

                                // make sense of the buffer
                                parse_buffer();

                                // now process any commands issued to the bot
                                process_commands();

                        }
                        $old_buffer = $con['buffer']['all'];
                }
        }
}

/* Accepts the command as an argument, sends the command
to the server, and then displays the command in the console
for debugging */
function cmd_send($command)
{
        global $con, $time, $CONFIG;
        /* Send the command. Think of it as writing to a file. */
        fputs($con['socket'], $command."\n\r");
        /* Display the command locally, for the sole purpose
        of checking output. (line is not actually not needed) */
        print (date("[d/m @ H:i]") ."-> ". $command. "\n\r");

}

function log_to_file ($data)
{
        $filename = "log.txt";
        $data .= "\n";
        // open the log file
        if ($fp = fopen($filename, "ab"))
        {
                // now write to the file
                if ((fwrite($fp, $data) === FALSE))
                {
                        echo "Could not write to file.<br />";
                }
        }
        else
        {
                echo "File could not be opened.<br />";
        }
}

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

        /* TIME */
        if(strtoupper($con['buffer']['text']) == '.TIME') {
                cmd_send(prep_text("Time", date("F j, Y, g:i a", time())));
        }

        /* NICK */
        if (substr(strtoupper($con['buffer']['text']), 0, 5) == ".NICK"){
                $args = explode(" ", $con['buffer']['text']);

                if (count($args) < 3)
                cmd_send(prep_text("Nick", "Syntax: .nick admin_pass new_nick"));
                else
                {
                        if ($args[1] == $CONFIG['admin_pass'])
                        cmd_send("NICK ". $args[2]);
                        else
                        cmd_send(prep_text("Nick", "Invalid password"));
                }
        }

        /* Noob */
        if(strtoupper(substr($con['buffer']['text'], 0, 5)) == '.NOOB') {
                $args = explode(" ", $con['buffer']['text'], 2);
                $name = (!empty($args[1]))?$args[1]:"beginner";
                cmd_send(prep_text("Beginner Help", "Welcome, ".$name.", to PHP! Some tutorials: www.codedemons.net, www.zend.com, www.phpbuilder.com, www.php.net"));
        }

        /* No PMs */
        if(strtoupper(substr($con['buffer']['text'], 0, 5)) == '.PM') {
                cmd_send(prep_text("please"," Please do not send PMs to ops/peons unless you have asked first."));
        }
}

function parse_buffer()
{

        /*
        :username!~identd@hostname JOIN :#php
        :username!~identd@hostname PRIVMSG #PHP :action text
        :username!~identd@hostname command channel :text
        */

        global $con, $CONFIG;

        $buffer = $con['buffer']['all'];
        $buffer = explode(" ", $buffer, 4);

        /* Get username */
        $buffer['username'] = substr($buffer[0], 1, strpos($buffer['0'], "!")-1);

        /* Get identd */
        $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);

        /* The user and the host, the whole shabang */
        $buffer['user_host'] = substr($buffer[0],1);

        /* Isolate the command the user is sending from
        the "general" text that is sent to the channel
        This is  privmsg to the channel we are talking about.

        We also format $buffer['text'] so that it can be logged nicely.
        */
        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:
                // it is probably a PRIVMSG
                $buffer['command'] = $buffer[1];
                $buffer['channel'] = $buffer[2];
                $buffer['text'] = substr($buffer[3], 1);
                break;
        }
        $con['buffer'] = $buffer;
}

function prep_text($type, $message)
{
        global $con;
        return ('PRIVMSG '. $con['buffer']['channel'] .' :['.$type.']'.$message);
}
?>
Personal tools