Right a few assumptions are being made: you have a text editor, at least a basic knowledge of object orientated PHP, access to an IRC client, a web server with PHP 5.3.0 preferably, if not a work around is needed later in the tutorial.
So now we have all of that out of the way lets get down to business. First thing we need to do is set a couple of PHP settings dynamically with these two lines of code:
<?php
set_time_limit(0);
ini_set('display_errors', 'on');
set_time_limit is a PHP directive that says how long PHP should try to complete the script before it times out (in seconds), by setting it to 0 we are basically telling PHP never to time out on the script.
The other line is just telling PHP to let us know about any warnings or errors that the script encounters, helps for when we are testing new features.
Next we need to set up a couple of config values so that the bot can connect to the right IRC server properly...
$config = array( 'server' => 'example.com', 'port' => 6667, 'nick' => 'nicknick', 'name' => 'IhaveNoName', 'pass' => 'meh', );
I set it up in an array to make it easier to access, within that example you need to change the values. The server value should be set to the IRCd's address like irc.cyberarmy.net for example. The default IRC port is 6667 so you won't change that unless you need to. The nick value is your nickname (screen name) as seen by the other users. The name value stores the user's “real name” and the pass is for registering with NickServ.
Now the enviroment has been set up and we can start working on the bulk of the code, the main class. I decided to create its own class for the simple reason, I like OO programming and it is a lot neater.
First thing we do is declare to PHP that we are using a class and then we will define the two objects that we will use throughout the rest of the script.
class IRCBot {
//This is going to hold our TCP/IP connection
var $socket;
//This is going to hold all of the messages both server and client
var $ex = array();
In OO PHP coding, to declare and object of a class you use the keyword var followed by the variables same (yes still with the $).
Next piece of code is going to be the construct, in PHP5 onwards the construct is a function that automatically gets called whenever a class is called, and its opposite is the destruct which isn't covered in this tutorial.
/*
Construct item, opens the server connection, logs the bot in
@param array
*/
function __construct($config)
{
$this->socket = fsockopen($config['server'], $config['port']);
$this->login($config);
$this->main();
$this->send_data('JOIN', '#chat');
}
Lets break this down and step through the code.
function __construct($config)
Due to the face that construct is a key feature in PHP it is prefixed with __ (two underscores), you don't have to pass any parameters to this function but if you remember the config we did near the top of the file, well that is what we will be passing to the construct.
$this->socket = fsockopen($config['server'], $config['port']);
To access an object from within a class you need to use the keyword $this-> (if you want to learn more check the php.net documentation). What this line does is opens a socket (connection to the server) using the server and port parameters that we set in $config. There are a lot more parameters that you can pass to fsockopen but we don't need them so I won't go into them.
If you used the php script so far (making sure you close the class off) and called the class, you would have an active connection to the server and nothing else.
$this->login($config);
The next thing we need to do is tell the bot it needs to “login” to the IRCd, but this function will be discussed a little later.
$this->main();
This will execute the main function in our script which handles all of the server messages etc.
$this->send_data('JOIN', '#chat');
This calls our send_data function which will be discussed in a minute but what we are doing is telling the bot to issue the JOIN (join channel) command and join the #chat channel.
Right that is our construct function finished so the next bit that we are going to look at is the login function.
/*
Logs the bot in on the server
@param array
*/
function login($config)
{
$this->send_data('USER', $config['nick'].' acidavengers.co.uk '.$config['nick'].' :'.$config['name']);
$this->send_data('NICK', $config['nick']);
}
The sole purpose of this function is to just get the bot to login (register) with the IRC server. To do this it needs to do two things. First off we need to tell the server who we are, so we use the send_data function to send the USER command, the information we need to send looks like this (nick host nick:realname). Once you have told the server that the bot is a user you need to send the bot's nickname so it ban be interacted with.
The next thing we need to do is create the function main(). As the name suggests this function is going to be the most used function. To make it work the way we need to we will need to code in an infinite loop. Yes, I know that coding 101 tells you never to create an infinite loop, but we will be doing so under controlled circumstances.
/*
This is the workhorse function, grabs the data from the server and displays on the browser
*/
function main()
{
$data = fgets($this->socket, 128);
echo nl2br($data);
flush();
$this->ex = explode(' ', $data);
Lets look at this extract, first thing we do is we store the first 128 characters (or until it finds a newline character \n) from the socket and then store it in $data. The next thing the bot will do is output that data to the browser but converting all of the newline characters to HTML newlines (<br>). Then we flush the output buffer and explode (split) the $data variable's contents into the $ex object. The reason why we do this is so we can access it later on.
To be able to keep an active connection on IRC the server, the server periodically sends a command (PING) plus a code which IRC clients reply to with the PONG command and the exact same code. Considering our bot isn't using an IRC client we need to wait for the PING command and reply to it ourselves.
All commands sent by the server will always be stored in $this->ex[0] because it is the first word to be sent. So what we do is a simple if statement to see if $this->ex[0] matches PING, if it does, we then need to use our send_data function to reply to that with PONG and the code that the server sent (stored in $this->ex[1]). The following code does just that.
if($this->ex[0] == 'PING')
{
$this->send_data('PONG', $this->ex[1]); //Plays ping-pong with the server to stay connected.
}
Next thing our bot needs to do is to is to keep an eye out for any commands that has been sent by a user and then process it.
$command = str_replace(array(chr(10), chr(13)), '', $this->ex[3]);
switch($command) //List of commands the bot responds to from a user.
{
case ':!join':
$this->join_channel($this->ex[4]);
break;
case ':!quit':
$this->send_data('QUIT', 'acidavengers.co.uk made Bot');
break;
case ':!op':
$this->op_user();
break;
case ':!deop':
$this->op_user('','', false);
break;
case ':!voice':
$this->voice_user();
break;
case ':!devoice':
$this->voice_user('','',false);
break;
case ':!protect':
$this->protect_user();
break;
}
From this snippit you can see that we have used a switch statement to work out that to do with the command that is sent to the bot, you might wonder why they begin with : (colon) this is because of the way in which information is sent to the socket. All that is left is to loop back on itself by calling the main function again.
$this->main(); }
That is all that should be needed to talk about for this tutorial so here is the full code listing.
<?php
//So the bot doesnt stop.
set_time_limit(0);
ini_set('display_errors', 'on');
//Example connection stuff.
$config = array(
'server' => 'example.com',
'port' => 6667,
'nick' => 'nicknick',
'name' => 'IhaveNoName',
'pass' => 'meh',
);
class IRCBot {
//This is going to hold our TCP/IP connection
var $socket;
//This is going to hold all of the messages both server and client
var $ex = array();
/*
Construct item, opens the server connection, logs the bot in
@param array
*/
function __construct($config)
{
$this->socket = fsockopen($config['server'], $config['port']);
$this->login($config);
$this->main();
$this->send_data('JOIN', '#chat');
}
/*
Logs the bot in on the server
@param array
*/
function login($config)
{
$this->send_data('USER', $config['nick'].' acidavengers.co.uk '.$config['nick'].' :'.$config['name']);
$this->send_data('NICK', $config['nick']);
}
/*
This is the workhorse function, grabs the data from the server and displays on the browser
*/
function main()
{
$data = fgets($this->socket, 128);
echo nl2br($data);
flush();
$this->ex = explode(' ', $data);
if($this->ex[0] == 'PING')
{
$this->send_data('PONG', $this->ex[1]); //Plays ping-pong with the server to stay connected.
}
$command = str_replace(array(chr(10), chr(13)), '', $this->ex[3]);
switch($command) //List of commands the bot responds to from a user.
{
case ':!join':
$this->join_channel($this->ex[4]);
break;
case ':!quit':
$this->send_data('QUIT', 'acidavengers.co.uk made Bot');
break;
case ':!op':
$this->op_user();
break;
case ':!deop':
$this->op_user('','', false);
break;
case ':!protect':
$this->protect_user();
break;
}
$this->main();
}
function send_data($cmd, $msg = null) //displays stuff to the broswer and sends data to the server.
{
if($msg == null)
{
fputs($this->socket, $cmd."\r\n");
echo '<strong>'.$cmd.'</strong><br />';
} else {
fputs($this->socket, $cmd.' '.$msg."\r\n");
echo '<strong>'.$cmd.' '.$msg.'</strong><br />';
}
}
function join_channel($channel) //Joins a channel, used in the join function.
{
if(is_array($channel))
{
foreach($channel as $chan)
{
$this->send_data('JOIN', $chan);
}
} else {
$this->send_data('JOIN', $channel);
}
}
function protect_user($user = '')
{
if($user == '')
{
if(php_version() >= '5.3.0')
{
$user = strstr($this->ex[0], '!', true);
} else {
$length = strstr($this->ex[0], '!');
$user = substr($this->ex[0], 0, $length);
}
}
}
$this->send_data('MODE', $this->ex[2] . ' +a ' . $user);
}
function op_user($channel = '', $user = '', $op = true)
{
if($channel == '' || $user == '')
{
if($channel == '')
{
$channel = $this->ex[2];
}
if($user == '')
{
if(php_version() >= '5.3.0')
{
$user = strstr($this->ex[0], '!', true);
} else {
$length = strstr($this->ex[0], '!');
$user = substr($this->ex[0], 0, $length);
}
}
}
if($op)
{
$this->send_data('MODE', $channel . ' +o ' . $user);
} else {
$this->send_data('MODE', $channel . ' -o ' . $user);
}
}
}
$bot = new IRCBot($config);
?>
Note: Make sure if you put this on a live server, you might want to watch out as it is a bit of a bandwidth also you need to keep the browser window open because it is a browser script, i havent gotten around to using CLI based PHP yet.
ToDo: Some implimentation for logging and auto join a channel.





MultiQuote






|