diff --git a/src/infrastructure/daemon/bot/PhabricatorBot.php b/src/infrastructure/daemon/bot/PhabricatorBot.php index 12ab9e663a..18a0c74648 100644 --- a/src/infrastructure/daemon/bot/PhabricatorBot.php +++ b/src/infrastructure/daemon/bot/PhabricatorBot.php @@ -1,154 +1,160 @@ getArgv(); if (count($argv) !== 1) { throw new Exception('usage: PhabricatorBot '); } $json_raw = Filesystem::readFile($argv[0]); try { $config = phutil_json_decode($json_raw); } catch (PhutilJSONParserException $ex) { throw new PhutilProxyException( pht("File '%s' is not valid JSON!", $argv[0]), $ex); } $nick = idx($config, 'nick', 'phabot'); $handlers = idx($config, 'handlers', array()); $protocol_adapter_class = idx( $config, 'protocol-adapter', 'PhabricatorIRCProtocolAdapter'); $this->pollFrequency = idx($config, 'poll-frequency', 1); $this->config = $config; foreach ($handlers as $handler) { $obj = newv($handler, array($this)); $this->handlers[] = $obj; } $ca_bundle = idx($config, 'https.cabundle'); if ($ca_bundle) { HTTPSFuture::setGlobalCABundleFromPath($ca_bundle); } $conduit_uri = idx($config, 'conduit.uri'); if ($conduit_uri) { - $conduit_user = idx($config, 'conduit.user'); - $conduit_cert = idx($config, 'conduit.cert'); + $conduit_token = idx($config, 'conduit.token'); // Normalize the path component of the URI so users can enter the // domain without the "/api/" part. $conduit_uri = new PhutilURI($conduit_uri); $conduit_host = (string)$conduit_uri->setPath('/'); $conduit_uri = (string)$conduit_uri->setPath('/api/'); $conduit = new ConduitClient($conduit_uri); - $response = $conduit->callMethodSynchronous( - 'conduit.connect', - array( - 'client' => 'PhabricatorBot', - 'clientVersion' => '1.0', - 'clientDescription' => php_uname('n').':'.$nick, - 'host' => $conduit_host, - 'user' => $conduit_user, - 'certificate' => $conduit_cert, - )); + if ($conduit_token) { + $conduit->setConduitToken($conduit_token); + } else { + $conduit_user = idx($config, 'conduit.user'); + $conduit_cert = idx($config, 'conduit.cert'); + + $response = $conduit->callMethodSynchronous( + 'conduit.connect', + array( + 'client' => 'PhabricatorBot', + 'clientVersion' => '1.0', + 'clientDescription' => php_uname('n').':'.$nick, + 'host' => $conduit_host, + 'user' => $conduit_user, + 'certificate' => $conduit_cert, + )); + } $this->conduit = $conduit; } // Instantiate Protocol Adapter, for now follow same technique as // handler instantiation $this->protocolAdapter = newv($protocol_adapter_class, array()); $this->protocolAdapter ->setConfig($this->config) ->connect(); $this->runLoop(); $this->protocolAdapter->disconnect(); } public function getConfig($key, $default = null) { return idx($this->config, $key, $default); } private function runLoop() { do { $this->stillWorking(); $messages = $this->protocolAdapter->getNextMessages($this->pollFrequency); if (count($messages) > 0) { foreach ($messages as $message) { $this->routeMessage($message); } } foreach ($this->handlers as $handler) { $handler->runBackgroundTasks(); } } while (!$this->shouldExit()); } public function writeMessage(PhabricatorBotMessage $message) { return $this->protocolAdapter->writeMessage($message); } private function routeMessage(PhabricatorBotMessage $message) { $ignore = $this->getConfig('ignore'); if ($ignore) { $sender = $message->getSender(); if ($sender && in_array($sender->getName(), $ignore)) { return; } } if ($message->getCommand() == 'LOG') { $this->log('[LOG] '.$message->getBody()); } foreach ($this->handlers as $handler) { try { $handler->receiveMessage($message); } catch (Exception $ex) { phlog($ex); } } } public function getAdapter() { return $this->protocolAdapter; } public function getConduit() { if (empty($this->conduit)) { throw new Exception( "This bot is not configured with a Conduit uplink. Set 'conduit.uri', ". "'conduit.user' and 'conduit.cert' in the configuration to connect."); } return $this->conduit; } } diff --git a/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php index cffa6faf35..f226d0ad76 100644 --- a/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php +++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php @@ -1,201 +1,200 @@ getCommand()) { case 'MESSAGE': $message = $original_message->getBody(); $matches = null; $paste_ids = array(); $commit_names = array(); $vote_ids = array(); $file_ids = array(); $object_names = array(); $output = array(); $pattern = '@'. - '(?getConduit()->callMethodSynchronous( 'phid.lookup', array( 'names' => $object_names, )); foreach ($objects as $object) { $output[$object['phid']] = $object['fullName'].' - '.$object['uri']; } } if ($vote_ids) { foreach ($vote_ids as $vote_id) { $vote = $this->getConduit()->callMethodSynchronous( 'slowvote.info', array( 'poll_id' => $vote_id, )); $output[$vote['phid']] = 'V'.$vote['id'].': '.$vote['question']. ' Come Vote '.$vote['uri']; } } if ($file_ids) { foreach ($file_ids as $file_id) { $file = $this->getConduit()->callMethodSynchronous( 'file.info', array( 'id' => $file_id, )); $output[$file['phid']] = $file['objectName'].': '. $file['uri'].' - '.$file['name']; } } if ($paste_ids) { foreach ($paste_ids as $paste_id) { $paste = $this->getConduit()->callMethodSynchronous( 'paste.query', array( 'ids' => array($paste_id), )); $paste = head($paste); $output[$paste['phid']] = 'P'.$paste['id'].': '.$paste['uri'].' - '. $paste['title']; if ($paste['language']) { $output[$paste['phid']] .= ' ('.$paste['language'].')'; } $user = $this->getConduit()->callMethodSynchronous( 'user.query', array( 'phids' => array($paste['authorPHID']), )); $user = head($user); if ($user) { $output[$paste['phid']] .= ' by '.$user['userName']; } } } if ($commit_names) { $commits = $this->getConduit()->callMethodSynchronous( - 'diffusion.getcommits', + 'diffusion.querycommits', array( - 'commits' => $commit_names, + 'names' => $commit_names, )); - foreach ($commits as $commit) { - if (isset($commit['error'])) { - continue; - } - $output[$commit['commitPHID']] = $commit['uri']; + foreach ($commits['data'] as $commit) { + $output[$commit['phid']] = $commit['uri']; } } foreach ($output as $phid => $description) { // Don't mention the same object more than once every 10 minutes // in public channels, so we avoid spamming the chat over and over // again for discsussions of a specific revision, for example. $target_name = $original_message->getTarget()->getName(); if (empty($this->recentlyMentioned[$target_name])) { $this->recentlyMentioned[$target_name] = array(); } $quiet_until = idx( $this->recentlyMentioned[$target_name], $phid, 0) + (60 * 10); if (time() < $quiet_until) { // Remain quiet on this channel. continue; } $this->recentlyMentioned[$target_name][$phid] = time(); $this->replyTo($original_message, $description); } break; } } }