示例#1
0
文件: Bot.php 项目: xhoogland/Monique
 /**
  * This function will process all messages received directly from the
  * socket, in here we will handle various callbacks and functions.
  *
  * @param string $sMessage The raw message being received.
  * @return boolean
  */
 public function onReceive($sMessage)
 {
     // TODO Refactor this mess.
     $this->In->Chunks = explode(' ', $sMessage);
     $this->In->Raw = $sMessage;
     $sNetworkName = $this->m_aBotInfo['Network']['Name'];
     $this->In->User = new User($sNetworkName, substr($this->In->Chunks[0], 1));
     $this->In->PostColon = '';
     /** Extract message, if there is any. **/
     $nColonPosition = strpos($sMessage, ' :', 2);
     if ($nColonPosition !== false) {
         $this->In->PostColon = substr($sMessage, $nColonPosition + 2);
     }
     // Exception for "PING", which is not the second piece;
     if ($this->In->Chunks[0] == 'PING') {
         return $this->m_pSocket->send('PONG :' . $this->In->PostColon);
     }
     ErrorExceptionHandler::$Context = $this;
     $pModules = ModuleManager::getInstance();
     $bIsSlave = $this->m_aBotInfo['Slave'];
     switch (strtolower($this->In->Chunks[1])) {
         case '001':
             $this->m_aBotInfo['Connected'] = true;
             $this->m_aBotInfo['ConnectTry'] = 0;
             $this->m_aBotInfo['SentPings'] = 0;
             $this->m_sNickname = $this->In->Chunks[2];
             $this->m_pSocket->send('MODE ' . $this->m_sNickname . ' +B');
             $pModules->onConnect($this);
             break;
         case '005':
             // Information about what the server supports;
             $pNetworkManager = NetworkManager::getInstance();
             $pNetworkManager->parseSupported($sNetworkName, array_slice($this->In->Chunks, 3));
             if ($pNetworkManager->getSupportRule($sNetworkName, 'NAMESX') !== false) {
                 $this->m_pSocket->send('PROTOCTL NAMESX');
             }
             break;
         case '332':
             // Topic command
             if (!$bIsSlave) {
                 $pModules->onChannelTopic($this, $this->In->Chunks[3], $this->In->PostColon);
             }
             break;
         case '353':
             // Names command
             if (!$bIsSlave) {
                 $pModules->onChannelNames($this, $this->In->Chunks[4], $this->In->PostColon);
             }
             break;
         case 'invite':
             // Inviting someone to a channel
             if (!$bIsSlave) {
                 $pModules->onInvite($this, $this->In->User->Nickname, $this->In->Chunks[2], substr($this->In->Chunks[3], 1));
             }
             break;
         case 'join':
             // Joining a certain channel
             $sChannel = str_replace(':', '', $this->In->Chunks[2]);
             if ($this->In->User->Nickname == $this->m_sNickname) {
                 $this->m_aBotInfo['Channels'][strtolower($sChannel)] = true;
             }
             if (!$bIsSlave) {
                 $pModules->onChannelJoin($this, $sChannel, $this->In->User->Nickname);
             }
             break;
         case 'kick':
             // When someone gets kicked
             if ($this->In->Chunks[3] == $this->m_sNickname) {
                 unset($this->m_aBotInfo['Channels'][strtolower($this->In->Chunks[2])]);
             }
             if (!$bIsSlave) {
                 $pModules->onChannelKick($this, $this->In->Chunks[2], $this->In->Chunks[3], $this->In->User->Nickname, $this->In->PostColon);
             }
             break;
         case 'mode':
             // Change a mode on a channel
             if (!$bIsSlave) {
                 $pModules->onChannelMode($this, $this->In->Chunks[2], implode(' ', array_slice($this->In->Chunks, 3)));
             }
             break;
         case 'nick':
             // Nickchanges
             $sNewNick = str_replace(':', '', $this->In->Chunks[2]);
             if ($this->In->User->Nickname == $this->m_sNickname) {
                 $this->m_sNickname = $sNewNick;
             }
             if (!$bIsSlave) {
                 $pModules->onChangeNick($this, $this->In->User->Nickname, $sNewNick);
             }
             break;
         case 'notice':
             // Notice received from someone/something
             if ($this->In->PostColon == 'Nuwani201') {
                 /** Notice to see if we're still connected. **/
                 $this->m_aBotInfo['SentPings']--;
                 break;
             }
             if (!$bIsSlave) {
                 $pModules->onNotice($this, $this->In->Chunks[2], $this->In->User->Nickname, $this->In->PostColon);
             }
             break;
         case 'part':
             // Leaving a channel
             $sChannel = str_replace(':', '', $this->In->Chunks[2]);
             if ($this->In->User->Nickname == $this->m_sNickname) {
                 unset($this->m_aBotInfo['Channels'][strtolower($sChannel)]);
             }
             if (!$bIsSlave) {
                 $pModules->onChannelPart($this, $sChannel, $this->In->User->Nickname, $this->In->PostColon);
             }
             break;
         case 'privmsg':
             // A normal message of somekind
             if ($bIsSlave) {
                 break;
             }
             /** slaves don't handle messages **/
             $sMessageSource = ltrim($this->In->Chunks[2], '+%@&~:');
             if ($this->In->PostColon[0] != chr(1)) {
                 if (substr($sMessageSource, 0, 1) == '#') {
                     // If the bot was addressed, remove the prefix and handle the message like normal.
                     // The original message is still available in $pBot -> In -> PostColon.
                     $sMessage = $this->In->PostColon;
                     $sPrefix = $this->m_sNickname . ': ';
                     if (substr($sMessage, 0, strlen($sPrefix)) == $sPrefix) {
                         $sMessage = substr($sMessage, strlen($sPrefix));
                     }
                     $pModules->onChannelPrivmsg($this, $sMessageSource, $this->In->User->Nickname, $sMessage);
                 } else {
                     $pModules->onPrivmsg($this, $this->In->User->Nickname, $this->In->PostColon);
                 }
             } else {
                 $sType = strtoupper(substr(str_replace("", '', $this->In->Chunks[3]), 1));
                 $sMessage = trim(substr($this->In->PostColon, strlen($sType) + 2, -1));
                 $pModules->onCTCP($this, $sMessageSource, $this->In->User->Nickname, $sType, $sMessage);
             }
             break;
         case 'topic':
             // A topic has been changed
             if (!$bIsSlave) {
                 $pModules->onChangeTopic($this, $this->In->Chunks[2], $this->In->User->Nickname, $this->In->PostColon);
             }
             break;
         case 'quit':
             // Leaving IRC alltogether
             if (!$bIsSlave) {
                 $pModules->onQuit($this, $this->In->User->Nickname, $this->In->PostColon);
             }
             break;
         default:
             $pModules->onUnhandledCommand($this);
             break;
     }
     if (!$bIsSlave) {
         // Slaves are dumb... no really, they are.
         $pModules->onRaw($this, $this->In->Raw);
     }
     ErrorExceptionHandler::$Context = null;
     return true;
 }
