I’m making a small PHP bot for myself, nothing too complicated as I’m still in the process of learning PHP but I was wondering what the best way is to build a dynamic plugin system for it.
Right now I have 3 classes:
- base.php - Will be the base and core functions for the bot
- handler.php - Handles the incoming messages
- IRC.php - Everything to do with the socket
Then of course a tests file: Bot.php which is just a file initializing my bot. I have included all the code for the above files at the bottom of this post, none of them are finished but merely just a basic mock-up. It does work and connect to the server though. I must also note that its based on https://github.com/pogosheep/IRC-Bot I basically just stripped out the stuff I didn't want so I could start from scratch with something basic and build around it for my learning.
The issue I’m having is figuring out how to structure a plugin system, I have the handler class will handle all the incoming messages from the IRC so I can use that to call the commands (plugins).
Ideally I wanted a way so that each plugin can register multiple commands for multiple functions within the same plugin template, so somehow be hooked into the incoming message stream and detect the commands associated with that plugin. Maybe I can do that the way its setup at the moment, I don’t know.
To help explain what I want I have two examples of different types of plugins that I want to work with the same Plugin template.
E.g a “Move” plugin – the move the bot between channels will register the commands
!join
!part
Each command calling a function
Or a “Nick_alert” plugin will do something every time the bots nick is said, so won’t necessarily register a command but reads the input stream and does something.
I don’t necessarily want code to make a Plugin system for it, just an explanation of how to structure it. Any help is appreciated thank you 
- Ben
IRC.php
PHP Code:
<?php
/**
* Creates a connection with the IRC server
*/
class IRC {
/**
* The server you want to connect to.
* @var string
*/
private $server = '';
/**
* The port of the server to connect to (Default 6667).
* @var integer
*/
private $port = 6667;
/**
* TCP/IP Connection.
* @var type
*/
private $socket;
/**
* Close the connection.
*/
public function __destruct() {
$this->disconnect();
}
/**
* Sets the server.
* @param string $server Server address to set.
*/
public function setServer( $server ) {
$this->server = (string) $server;
}
/**
* Sets the port.
* @param integer $port Port to set.
*/
public function setPort( $port ) {
$this->port = (int) $port;
}
/**
* Opens a connection.
*/
public function connect() {
// Create a new socket.
$this->socket = fsockopen( $this->server, $this->port );
// Check if we connected successfully.
if( !$this->isConnected()) {
// ERROR
#$this->error( 'Unable to connect to server: ' . $this->server . ' and port: ' . $this->port . '.' );
}
}
/**
* Disconnect from the server.
* @return boolean True if the connection was closed. FALSE otherwise.
*/
public function disconnect() {
return fclose( $this->socket );
}
/**
* Reconnects to the server
*/
public function reconnect() {
if( !$this->isConnected() ) {
$this->connect();
}
else {
$this->disconnect();
$this->connect();
}
}
/**
* Check if connection exists.
* @return boolean True if connection exists. FALSE otherwise.
*/
public function isConnected() {
return (is_resource( $this->socket ) ? true : false);
}
/**
* Interacts with the server.
* @returns int|boolean the number of bytes written, or FALSE on error.
*/
public function sendData( $data ) {
return fwrite( $this->socket, $data . "\r\n" );
}
public function sendRawData( $data ) {
return fwrite( $this->socket, $data );
}
/**
* Returns data from the server.
* @returns string|boolean The data as string, or FALSE if no data is available.
*/
public function getData() {
return fgets( $this->socket, 256 );
}
}
?>
base.php
PHP Code:
<?php
include 'handler.php';
include 'irc.php';
class Bot {
private $IRC = null;
private $channel = array( );
private $name, $nick, $password, $host;
private $maxReconnect = 0;
private $admins = array( );
public $logstream;
public function __construct() {
$this->IRC = new IRC();
$this->logstream = fopen('log.txt', 'a');
}
public function __destruct() {
$this->IRC->disconnect();
fclose( $this->logstream );
}
public function connect() {
// Disconnect if already connected.
if( $this->IRC->isConnected() ) {
$this->IRC->disconnect();
}
// Connect to the IRC server.
$this->IRC->connect();
// Specify the username, hostname and real name.
$this->IRC->sendData( 'USER ' . $this->nick . ' ' . $this->host . ' ' . $this->nick . ' :' . $this->name );
// Change IRC nickname.
$this->IRC->sendData( 'NICK ' . $this->nick );
// Initiate handler class
$handler = new handler( $this, $this->IRC );
}
public function disconnect() {
if( $this->IRC->isConnected() ) {
$this->IRC->disconnect();
}
}
public function log( $data ) {
fwrite( $this->logstream, $data . "\n" );
}
# Setter functions
public function setServer( $server ) {
$this->IRC->setServer( $server );
}
public function setPort( $port ) {
$this->IRC->setPort( $port );
}
public function setChannel( $channel ) {
$this->channel = (array) $channel;
}
public function setName( $name ) {
$this->name = (string) $name;
}
public function setNick( $nick ) {
$this->nick = (string) $nick;
}
public function setPassword( $password ) {
$this->password = (string) $password;
}
public function setHost( $host ) {
$this->host = (string) $host;
}
public function setMaxConnections( $maxReconnect ) {
$this->maxReconnect = (int) $maxReconnect;
}
public function getChannels() {
return $this->$channel;
}
}
?>
handler.php
PHP Code:
<?php
/**
* Handles messages/commands from the server
*/
class handler {
/**
* IRC Bot.
* @var type
*/
private $bot;
private $IRC;
public function __construct( $bot, $irc ) {
// Reference to the bot
$this->bot = $bot;
$this->IRC = $irc;
// Start reading the input
$this->main();
}
public function main() {
$counter = 0;
do {
// Get the data
$data = $this->IRC->getData();
// Join channels
$args = explode( ' ', $data );
// Play ping pong with server, to stay connected:
if ($args[0] == 'PING') {
$this->IRC->sendData( 'PONG ' . $args[1] );
}
// Nothing new from the server, step over.
if ($args[0] == 'PING' || !isset( $args[3] )) {
continue;
}
// Get IRC response
$args = explode( ' ', $data );
// Log input
$this->bot->log($data);
// Just so i can see in the command prompt
var_dump( $data );
} while (true);
}
}
?>
and the bot.php file
PHP Code:
<?php
set_time_limit( 0 );
ini_set( 'display_errors', 'on' );
// Include the essential files
require 'base.php';
// Create a new bot
$irc_bot= new Bot();
// Configure the bot
$irc_bot->setServer( 'irc.freenode.net' );
$irc_bot->setport( 6667 );
$irc_bot->setNick( 'Ben_Test' );
$irc_bot->setName( 'Ben_Test' );
$irc_bot->setHost( 'BensBot');
$irc_bot->setPassword( 'Password');
$irc_bot->setChannel( '#ben_bottest' );
$irc_bot->setMaxConnections( 1 );
// Load plugins - Want to be able to do this
#$irc_bot->load( 'plugins/admins.php' );
#$irc_bot->load( 'plugins/basic_commands.php' );;
// Establish connection
$irc_bot->connect();
?>