Location: PHPKode > projects > SteelBot > steelbot/include/classes/steelbot.class.php
<?php

/**
 * SteelBot class for SteelBot
 * 
 * http://steelbot.net
 * 
 * @author N3x^0r
 *
 */

class SteelBot extends SteelBotCore {

static public  $database,
               $msgdropped = false,
               $lng,
               $cmdlist = array(),
               
               $aliases = array(),
               
               $sender,
               $content,
               $alias,
               
               $plugins = array();                             

static private $current_plugin = null;

static function Init($cfg) {
    parent::$cfg = $cfg;
    parent::Init();        

    Proto::Init();    
    // загрузка плагинов
    self::LoadPlugins(parent::$cfg['plugin_dir']);
    try {
        foreach (self::$plugins as $name=>$plug) {
            self::CheckDependency($name);    
        } 
    } catch (BotException $e) {
        slog::add('steelbot', "Exception catched: ".$e->getMessage());
        parent::DoExit();
    }
     
    // i18n    
    self::InitLang();
    
}

static function InitLang($lang = null) {
    slog::add('steelbot', "Initializing i18n... ");
    if (!$lang) {
        $lang = parent::$cfg['language'];
    } elseif (strlen($lang) > 2) {
        $lang = substr($slng, 0,2);
    }
    
    self::$lng = new SteelBotLng( $lang );
    self::$lng->AddDict( STEELBOT_DIR.'/include/lang/'.$lang.'.php' );
    slog::result("[$lang] OK");
    
}

// plugin functions
static function LoadPlugins($dir) {
    $pattern = $dir.
               DIRECTORY_SEPARATOR."*.plugin.php"; 
    
    $pluglist = glob($pattern);
    foreach ($pluglist as $v) {
        
            try {
                self::LoadPluginByName($v);
            } catch (BotException $e) {
                slog::add('steelbot','Exception: '.$e->getMessage(), LOG_PLUGIN_LOAD);
            }
        
    } 
    
    foreach (glob($dir.DIRECTORY_SEPARATOR.'*', GLOB_ONLYDIR) as $d) {
        self::LoadPlugins($d);
    }
}

static function LoadPluginByName($name) {
    $name = str_replace('.plugin.php', '', basename($name) );
    if (is_dir(self::$cfg['plugin_dir'].DIRECTORY_SEPARATOR.$name)) {
        $filename = self::$cfg['plugin_dir'].DIRECTORY_SEPARATOR.$name.DIRECTORY_SEPARATOR.$name.'.plugin.php';
    } else {
        $filename = self::$cfg['plugin_dir'].DIRECTORY_SEPARATOR.$name.'.plugin.php';
    }
    if (array_key_exists($name, self::$plugins)) {
        throw new BotException(("Plugin $name already exists"));
    } else {
        slog::add('steelbot', "Loading plugin: $name ... ");
        $plug = new Plugin($filename);
        self::$current_plugin = $plug;
                          
        $plug->Load();
        self::CheckDependency($name);
        self::$plugins[$name] = $plug;
        slog::add('steelbot', "'$name' load OK", LOG_PLUGIN_LOAD);
        parent::EventRun( new Event(EVENT_PLUGIN_LOADED, array('name'=>$name)));                   
        self::$current_plugin = null;
        return true;        
    }
}

static function PluginLoaded($plugin) {
    return array_key_exists($plugin, self::$plugins);
}

static function Msg($text, $to = false) {
    if (!$to) {
        $to = self::$sender;        
    }    
    Proto::Msg($text, $to);    
    $ev = parent::EventRun( new Event(EVENT_MSG_SENT, array('text'=>$text, 'to'=>$to)) );    
    slog::add('steelbot', "[>$to ".$text, LOG_MSG_SENT);
}
    
static function GetSender() {
	return self::$sender;
}

static function GetMsgText() {
	return self::$content;
}  

static function GetAlias() {
    return self::$alias;
}     

/**
 * @desc Отправляет сообщение со справкой по указанной команде $cmd
 *
 * @param string $cmd - имя команды
 */
static function CmdHelp($cmd) {
    if (array_key_exists($cmd, self::$aliases)) {
        if ( self::$aliases[$cmd]->GetAccess() <= self::GetUserAccess() ) {
            $msg = str_replace('%c', $cmd, self::$aliases[$cmd]->GetHelp(BotCommand::HELP_FULL) );
            self::Msg( $msg );
        } else {
            self::Msg( LNG(LNG_CMDNOACCESS) );
        }
    } else {
		self::Msg( LNG( LNG_HELP_NOTFOUND, $cmd ) );
	}
}

/**
 * @desc Если не задан параметр, выводит список команд. Если параметр задан,
 * то отправляет помощь по указанной команде $val
 *
 * @param string $val параметр-команда
 */
static function help() {
    @list($command, $val) = explode(' ', self::$content, 2);
	if (empty($val)) {
	        $helpstr = array();
	        foreach (self::$aliases as $alias=>$cmd) {
                $cmdaccess = $cmd->GetAccess();

                // Показываем команду, только если она подходит пользователю по уровню доступа,
                // и не является администраторской (для администраторских команд свой хелпер)
                if ( ($cmdaccess <= SteelBot::GetUserAccess()) && ($cmdaccess < 100) ) {
                    $helpstr[] = str_replace('%c', $alias, $cmd->GetHelp(BotCommand::HELP_SHORT));
                }
	        }	
	        self::Msg( LNG(LNG_HELPCOMMANDS)."\n".implode('',$helpstr) );
	} else {
	   self::CmdHelp($val); 
	}
}

/**
 * @desc Регистрирует пользовательскую команду в системе.
 *
 * @param string $command - имя команды
 * @param string $func - функция, которая будет вызвана при получении этой команды
 * @param int $access - уровень доступа к команде
 * @param string $helpstr - текст, который будет отправляться при обращении
 * к помощи по данной команде
 * @param bool $create_alias - создать алиас с именем команды. Устанавливается в
 * false, если у команды должно быть другое название.
 *
 * @return BotCommand object
 *
 */
static function RegisterCmd($command, $func, $access = 1, $helpstr = null, $create_alias = true) {
    $tmp_plug = self::$current_plugin;
    if ( is_null(self::$current_plugin)) {
        $bt = array_shift( debug_backtrace() );
        $plugname = str_replace( '.plugin.php', '', basename($bt['file']));
        if ( self::PluginLoaded($plugname) ) {
            self::$current_plugin = self::$plugins[$plugname];
        }
    }
    
    if ($command instanceof BotCommand) {
       $obj = $command;
       
    } else {
       if (!parent::$cfg['msg_case_sensitive']) {
            $command = mb_strtolower($command, 'utf-8');
       }
	   if (!is_numeric($access)) {
	        $access = 1;
	   }	
	   $obj = new BotCommand($command, $func, $access, $helpstr, self::$current_plugin);
    }	
    
    self::AppendCmd($obj); 
    if ($create_alias) { 
        self::AddAlias(self::$current_plugin->GetName(), mb_strtolower($obj->GetName(), 'utf-8'), $obj->GetName() );
    }

    self::$current_plugin = $tmp_plug;
	return $obj;
}

static function AppendCmd($command) {
    $name = mb_strtolower( $command->GetName(), 'utf-8' );        

    if (self::$current_plugin == null) {
        self::$aliases[$command->GetName()] = $command;
        return true;

    } else {
        $plugin_name = self::$current_plugin->GetName();
        if (@self::$cmdlist[$name][$plugin_name] instanceof BotCommand) {
            
	    slog::add('steelbot', $command->GetName(). ' => '.func2str(self::$cmdlist[$command]->GetName()), LOG_CMD_ALREADY_REG );
            throw new BotException("$name already  exists in $plugin_name", ERR_CMD_ALREADY_DEFINED);
            
        } else {
            self::$cmdlist[$name][$plugin_name] = $command;         
            return self::$current_plugin->AddCommand($command);
        }
    }
}

static function AddDependence($dep, $version, $type='plugin') {
    if (self::$current_plugin == null) {
        trigger_error("SteelBot::AddDependence() out of plugin call", E_USER_WARNING);
        return false;
    } else {    
        return self::$current_plugin->AddDependence($dep, $version, $type);
    }
}

static function CheckDependency($plugin) {
    if (array_key_exists($plugin, self::$plugins)) {
        slog::add('steelbot', "Checking for dependencies $plugin... ", LOG_DEPENDENCY_CHECK);
        $dependencies = self::$plugins[$plugin]->GetDependencies();
        
        // plugins check
        foreach ($dependencies['plugin'] as $dep) {
            if ( array_key_exists($dep['dep'], self::$plugins) ) {
                $info = self::$plugins[$dep['dep']]->GetInfo();                    
                if ( !(CheckVersion( $dep['version'], $info['version']) === false) ) {
                         continue;
                }
            }
            throw new BotException("Plugin $plugin require {$dep['dep']} {$dep['version']} plugin", ERR_DEPENDENCY);            
        }
        
        // protocol check
        $proto_info = Proto::GetProtoInfo();
        foreach ($dependencies['proto'] as $dep) {
            if ($proto_info['name'] == $dep['dep']) {
                if ( CheckVersion($dep['version'], $proto_info['version']) === false ) {
                    throw new BotException("Plugin $plugin require protocol {$proto_info['name']} {$dep['version']} or higher", ERR_DEPENDENCY);
                } else {
                    break;
                }
            }
        }

        // database check
        $db_info = self::$database->GetDBInfo();
        foreach ($dependencies['database'] as $dep) {           
            if ($db_info['name'] == $dep['dep']) {

                if ( CheckVersion($dep['version'], $db_info['version']) === false ) {
                    throw new BotException("Plugin $plugin require database {$db_info['name']} {$dep['version']} or higher", ERR_DEPENDENCY);
                } else {                    
                    break;
                }
            }
        }

        // bot check
        if ( count($dependencies['bot']) && CheckVersion($dependencies['bot']['version'], self::GetVersion())===false ) {
            throw new BotException("Plugin $plugin require SteelBot {$dependencies['bot']['version']} or higher", ERR_DEPENDENCY);
        }
        slog::result("OK");
    }
}

static function FindAlias($plugin, $command) {
    if (is_object(self::$cmdlist[$command][$plugin])) {
        return self::$cmdlist[$command][$plugin]->GetAliases(true);
    } else {
        return false;
    }
}

static function AddAlias($plugin, $command, $alias) {
    if (self::CommandExists($plugin, $command)) {
        self::$cmdlist[$command][$plugin]->AddAlias($alias);
        self::$aliases[$alias] = self::$cmdlist[$command][$plugin];
        slog::add('steelbot', $command. ' => '.$plugin.'/'.$command, LOG_CMD_REGISTER);
        return true;
    } else {
        return false;
    }
}

static function ExportInfo($name, $version, $author) {
    if ( !is_null(self::$current_plugin) ) { 
        if ( func_num_args() == 4 ) {
            trigger_error("SteelBot::ExportInfo parameter list is deprecated. Please use 3 parameters instead 4 in ",
                E_USER_WARNING);
            $args = func_get_args();
            $info = array(
                'name' => $args[0],
                 'author' => $args[1].'.'.$args[2],
                    'version' => $args[3]
            );
        } else {
            $info = array(
                    'name' => $name,
                    'author' => $author,
                    'version' => $version
            );
        }
        self::$current_plugin->ExportInfo($info);
    }
}

/**
 * @desc Удаляет пользовательскую команду
 *
 * @param string $command - имя команды
 * @return bool - true, если команда удалена
 *                false, если команда не зарегистрирована
 * 
 * @todo Удалять все алиасы из бота. Создавать событие.
 */
static function UnregisterCmd($plugin, $command) {
    if (self::CommandExists($plugin, $command)) {
        unset(self::$cmdlist[$command][$plugin]);
        slog::add('steelbot', $command, LOG_CMD_UNREGISTER);
        return true;
    } else {
        return false;
    }
}

static function DropMsg() {
    self::$msgdropped = true;
}

/**
 * @desc Устанавливает уровень доступа к указанной пользовательской команде.
 *
 * @param unknown_type $cmd
 * @param unknown_type $level
 * @return bool - true, если уровень установлен
 *                false,если получен некорректный уровень доступа или
 *                команда не найдена 
 */
static function SetCmdAccess($plugin, $cmd,$level) {
	if (!is_numeric($level)) {
	    throw new BotException("$level is not a numeric value", ERR_NOT_NUMERIC);
	} elseif (self::CommandExists($plugin, $cmd)) {
		if (self::$cmdlist[$cmd][$plugin]->SetAccess( $level )) {
		    self::$database->SetCmdAccess($plugin, $cmd, $level);
		    $ev = new Event(EVENT_CMD_ACCESS_CHANGED, array(
		                                               'plugin' => $plugin,
		                                               'command'=>$cmd, 
		                                               'level'=>$level
		                                              )
		    );
		    parent::EventRun($ev);
		}
		return true;
	} else throw new BotException("Command does not exists", ERR_CMD_NOTFOUND);
}

static function SetOption($option, $value) {
    if (array_key_exists($option, parent::$cfg) ){
        parent::$cfg[$option] = $value;
        return true;
    } else {
        return false;
    }
}

static function CommandExists($plugin, $cmd) {
    return array_key_exists($cmd,self::$cmdlist) &&
           array_key_exists($plugin, self::$cmdlist[$cmd]);   
}

static function AliasExists($alias) {
    return array_key_exists($alias, self::$aliases);
}

/**
 * @desc Установливает пользователю уровень доступа к боту
 *
 * @param string $user - jid пользователя
 * @param int $level - уровень доступа от 1 до 100 
 * @return boolean
 */
static function SetUserAccess($user,$level) {
    if (!is_numeric($level) || $level > 100) {
        slog::add('steelbot', "Incorrect users access level: $level");     
        return false;
    } else {
        self::$database->SetUserAccess($user, $level);
        return true;
    }    
}

/**
 * @desc Возвращает уровень доступа, установленный для пользователя. Если 
 * пользователь не указан, то возвращает уровень доступа приславшего сообщение.
 *
 * @param  string $user
 * @return int
 */
static function GetUserAccess($user = false) {

    $user = $user?$user:self::GetSender();      
    
    if (Proto::IsAdmin($user)) {
        return 100;
    } elseif ( ($access = self::$database->GetUserAccess($user))) {
        return $access;
    } else {
        slog::add('steelbot', "Error getting access for $user");
        return 1;
    }
}

static function GetVersion() {
    return STEELBOT_VERSION;
}

/**
 * @desc Анализирует и исполняет присланную пользовательскую команду
 *
 * @return unknown
 */
static function Parse($event) {
    if (self::$msgdropped) return false;
    @list($command, $params) = explode(' ', $event->content, 2);
    if (!parent::$cfg['msg_case_sensitive']) {
        $command = mb_strtolower($command, 'utf-8');
    }
	if (!array_key_exists($command, self::$aliases)) {
        self::Msg(parent::$cfg['err_cmd']);
		return false;
		    
	} else {
	    try {
            self::$alias = $command;
	        self::$aliases[$command]->Execute( $params );
	        
	    } catch (BotException $e) {
	        slog::add('steelbot', $e->getMessage(), LOG_EXCEPTION);
	        switch ($e->getCode()) {
	            case ERR_CMD_ACCESS:
	                self::Msg( LNG(LNG_CMDNOACCESS) );
	                break;
	                
	            case ERR_FUNC:
	                break;
	        }
	    }
	}
    self::$sender = null;
    self::$content = null;
    self::$alias = null;
	return true;    
}

static function Connect() {
    if ($p = Proto::Connect() ) {
        slog::add('steelbot', "Connected", LOG_CONNECTED);
        parent::EventRun( new Event(EVENT_CONNECTED) );    
    } else {
        slog::add('steelbot', "Connection error", LOG_CONNECTION_ERROR);
    }
    
    return $p;
}

static function Disconnect() {
    Proto::Disconnect();
    slog::add('steelbot', "Disconnected", LOG_DISCONNECTED);
}

static function Connected() {
    return Proto::Connected();
}

static function ParseMessage() {
    self::$msgdropped = false;
    $message = Proto::GetMessage();
    
    switch ($message['type']) {
        case 'message':
            unset($message['type']);
            self::$sender = $message['sender'];
            self::$content = $message['content'];
            slog::add('steelbot', self::$content, LOG_MSG_RECIEVED, self::$sender);
            parent::EventRun(new Event(EVENT_MSG_RECIEVED, $message));
            break;
            
        case 'authrequest':
            unset($message['type']);
            parent::EventRun(new Event(EVENT_AUTH_REQUEST, $message));
            break;
            
        case 'userstatus':
            unset($message['type']);
            slog::add('steelbot', "Presence: {$message['sender']} [{$message['show']}] {$message['status']}");
            parent::EventRun(new Event(EVENT_USR_STATUS, $message));
            break;
            
        case 'error':
            slog::add('steelbot', "error from proto: ".Proto::Error());
            break;
         
            
        case false:
            break;
               
        default:
            if (isset($message['event'])) { //генерация специфичного для протокола события
                parent::EventRun(new Event(constant($message['event']), $message) );
                
            } else {
                slog::add('steelbot', "Unknown message from server: '".$message['type']."'");
                var_dump($message);
            }
            break;
            
                    
    }
    usleep((int)SteelBot::$cfg['delaylisten']*1000000);
}

static function Error() {
    return Proto::Error();
}

}
Return current item: SteelBot