<?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();
}
}