Source for file SmartIRC.php
Documentation is available at SmartIRC.php
* This is a PHP class for communication with IRC networks,
* which conforms to the RFC 2812 (IRC protocol).
* It's an API that handles all IRC protocol messages.
* This class is designed for creating IRC bots, chats and showing IRC related
* Documentation, a HOWTO, and examples are included in SmartIRC.
* Here you will find a service bot which I am also developing
* <http://cvs.meebey.net/atbs> and <http://cvs.meebey.net/phpbitch>
* Latest versions of Net_SmartIRC you will find on the project homepage
* or get it through PEAR since SmartIRC is an official PEAR package.
* Official Project Homepage: <http://pear.php.net/package/Net_SmartIRC/>
* Net_SmartIRC conforms to RFC 2812 (Internet Relay Chat: Client Protocol)
* Copyright (c) 2002-2005 Mirco Bauer <meebey@meebey.net> <http://www.meebey.net>
* Full LGPL License: <http://www.gnu.org/licenses/lgpl.txt>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ------- PHP code ----------
require_once 'Net/SmartIRC/defines.php';
require_once 'Net/SmartIRC/irccommands.php';
require_once 'Net/SmartIRC/messagehandler.php';
define('SMARTIRC_VERSION', '1.1.14');
define('SMARTIRC_VERSIONSTRING', 'Net_SmartIRC '.SMARTIRC_VERSION );
* @author Mirco 'meebey' Bauer <meebey@meebey.net>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @link http://pear.php.net/package/Net_SmartIRC
const IP_PATTERN = '/(?:(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})|(?:\[[0-9A-Fa-f:]+\])|(?:[a-zA-Z0-9-_.]+)):[0-9]{1,5}/';
protected $_state = SMARTIRC_STATE_DISCONNECTED;
SMARTIRC_HIGH => array (),
SMARTIRC_MEDIUM => array (),
* Stores all channels in this array where we are joined, works only if channelsyncing is activated.
* Eg. for accessing a user, use it like this: (in this example the SmartIRC object is stored in $irc)
* $irc->getUser('#test', 'meebey')->nick;
* @see setChannelSyncing()
* @see Net_SmartIRC_channel
* @see Net_SmartIRC_channeluser
* Stores all users that had/have contact with us (channel/query/notice etc.), works only if usersyncing is activated.
* Eg. for accessing a user, use it like this: (in this example the SmartIRC object is stored in $irc)
* $irc->user['meebey']->host;
* @see Net_SmartIRC_ircuser
* Stores the path to the modules that can be loaded.
* Stores all objects of the modules.
* All numeric IRC replycodes, the index is the numeric replycode.
* @see $SMARTIRC_nreplycodes
* Constructor. Initiates the messagebuffer and "links" the replycodes from
* global into properties. Also some PHP runtime settings are configured.
* @param array $params Properties to set during instantiation
// can't stop using the global without potentially breaking BC
$this->nreplycodes = &$GLOBALS['SMARTIRC_nreplycodes'];
if (isset ($_SERVER['REQUEST_METHOD'])) {
// the script is called from a browser, lets set default log destination
// to SMARTIRC_BROWSEROUT (makes browser friendly output)
// you'll want to pass an array that includes keys like:
// ModulePath, Debug, ChannelSyncing, AutoRetry, RunAsDaemon
// so we can call their setters here
foreach ($params as $varname => $val) {
$funcname = 'set' . $varname;
* Keeps BC since private properties were once publicly accessible.
* @param string $name The property name asked for
* @return mixed the property's value
public function __get($name)
// PHP allows $this->getChannel($param)->memberofobject,
// but we need to not break BC.
if ($name == 'channel' || $name == 'user'):
$name = '_' . $name . 's';
* Handle calls to renamed or deprecated functions
public function __call($method, $args)
'setChannelSynching' => 'setChannelSyncing',
'setDebug' => 'setDebugLevel',
'channel' => 'getChannel',
'_nicknameinuse' => '_event_err_nicknameinuse',
'setAutoReconnect' => '',
if (empty ($map[$method])) {
" WARNING: you are using $method() which is deprecated "
. "and no longer functional.",
" WARNING: you are using $method() which is a deprecated "
." method, using {$map[$method]}() instead!" , __FILE__ , __LINE__ );
" WARNING: $method() does not exist!" , __FILE__ , __LINE__ );
* Enables/disables autoretry for connecting to a server.
* @param boolean $boolean
* Sets the maximum number of attempts to connect to a server
* @param integer|null$autoretrymax
if ($autoretrymax == 0 ) {
* Enables/disables the benchmark engine.
* @param boolean $boolean
* Sets an IP address (and optionally, a port) to bind the socket to.
* Limits the bot to claiming only one of the machine's IPs as its home.
* Call with no parameters to unbind.
* @return string The bound address with port
* Enables/disables channel syncing.
* Channel syncing means, all users on all channel we are joined are tracked in the
* channel array. This makes it very handy for botcoding.
* @param boolean $boolean
'DEBUG_CHANNELSYNCING: Channel syncing enabled',
'DEBUG_CHANNELSYNCING: Channel syncing disabled',
* Sets the CTCP version reply string.
* @param string $versionstring
* Sets the level of debug messages.
* Sets the debug level (bitwise), useful for testing/developing your code.
* Here the list of all possible debug levels:
* SMARTIRC_DEBUG_CONNECTION
* SMARTIRC_DEBUG_IRCMESSAGES
* SMARTIRC_DEBUG_MESSAGETYPES
* SMARTIRC_DEBUG_ACTIONHANDLER
* SMARTIRC_DEBUG_TIMEHANDLER
* SMARTIRC_DEBUG_MESSAGEHANDLER
* SMARTIRC_DEBUG_CHANNELSYNCING
* SMARTIRC_DEBUG_USERSYNCING
* Default: SMARTIRC_DEBUG_NOTICE
* @see SMARTIRC_DEBUG_NOTICE
* Sets the delaytime before closing the socket when disconnect.
* @param integer|null$milliseconds
&& $milliseconds >= self ::DEF_DISCONNECT_TIME
* Sets the destination of all log messages.
* Sets the destination of log messages.
* SMARTIRC_FILE for saving the log into a file
* SMARTIRC_STDOUT for echoing the log to stdout
* SMARTIRC_SYSLOG for sending the log to the syslog
* Default: SMARTIRC_STDOUT
* @param integer $type must be on of the constants
'WARNING: unknown logdestination type ('. $type
. '), will use STDOUT instead', __FILE__ , __LINE__ );
* Sets the file for the log if the destination is set to file.
* Sets the logfile, if {@link setLogDestination logdestination} is set to SMARTIRC_FILE.
* This should be only used with full path!
* Sets the paths for the modules.
* Sets the delay for receiving data from the IRC server.
* Sets the delaytime between messages that are received, this reduces your CPU load.
* Don't set this too low (min 100ms).
* @param integer|null$milliseconds
&& $milliseconds >= self ::DEF_RECEIVE_DELAY
* Sets the delaytime before attempting reconnect.
* Value of 0 disables the delay entirely.
* @param integer|null$milliseconds
* Sets whether the script should be run as a daemon or not
* ( actually disables/enables ignore_user_abort() )
* @param boolean $boolean
* Sets the delay for sending data to the IRC server.
* Sets the delay time between sending messages, to avoid flooding
* IRC servers. If your bot has special flooding permissions on the
* network you're connected to, you can set this quite low to send
* @param integer|null$milliseconds
* Sets the receive timeout.
* If the timeout occurs, the connection will be reinitialized
* @param integer|null$seconds
* Sets the transmit timeout.
* If the timeout occurs, the connection will be reinitialized
* @param integer|null$seconds
* Enables/disables user syncing.
* User syncing means, all users we have or had contact with through channel, query or
* notice are tracked in the $irc->user array. This is very handy for botcoding.
* @param boolean $boolean
'DEBUG_USERSYNCING: User syncing enabled', __FILE__ , __LINE__ );
'DEBUG_USERSYNCING: User syncing disabled', __FILE__ , __LINE__ );
* Starts the benchmark (sets the counters).
* Stops the benchmark and displays the result.
* Shows the benchmark result.
* Adds an entry to the log.
* Adds an entry to the log with Linux style log format.
* Possible $level constants (can also be combined with "|"s)
* SMARTIRC_DEBUG_CONNECTION
* SMARTIRC_DEBUG_IRCMESSAGES
* SMARTIRC_DEBUG_MESSAGETYPES
* SMARTIRC_DEBUG_ACTIONHANDLER
* SMARTIRC_DEBUG_TIMEHANDLER
* SMARTIRC_DEBUG_MESSAGEHANDLER
* SMARTIRC_DEBUG_CHANNELSYNCING
* SMARTIRC_DEBUG_USERSYNCING
* @see SMARTIRC_DEBUG_NOTICE
* @param integer $level bit constants (SMARTIRC_DEBUG_*)
* @param string $entry the new log entry
* @param string|null$file The source file originating the log() call
* @param int|null$line The line of code that called log()
public function log($level, $entry, $file = null , $line = null )
'WARNING: invalid log level passed to log() ('. $level. ')',
if (substr($entry, -1 ) != "\n") {
if ($file !== null && $line !== null ) {
$entry = $file. '('. $line. ') '. $entry;
$entry = 'unknown(0) '. $entry;
$formattedentry = date('M d H:i:s '). $entry;
// we reconncted and don't want to destroy the old log entries
* Returns a reference to the channel object of the specified channelname.
* @param string $channelname
'WARNING: getChannel() is called and the required Channel '
. 'Syncing is not activated!', __FILE__ , __LINE__
'WARNING: getChannel() is called and the required channel '
. $channelname. ' has not been joined!', __FILE__ , __LINE__
* Returns a reference to the user object for the specified username and channelname.
* @param string $channelname
* @param string $username
public function &getUser($channelname, $username)
. ' the required Channel Syncing is not activated!',
if ($this->isJoined($channelname, $username)) {
* Creates the sockets and connects to the IRC server on the given port.
* Returns this SmartIRC object on success, and false on failure.
* @param bool $reconnecting For internal use only
* @return boolean|Net_SmartIRC
public function connect($addr, $port = 6667 , $reconnecting = false )
if ($hasPort = preg_match(self ::IP_PATTERN , $addr)) {
} elseif ($hasPort === 0 ) {
$timeout = ini_get("default_socket_timeout");
$timeout, STREAM_CLIENT_CONNECT , $context)
$error_msg = " couldn't connect to \"$addr\" reason: \"$errstr ($errno)\"";
return ($reconnecting) ? false : $this->reconnect();
* Disconnects from the IRC server nicely with a QUIT or just destroys the socket.
* Disconnects from the IRC server in the given quickness mode.
* - true, just close the socket
* - false, send QUIT and wait {@link $_disconnectime $_disconnectime} before
* @param boolean $quick default: false
* @return boolean|Net_SmartIRC
// let's clean our channel array
. 'cleaned channel array', __FILE__ , __LINE__
// let's clean our user array
. 'user array', __FILE__ , __LINE__
* Reconnects to the IRC server with the same login info,
* it also rejoins the channels
* @return boolean|Net_SmartIRC
// remember in which channels we are joined
if (empty ($value->key )) {
$channels[] = array ('name' => $value->name );
$channels[] = array ('name' => $value->name , 'key' => $value->key );
foreach ($channels as $value) {
if (isset ($value['key'])) {
$this->join($value['name'], $value['key']);
$this->join($value['name']);
* login and register nickname on the IRC network
* Registers the nickname and user information on the IRC network.
* @param string $realname
* @param integer $usermode
* @param string $username
* @param string $password
public function login($nick, $realname, $usermode = 0 , $username = null ,
if ($username !== null ) {
if ($password !== null ) {
$ipos = strpos($usermode, 'i');
$wpos = strpos($usermode, 'w');
. $usermode. ') is not valid, using 0 instead',
// if we have extra commands to send, do it now
// if we sent "ns auth" commands, we may need to resend our nick
* adds a command to the list of commands to be sent after login() info
* @param string $cmd the command to add to the perform list
* Adds a message to the messagequeue, with the optional priority.
* @param integer $priority must be one of the priority constants
* @return boolean|Net_SmartIRC
public function send($data, $priority = SMARTIRC_MEDIUM )
." with an invalid priority passed ($priority), message is "
. 'ignored!', __FILE__ , __LINE__
* checks if the bot is connected
* checks if the passed nickname is our own nickname
* @param string $nickname
public function isMe($nickname)
return ($nickname == $this->_nick);
* checks if we or the given user is joined to the specified channel and returns the result
* ChannelSyncing is required for this.
* @param string $nickname
public function isJoined($channel, $nickname = null )
. 'and the required Channel Syncing is not activated!',
if ($nickname !== null ) {
. ' on a user in a channel we are not joined to!',
if ($nickname === null ) {
* Checks if we or the given user is founder on the specified channel and returns the result.
* ChannelSyncing is required for this.
* @param string $nickname
public function isFounder($channel, $nickname = null )
. 'and the required Channel Syncing is not activated!',
if ($nickname === null ) {
$nickname = $this->_nick;
return ($this->isJoined($channel, $nickname)
&& $this->getUser($channel, $nickname)->founder
* Checks if we or the given user is admin on the specified channel and returns the result.
* ChannelSyncing is required for this.
* @param string $nickname
public function isAdmin($channel, $nickname = null )
. 'and the required Channel Syncing is not activated!',
if ($nickname === null ) {
$nickname = $this->_nick;
return ($this->isJoined($channel, $nickname)
&& $this->getUser($channel, $nickname)->admin
* Checks if we or the given user is opped on the specified channel and returns the result.
* ChannelSyncing is required for this.
* @param string $nickname
public function isOpped($channel, $nickname = null )
. 'and the required Channel Syncing is not activated!',
if ($nickname === null ) {
$nickname = $this->_nick;
return ($this->isJoined($channel, $nickname)
&& $this->getUser($channel, $nickname)->op
* Checks if we or the given user is hopped on the specified channel and returns the result.
* ChannelSyncing is required for this.
* @param string $nickname
public function isHopped($channel, $nickname = null )
. 'and the required Channel Syncing is not activated!',
if ($nickname === null ) {
$nickname = $this->_nick;
return ($this->isJoined($channel, $nickname)
&& $this->getUser($channel, $nickname)->hop
* Checks if we or the given user is voiced on the specified channel and returns the result.
* ChannelSyncing is required for this.
* @param string $nickname
public function isVoiced($channel, $nickname = null )
. 'and the required Channel Syncing is not activated!',
if ($nickname === null ) {
$nickname = $this->_nick;
return ($this->isJoined($channel, $nickname)
&& $this->getUser($channel, $nickname)->voice
* Checks if the hostmask is on the specified channel banned and returns the result.
* ChannelSyncing is required for this.
* @param string $hostmask
public function isBanned($channel, $hostmask)
. 'and the required Channel Syncing is not activated!',
* Provides a mechanism to interrupt a listen() loop by a bot or something
* @param bool $ival Whether to interrupt the next listen iteration
* Goes into receive and idle mode. Only call this if you want to "spawn" the bot.
* No further lines of PHP code will be processed after this call, only the bot methods!
* goes into receive mode _only_ for one pass
* Goes into receive mode. It will return when one pass is complete.
* Use this when you want to connect to multiple IRC servers.
* @return boolean|Net_SmartIRC
// if we're not connected, we can't listen, so return
// see if any timehandler needs to be called
// also let's send any queued messages
// don't send them too fast
} else if ($mediumcount) {
// calculate selecttimeout
// check the socket to see if data is waiting for us
// this will trigger a warning when a signal is received
// the socket got data to read
} while ($rawlen && $rawdata{$rawlen - 1 } != "\n");
} else if ($result === false ) {
// panic! panic! something went wrong! maybe received a signal.
. ' returned false, something went wrong!',
. 'receive timeout detected, doing reconnect...',
. 'transmit timeout detected, doing reconnect...',
// split up incoming lines, remove any empty ones and
// trim whitespace off the rest
foreach ($rawdataar as $rawline) {
." received: \"$rawline\"" , __FILE__ , __LINE__
// building our data packet
$ircdata = new Net_SmartIRC_data ();
$ircdata->rawmessage = $rawline;
$ircdata->rawmessageex = explode(' ', $rawline); // kept for BC
$prefix = $trailing = '';
if ($rawline{0 } == ':') {
$prefixEnd = strpos($rawline, ' ');
$prefix = substr($rawline, 1 , $prefixEnd - 1 );
// parse out the trailing
if ($trailingStart = strpos($rawline, ' :')) { // this is not ==
$trailing = substr($rawline, $trailingStart + 2 );
$trailingStart = strlen($rawline);
// parse out command and params
$trailingStart - $prefixEnd - 1
$ircdata->from = $prefix;
$ircdata->params = $params;
$ircdata->message = $trailing;
$ircdata->messageex = explode(' ', $trailing);
if (preg_match('/^(\S+)!(\S+)@(\S+)$/', $prefix, $matches)) {
$ircdata->nick = $matches[1 ];
$ircdata->ident = $matches[2 ];
$ircdata->host = $matches[3 ];
$ircdata->host = $prefix;
// figure out what SMARTIRC_TYPE this message is
case SMARTIRC_RPL_WELCOME:
case SMARTIRC_RPL_YOURHOST:
case SMARTIRC_RPL_CREATED:
case SMARTIRC_RPL_MYINFO:
case SMARTIRC_RPL_BOUNCE:
case SMARTIRC_RPL_LUSERCLIENT:
case SMARTIRC_RPL_LUSEROP:
case SMARTIRC_RPL_LUSERUNKNOWN:
case SMARTIRC_RPL_LUSERME:
case SMARTIRC_RPL_LUSERCHANNELS:
case SMARTIRC_RPL_MOTDSTART:
case SMARTIRC_RPL_ENDOFMOTD:
case SMARTIRC_RPL_NAMREPLY:
if ($params[0 ] == $this->_nick):
$ircdata->channel = $params[2 ];
$ircdata->channel = $params[1 ];
case SMARTIRC_RPL_ENDOFNAMES:
if ($params[0 ] == $this->_nick):
$ircdata->channel = $params[1 ];
$ircdata->channel = $params[0 ];
case SMARTIRC_RPL_WHOREPLY:
case SMARTIRC_RPL_ENDOFWHO:
if ($params[0 ] == $this->_nick):
$ircdata->channel = $params[1 ];
$ircdata->channel = $params[0 ];
case SMARTIRC_RPL_LISTSTART:
case SMARTIRC_RPL_LISTEND:
case SMARTIRC_RPL_BANLIST:
case SMARTIRC_RPL_ENDOFBANLIST:
$ircdata->channel = $params[0 ];
$ircdata->channel = $params[0 ];
case SMARTIRC_RPL_WHOISUSER:
case SMARTIRC_RPL_WHOISSERVER:
case SMARTIRC_RPL_WHOISOPERATOR:
case SMARTIRC_RPL_WHOISIDLE:
case SMARTIRC_RPL_ENDOFWHOIS:
case SMARTIRC_RPL_WHOISCHANNELS:
case SMARTIRC_RPL_WHOWASUSER:
case SMARTIRC_RPL_ENDOFWHOWAS:
case SMARTIRC_RPL_UMODEIS:
case SMARTIRC_RPL_CHANNELMODEIS:
$ircdata->channel = $params[0 ];
case SMARTIRC_ERR_NICKNAMEINUSE:
case SMARTIRC_ERR_NOTREGISTERED:
if (strspn($ircdata->params [0 ], '&#+!')) {
$ircdata->channel = $params[0 ];
if ($ircdata->message {0 } == chr(1 )) {
if (preg_match("/^\1ACTION .*\1\$/", $ircdata->message )) {
$ircdata->channel = $params[0 ];
if (preg_match("/^\1.*\1\$/", $ircdata->message )) {
if (preg_match("/^\1.*\1\$/", $ircdata->message )) {
$ircdata->channel = (!empty ($params[0 ])) ? $params[0 ] : $ircdata->message;
$ircdata->channel = $params[0 ];
$ircdata->channel = $params[0 ];
$ircdata->channel = $params[0 ];
$ircdata->channel = $params[0 ];
." command type UNKNOWN ($command)" ,
. 'ircdata nick:"'. $ircdata->nick
. '" ident:"'. $ircdata->ident
. '" host:"'. $ircdata->host
. '" type:"'. $ircdata->type
. '" from:"'. $ircdata->from
. '" channel:"'. $ircdata->channel
. '" message:"'. $ircdata->message. '"', __FILE__ , __LINE__
// lets see if we have a messagehandler for it
'DEBUG_MESSAGEHANDLER: cannot translate unrecognized'
." messagecode $command into a command type" ,
$methodname = 'event_' . $command;
$_methodname = '_'. $methodname;
$_codetype = 'by numeric';
$_methodname = '_'. $methodname;
$_codetype = 'by string';
// if exists call internal method for the handling
. 'calling internal method "'. get_class($this). '->'
. $_methodname. '" ('. $_codetype. ')', __FILE__ , __LINE__
$this->$_methodname($ircdata);
// if exists call user defined method for the handling
. 'calling user defined method "'. get_class($this). '->'
. $methodname. '" ('. $_codetype. ')', __FILE__ , __LINE__
$this->$methodname($ircdata);
. ' method found for "'. $command. '" ('. $methodname. ')',
// now the actionhandlers are coming
$hmsg = $handlerinfo['message'];
$regex = ($hmsg{0 } == $hmsg{strlen($hmsg) - 1 })
if (($handlerinfo['type'] & $ircdata->type )
." actionhandler match found for id: $i type: "
. $ircdata->type. ' message: "'. $ircdata->message
." \" regex: \"$regex\"" , __FILE__ , __LINE__
$callback = $handlerinfo['callback'];
: '(anonymous function)';
'DEBUG_ACTIONHANDLER: calling "'. $cbstring. '"',
'DEBUG_ACTIONHANDLER: callback is invalid! "'. $cbstring. '"',
// if we've done anything that didn't work and the connection is broken,
. ' error detected, attempting reconnect!', __FILE__ , __LINE__
* waits for a special message type and returns the answer
* Creates a special actionhandler for that given TYPE and returns the answer.
* This will only receive the requested type, immediately quit and disconnect from the IRC server.
* Made for showing IRC statistics on your homepage, or other IRC related information.
* @param integer $messagetype see in the documentation 'Message Types'
* @param string $regex the pattern to match on
* @return array answer from the IRC server for this $messagetype
public function listenFor($messagetype, $regex = '.*')
$listenfor = new Net_SmartIRC_listenfor ();
return $listenfor->result;
* registers a new actionhandler and returns the assigned id
* Registers an actionhandler in Net_SmartIRC for calling it later.
* The actionhandler id is needed for unregistering the actionhandler.
* @param integer $handlertype bits constants, see in this documentation Message Types
* @param string $regexhandler the message that has to be in the IRC message in regex syntax
* @param object|callable$object either an object with the method, or a callable
* @param string $methodname the methodname that will be called when the handler happens
* @return integer assigned actionhandler id
. 'type to registerActionHandler()', __FILE__ , __LINE__
if (!empty ($methodname)) {
$object = array ($object, $methodname);
'message' => $regexhandler,
. 'actionhandler('. $id. ') registered', __FILE__ , __LINE__
* unregisters an existing actionhandler
* @param integer $handlertype
* @param string $regexhandler
* @param string $methodname
$object, $methodname = ''
. 'type to unregisterActionHandler()', __FILE__ , __LINE__
if (!empty ($methodname)) {
$object = array ($object, $methodname);
if ($handlerinfo['type'] == $handlertype
&& $handlerinfo['message'] == $regexhandler
&& $handlerinfo['callback'] == $object
$id = $handlerinfo['id'];
. 'actionhandler('. $id. ') unregistered', __FILE__ , __LINE__
. 'not find actionhandler type: "'. $handlertype. '" message: "'
. $regexhandler. '" matching callback. Nothing unregistered', __FILE__ , __LINE__
* unregisters an existing actionhandler via the id
* @param integer|array$id
if ($handlerinfo['id'] == $id) {
. 'actionhandler('. $id. ') unregistered', __FILE__ , __LINE__
. 'not find actionhandler id: '. $id. ' _not_ unregistered',
* registers a timehandler and returns the assigned id
* Registers a timehandler in Net_SmartIRC, which will be called in the specified interval.
* The timehandler id is needed for unregistering the timehandler.
* @param integer $interval interval time in milliseconds
* @param object|callable$object either an object with the method, or a callable
* @param string $methodname the methodname that will be called when the handler happens
* @return integer assigned timehandler id
if (!empty ($methodname)) {
$object = array ($object, $methodname);
. $id. ') registered', __FILE__ , __LINE__
* unregisters an existing timehandler via the id
if ($handlerinfo['id'] == $id) {
. 'timehandler('. $id. ') unregistered', __FILE__ , __LINE__
$timerarray[] = $values->interval;
." find timehandler id: $id _not_ unregistered" ,
* loads a module using preset path and given name
* @return boolean|Net_SmartIRC
// is the module already loaded?
. $name. '" already loaded!', __FILE__ , __LINE__
$classname = " Net_SmartIRC_module_$name";
. ' exists, initializing...', __FILE__ , __LINE__
." module; file \"$filename\" doesn't exist" , __FILE__ , __LINE__
// pray that there is no parse error, it will kill us!
." not found in $filename, aborting..." , __FILE__ , __LINE__
." \"$name\" from file..." , __FILE__ , __LINE__
if (!(isset ($methods['__construct']) || isset ($methods['module_init']))) {
. $classname. '::__construct() not found, aborting...',
if (!(isset ($methods['__destruct']) || isset ($methods['module_exit']))) {
. $classname. '::__destruct() not found, aborting...',
$required = array ('name', 'description', 'author', 'license');
foreach ($required as $varname) {
if (!isset ($vars[$varname])) {
." property {$classname}::\${$varname} not found." ,
// looks like the module satisfies us, so instantiate it
if (isset ($methods['module_init'])) {
// we're using an old module_init style module
$this->_modules[$name] = new $classname;
. $classname. '::module_init()', __FILE__ , __LINE__
$this->_modules[$name]->module_init ($this);
// we're using a new __construct style module, which maintains its
// own reference to the $irc client object it's being used on
$this->_modules[$name] = new $classname($this);
// we're using new style AND we have args to pass to the constructor
// only one arg, so pass it as is
// multiple args, so pass them in an array
." module: $name" , __FILE__ , __LINE__
* unloads a module by the name originally loaded with
* @return boolean|Net_SmartIRC
." $name..." , __FILE__ , __LINE__
$this->_modules[$name]->module_exit ($this);
." unloaded module: $name" , __FILE__ , __LINE__ );
." module: $name (it's not loaded!)" , __FILE__ , __LINE__
* Returns an array of the module names that are currently loaded
* adds an user to the channelobject or updates his info
protected function _adduser(&$channel, &$newuser)
if ($this->isJoined($channel->name , $newuser->nick )) {
. 'updating user: '. $newuser->nick. ' on channel: '
. $channel->name , __FILE__ , __LINE__
// lets update the existing user
$currentuser = &$channel->users [$lowerednick];
$props = array ('ident', 'host', 'realname', 'ircop', 'founder',
'admin', 'op', 'hop', 'voice', 'away', 'server', 'hopcount'
foreach ($props as $prop) {
if ($newuser->$prop !== null ) {
$currentuser->$prop = $newuser->$prop;
. 'adding user: '. $newuser->nick. ' to channel: '. $channel->name ,
$channel->users [$lowerednick] = $newuser;
$user = &$channel->users [$lowerednick];
$modes = array ('founder', 'admin', 'op', 'hop', 'voice');
foreach ($modes as $mode) {
" DEBUG_CHANNELSYNCING: adding $mode: ". $user->nick
. ' to channel: '. $channel->name , __FILE__ , __LINE__
$channel->{$ms}[$user->nick ] = true;
* looks for any time handlers that have timed out and calls them if valid
if ($microtimestamp >= $handlerinfo['lastmicrotimestamp']
+ ($handlerinfo['interval'] / 1000.0 )
$callback = $handlerinfo['callback'];
$handlerinfo['lastmicrotimestamp'] = $microtimestamp;
: '(anonymous function)';
'DEBUG_TIMEHANDLER: callback is invalid! "'. $cbstring. '"',
* An active-pinging system to keep the bot from dropping the connection
* sends a raw message to the IRC server
* Don't use this directly! Use message() or send() instead.
. $data. '"', __FILE__ , __LINE__
// writing to the socket failed, means the connection is broken
* removes an user from one channel or all if he quits
$nick = $ircdata->params [1 ];
. 'unknown TYPE ('. $ircdata->type
. ') in _removeuser(), trying default', __FILE__ , __LINE__
if ($this->_nick == $nick) {
'DEBUG_CHANNELSYNCING: we left channel: '. $ircdata->channel
. ' destroying...', __FILE__ , __LINE__
$lists = array ('founders', 'admins', 'ops', 'hops', 'voices');
'DEBUG_CHANNELSYNCING: user '. $nick
. ' quit, removing him from all channels', __FILE__ , __LINE__
// remove the user from all channels
foreach ($channelkeys as $channelkey) {
// loop through all channels
foreach ($channel->users as $uservalue) {
// loop through all user in this channel
if ($nick == $uservalue->nick ) {
'DEBUG_CHANNELSYNCING: found him on channel: '
. $channel->name. ' destroying...',
unset ($channel->users [$lowerednick]);
foreach ($lists as $list) {
if (isset ($channel->{$list}[$nick])) {
'DEBUG_CHANNELSYNCING: removing him '
." from $list list" , __FILE__ , __LINE__
unset ($channel->{$list}[$nick]);
'DEBUG_CHANNELSYNCING: removing user: '. $nick
. ' from channel: '. $ircdata->channel , __FILE__ , __LINE__
unset ($channel->users [$lowerednick]);
foreach ($lists as $list) {
if (isset ($channel->{$list}[$nick])) {
'DEBUG_CHANNELSYNCING: removing him '
." from $list list" , __FILE__ , __LINE__
unset ($channel->{$list}[$nick]);
* updates and returns the current connection state
&& (strtolower($rtype) == 'socket' || $rtype == 'stream')
public function isError($object) // is this even needed/used?
return new Net_SmartIRC_Error ($message);
* Struct for parsed incoming messages
public $params = array ();
public $messageex = array ();
public $rawmessageex = array ();
* Struct for individual channel data
class Net_SmartIRC_channel
public $founders = array ();
public $admins = array ();
public $voices = array ();
public $user_limit = false;
public $synctime_start = 0;
public $synctime_stop = 0;
* Struct for individual user data
* Struct for extra data that applies to each user in each channel they're in
class Net_SmartIRC_channeluser extends Net_SmartIRC_user
* Struct for data that applies to each user server-wide
class Net_SmartIRC_ircuser extends Net_SmartIRC_user
public $joinedchannels = array ();
* Built-in bot used by Net_SmartIRC::listenFor()
class Net_SmartIRC_listenfor
public $result = array ();
* stores the received answer into the result array
public function handler (&$irc, &$ircdata)
'DEBUG_ACTIONHANDLER: listenfor handler called', __FILE__ , __LINE__
$this->result[] = $ircdata;
public function __construct ($message)
$this->error_msg = $message;
public function getMessage ()
Documentation generated on Thu, 25 Jul 2019 12:49:09 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|