示例#2
0
 /**
  * The invoking function which allows us to use fancy syntax for commands. It allows the user
  * and bot-system to directly invoke the object variable.
  *
  * @param Bot $pBot The bot that got the command.
  * @param string $sDestination The place we should send the output to.
  * @param string $sChannel The channel the command was received in.
  * @param string $sNickname The nickname of the user who executed the command.
  * @param array $aParams The parameters given to the command.
  * @param string $sMessage The complete message after the command.
  * @throws Exception If the command was not callable.
  * @return boolean Did the command execute?
  */
 public function __invoke(Bot $pBot, $sDestination, $sChannel, $sNickname, $aParams, $sMessage)
 {
     if (!is_callable($this->m_rCachedCommand)) {
         /** Quite a serious problem this is. Throw an Exception. **/
         throw new Exception('Command ' . $this->getCommand() . ' is not callable.');
     }
     if ($this->getPermission() !== null && !$pBot->getSecurityManager()->hasPermission($pBot->In->User, $this->getPermission())) {
         return false;
     }
     if ($this->checkNetwork($pBot['Network']) && $this->checkChannel($sChannel)) {
         $cFunction = $this->m_rCachedCommand;
         $this->m_aStatistics['Executed']++;
         $this->m_aStatistics['LastTime'] = time();
         /** Let the exception handler know where we are executing code. **/
         ErrorExceptionHandler::$Source = $sDestination;
         /** Catch output. **/
         ob_start();
         $fStart = microtime(true);
         /** Execute the command. **/
         $nReturnCode = call_user_func($cFunction, $pBot, $sDestination, $sChannel, $sNickname, $aParams, $sMessage);
         $this->m_aStatistics['TotalTime'] += microtime(true) - $fStart;
         if ($nReturnCode == null || !is_int($nReturnCode)) {
             $nReturnCode = self::OUTPUT_NORMAL;
         }
         switch ($nReturnCode) {
             default:
             case self::OUTPUT_NORMAL:
                 $sCallback = 'privmsg';
                 break;
             case self::OUTPUT_ERROR:
                 $sCallback = 'error';
                 break;
             case self::OUTPUT_INFO:
                 $sCallback = 'info';
                 break;
             case self::OUTPUT_NOTICE:
                 $sCallback = 'notice';
                 break;
             case self::OUTPUT_SUCCESS:
                 $sCallback = 'success';
                 break;
             case self::OUTPUT_USAGE:
                 $sCallback = 'usage';
                 break;
         }
         /** Send output to IRC. **/
         $aOutput = explode("\n", trim(ob_get_clean()));
         if (isset($pBot) && $pBot instanceof Bot) {
             foreach ($aOutput as $sLine) {
                 call_user_func(array('Command', $sCallback), $pBot, $sDestination, $sLine);
             }
         }
         return true;
     }
     return false;
 }
