/** * Something unknown, weird, unexplored or otherwise not included has been * received by this bot, and this is a function in which we'll handle it. This * function will act as a connection-helper, if anything fails, we'll make * sure the bot can connect either way. * * @param Bot $pBot Bot which received this command. */ public function onUnhandledCommand(Bot $pBot) { switch ($pBot->In->Chunks[1]) { /** Sonium :Nickname is already in use. **/ case 433: switch ($pBot->In->Chunks[3]) { case $pBot['Nickname']: /** Try alternative nickname, if set up, else fall through. **/ if (isset($pBot['AltNickname'])) { $sNickname = $pBot['AltNickname']; break; } default: $sNickname = $pBot['Nickname'] . '_' . rand(1000, 9999); break; } $pBot->send('NICK ' . $sNickname); break; /** USER :Not enough parameters **/ /** USER :Not enough parameters **/ case 461: $sUsername = !empty($pBot['Username']) ? $pBot['Username'] : NUWANI_NAME; $sRealname = !empty($pBot['Realname']) ? $pBot['Realname'] : NUWANI_VERSION_STR; $pBot->send('USER ' . $sUsername . ' - - :' . $sRealname); break; /** Killed by the server for whatever reason. **/ /** Killed by the server for whatever reason. **/ case 'KILL': Timer::Create(function () use($pBot) { $pBot['Socket']->close(); $pBot->connect(); }, 1000, false); break; } }
/** * The function which tells this bot to connect to the IRC network. * Basically we just call the socket's connect function and we check if * the connection went well. If not, we'll try again after a timeout. If * we do somehow get connected, we send in our NICK and USER commands to * register with the IRC server. After that, the process () methods will * take over. * * @return boolean */ public function connect() { $this->m_aBotInfo['NextTry'] = 15 * pow(2, $this->m_aBotInfo['ConnectTry']); $this->m_aBotInfo['ConnectTry']++; if (!$this->m_pSocket->connect()) { if ($this->m_aBotInfo['ConnectTry'] >= 5) { echo '[Bot] Destroying bot ' . $this->m_sNickname . ' after 5 failed connection attempts.' . PHP_EOL; BotManager::getInstance()->destroy($this->m_pBot); return false; } echo '[Bot] Retrying in ' . $this->m_aBotInfo['NextTry'] . ' seconds...' . PHP_EOL; Timer::create(array($this, 'connect'), $this->m_aBotInfo['NextTry'] * 1000); return false; } $sUsername = isset($this->m_aBotInfo['Username']) && !empty($this->m_aBotInfo['Username']) ? $this->m_aBotInfo['Username'] : NUWANI_NAME; $sRealname = isset($this->m_aBotInfo['Realname']) && !empty($this->m_aBotInfo['Realname']) ? $this->m_aBotInfo['Realname'] : NUWANI_VERSION_STR; $this->m_pSocket->send('NICK ' . $this->m_sNickname); $this->m_pSocket->send('USER ' . $sUsername . ' - - :' . $sRealname); if (isset($this->m_aBotInfo['Network']['Options']['Password'])) { $this->m_pSocket->send('PASS ' . $this->m_aBotInfo['Network']['Options']['Password']); } return true; }
/** * After we have confirmed the identity of the one evaluating code on * this bot, we're ready to parse the evaluation string into the options. * * @param Bot $pBot Bot that should handle the evaluation. * @param string $sDestination Where should the output be redirected? * @param string $sEvaluation Line of code that should be executed. */ private function parseEvaluation(Bot $pBot, $sDestination, $sEvaluation) { $nFirstSpace = strpos($sEvaluation, ' '); if ($nFirstSpace === false) { return false; } $sEvaluationIdent = substr($sEvaluation, 0, $nFirstSpace); $sEvaluation = substr($sEvaluation, strlen($sEvaluationIdent) + 1); $aOptions = array('Type' => 'PHP', 'Buffering' => true, 'Operation' => $sEvaluation, 'Delay' => 0, 'MaxLines' => 4); if (strlen($sEvaluationIdent) != strlen($this->m_sPrefix)) { $sEvaluationIdent = str_replace($this->m_sPrefix, '', $sEvaluationIdent); if (strpos($sEvaluationIdent, '!') !== false) { $sEvaluationIdent = str_replace('!', '', $sEvaluationIdent); $aOptions['Type'] = 'EXEC'; } else { if (strpos($sEvaluationIdent, '@') !== false) { $sEvaluationIdent = str_replace('@', '', $sEvaluationIdent); $aOptions['Type'] = 'SQL'; $aOptions['MaxLines'] = 5; } } $aMatches = array(); preg_match_all('/(\\d+)(s|m|h)/', $sEvaluationIdent, $aMatches); foreach ($aMatches[0] as $iIndex => $sMatch) { $nThisDelay = $aMatches[1][$iIndex]; switch ($aMatches[2][$iIndex]) { case 'h': case 'H': $nThisDelay *= 60; // drop through // drop through case 'm': case 'M': $nThisDelay *= 60; break; } $sEvaluationIdent = str_replace($sMatch, '', $sEvaluationIdent); $aOptions['Delay'] += $nThisDelay; } if (strpos($sEvaluationIdent, 'out') !== false) { $sEvaluationIdent = str_replace('out', '', $sEvaluationIdent); $aOptions['Buffering'] = false; } if ($sEvaluationIdent != '') { /** Some weird f****d up prefix, ignore the line. **/ return false; } } if ($aOptions['Delay'] > 0) { Timer::create(function () use($pBot, $sDestination, $aOptions) { $pModules = ModuleManager::getInstance(); if (isset($pModules['Evaluation'])) { $pModules['Evaluation']->doEvaluation($pBot, $sDestination, $aOptions); } }, $aOptions['Delay'] * 1000, Timer::TIMEOUT); return true; } $this->doEvaluation($pBot, $sDestination, $aOptions); return true; }
public static function addMqdCommands(Commands $moduleManager) { $moduleManager->registerCommand(new \Command('mqd-on', function ($pBot, $sDestination, $sChannel, $sNickname, $aParams, $sMessage) { $id = Timer::create(function () use($pBot) { \LVP\InGame\QuoteDevice::sendRandomMessage($pBot); }, mt_rand(300, 420) * 1000, false); file_put_contents(\LVP\InGame\QuoteDevice::$m_sMqdFileName, $id); }, 'mqd')); $moduleManager->registerCommand(new \Command('mqd-off', function ($pBot, $sDestination, $sChannel, $sNickname, $aParams, $sMessage) { $bSuccess = Timer::destroy(file_get_contents(\LVP\InGame\QuoteDevice::$m_sMqdFileName)); if ($bSuccess === false) { echo 'Couldn\'t turn off'; return \Command::OUTPUT_ERROR; } else { echo 'Turned off.'; file_put_contents(\LVP\InGame\QuoteDevice::$m_sMqdFileName, ''); return \Command::OUTPUT_SUCCESS; } }, 'mqd')); }
/** * The constructor will prepare the module for immediate use. */ public function __construct() { if (!class_exists('LVP')) { // Third party require 'Sources/Vendor/geoipcity.php'; require 'Sources/Vendor/QuerySAMPServer.php'; // Our own stuff require 'LVP.php'; require 'LVPDatabase.php'; require 'LVPEchoHandlerClass.php'; require 'LVPEchoMessageParser.php'; require 'LVPConfiguration.php'; require 'LVPCommandHandler.php'; require 'LVPCrewHandler.php'; require 'LVPIpManager.php'; require 'LVPPlayerManager.php'; require 'LVPWelcomeMessage.php'; require 'LVPRadioHandler.php'; } if (!is_dir('Data/LVP')) { mkdir('Data/LVP', 0777); } $this->setNuwaniInfo(array('Nuwani', 'Nuweni', 'Nuwini', 'Nuwoni', 'Nuwuni', 'Nowani', 'Noweni', 'Nowini', 'Nowoni', 'Nowuni', 'Nawani', 'Nawoni'), array('sa-mp.nl', 'gtanet-37ag2t.sa-mp.nl', 'gtanet-hqt.8ca.192.82.IP')); $aLvpChannels = array('#LVP' => LVP::LEVEL_NONE, '#LVP.Beta' => LVP::LEVEL_NONE, '#LVP.Beta.echo' => LVP::LEVEL_NONE, '#LVP.crew' => LVP::LEVEL_ADMINISTRATOR, '#LVP.Dev' => LVP::LEVEL_DEVELOPER, '#LVP.echo' => LVP::LEVEL_NONE, '#LVP.Managers' => LVP::LEVEL_MANAGEMENT, '#LVP.Management' => LVP::LEVEL_MANAGEMENT, '#LVP.NL' => LVP::LEVEL_NONE, '#LVP.VIP' => LVP::LEVEL_VIP, '#Bot' => LVP::LEVEL_MANAGEMENT); foreach ($aLvpChannels as $sChannel => $nLevel) { $this->addLvpChannel($nLevel, $sChannel); } $aCrewColors = array(LVP::LEVEL_MANAGEMENT => '03', LVP::LEVEL_ADMINISTRATOR => '04', LVP::LEVEL_DEVELOPER => '12'); $this->m_nDatabaseTimerId = Timer::create(array(LVPDatabase::getInstance(), 'ping'), 30000, Timer::INTERVAL); $this->m_pCommandHandler = new LVPCommandHandler($this); $this->m_pConfiguration = new LVPConfiguration($this); $this->m_pCrewHandler = new LVPCrewHandler($this, $aCrewColors); $this->m_pMessageParser = new LVPEchoMessageParser($this); $this->m_pIpManager = new LVPIpManager($this); $this->m_pPlayerManager = new LVPPlayerManager($this); $this->m_pWelcomeMessage = new LVPWelcomeMessage($this); $this->m_pRadioHandler = new LVPRadioHandler($this); $this->registerCommands(); }