示例#3
0
 /**
  * This function will immediatly execute the evaluation that we're doing
  * right now. Evaluation delays are already handled by the parser.
  *
  * @param Bot $pBot Bot that should handle the evaluation.
  * @param string $sDestination Where should the output be redirected?
  * @param array $aOptions Array with the parsed options for this evaluation.
  */
 public function doEvaluation(Bot $pBot, $sDestination, $aOptions)
 {
     ob_start();
     ErrorExceptionHandler::$Source = $sDestination;
     switch ($aOptions['Type']) {
         case 'PHP':
             eval($aOptions['Operation']);
             break;
         case 'EXEC':
             $process = proc_open($aOptions['Operation'], array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
             if (is_resource($process)) {
                 fclose($pipes[0]);
                 $output = trim(stream_get_contents($pipes[1]));
                 fclose($pipes[1]);
                 $error = trim(stream_get_contents($pipes[2]));
                 fclose($pipes[2]);
                 $returnValue = proc_close($process);
                 if ($output != '') {
                     echo $output . ' ';
                 }
                 $haveNewLine = false;
                 if ($error != '') {
                     echo PHP_EOL . ModuleBase::COLOUR_RED . '* Error' . ModuleBase::CLEAR . ': ' . $error . ' ';
                     $haveNewLine = true;
                 }
                 if ($returnValue !== 0) {
                     if (!$haveNewLine) {
                         echo PHP_EOL;
                     } else {
                         echo '| ';
                     }
                     echo ModuleBase::COLOUR_TEAL;
                     if (!$haveNewLine) {
                         echo '* ';
                     }
                     echo 'Return value' . ModuleBase::CLEAR . ': ' . $returnValue;
                     $haveNewLine = true;
                 }
             }
             break;
         case 'SQL':
             $pDatabase = Database::getInstance();
             if ($pDatabase == null || $pDatabase->connect_error) {
                 echo '4* Database Error: Could not connect to database';
                 if ($pDatabase != null) {
                     echo ': "' . $pDatabase->connect_error . '"';
                 }
                 echo '.';
                 break;
             }
             $pResult = $pDatabase->query($aOptions['Operation']);
             if ($pResult === false) {
                 echo '4* Database Error: ' . $pDatabase->error;
             } else {
                 if ($pResult->num_rows == 0) {
                     echo '10* No rows.';
                 } else {
                     $aFields = $aFieldLen = array();
                     foreach ($pResult->fetch_fields() as $pField) {
                         $aFields[$pField->name] = array($pField->name);
                         $aFieldLen[$pField->name] = strlen($pField->name);
                     }
                     while (($aRow = $pResult->fetch_assoc()) != null) {
                         foreach ($aRow as $sField => $mValue) {
                             if ($mValue == null) {
                                 $mValue = 'NULL';
                             }
                             $aFields[$sField][] = $mValue;
                             $aFieldLen[$sField] = max($aFieldLen[$sField], strlen((string) $mValue));
                         }
                     }
                     // Output is imminent.
                     for ($i = 0; $i <= $pResult->num_rows; $i++) {
                         // 1 extra loop for the header.
                         foreach (array_keys($aFields) as $sField) {
                             echo sprintf('| ' . ($i == 0 ? '' : '') . '%\'' . chr(160) . '-' . $aFieldLen[$sField] . 's' . ($i == 0 ? '' : '') . ' ', $aFields[$sField][$i]);
                         }
                         echo '|' . PHP_EOL;
                     }
                 }
             }
             break;
     }
     $aOutput = explode("\n", trim(ob_get_clean()));
     if (count($aOutput) > $aOptions['MaxLines'] + 1 && $aOptions['Buffering'] == true) {
         $nSize = count($aOutput);
         $aOutput = array_slice($aOutput, 0, $aOptions['MaxLines']);
         $aOutput[] = '10* Displayed ' . $aOptions['MaxLines'] . ' out of ' . $nSize . ' lines.';
     }
     if (isset($pBot) && $pBot instanceof Bot) {
         foreach ($aOutput as $sLine) {
             $pBot->send('PRIVMSG ' . $sDestination . ' :' . trim($sLine), false);
         }
     }
 }