[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Simple IRC bot which runs as a Phabricator daemon. Although this bot is 5 * somewhat useful, it is also intended to serve as a demo of how to write 6 * "system agents" which communicate with Phabricator over Conduit, so you can 7 * script system interactions and integrate with other systems. 8 * 9 * NOTE: This is super janky and experimental right now. 10 */ 11 final class PhabricatorBot extends PhabricatorDaemon { 12 13 private $handlers; 14 15 private $conduit; 16 private $config; 17 private $pollFrequency; 18 19 public function run() { 20 $argv = $this->getArgv(); 21 if (count($argv) !== 1) { 22 throw new Exception('usage: PhabricatorBot <json_config_file>'); 23 } 24 25 $json_raw = Filesystem::readFile($argv[0]); 26 $config = json_decode($json_raw, true); 27 if (!is_array($config)) { 28 throw new Exception("File '{$argv[0]}' is not valid JSON!"); 29 } 30 31 $nick = idx($config, 'nick', 'phabot'); 32 $handlers = idx($config, 'handlers', array()); 33 $protocol_adapter_class = idx( 34 $config, 35 'protocol-adapter', 36 'PhabricatorIRCProtocolAdapter'); 37 $this->pollFrequency = idx($config, 'poll-frequency', 1); 38 39 $this->config = $config; 40 41 foreach ($handlers as $handler) { 42 $obj = newv($handler, array($this)); 43 $this->handlers[] = $obj; 44 } 45 46 $ca_bundle = idx($config, 'https.cabundle'); 47 if ($ca_bundle) { 48 HTTPSFuture::setGlobalCABundleFromPath($ca_bundle); 49 } 50 51 $conduit_uri = idx($config, 'conduit.uri'); 52 if ($conduit_uri) { 53 $conduit_user = idx($config, 'conduit.user'); 54 $conduit_cert = idx($config, 'conduit.cert'); 55 56 // Normalize the path component of the URI so users can enter the 57 // domain without the "/api/" part. 58 $conduit_uri = new PhutilURI($conduit_uri); 59 60 $conduit_host = (string)$conduit_uri->setPath('/'); 61 $conduit_uri = (string)$conduit_uri->setPath('/api/'); 62 63 $conduit = new ConduitClient($conduit_uri); 64 $response = $conduit->callMethodSynchronous( 65 'conduit.connect', 66 array( 67 'client' => 'PhabricatorBot', 68 'clientVersion' => '1.0', 69 'clientDescription' => php_uname('n').':'.$nick, 70 'host' => $conduit_host, 71 'user' => $conduit_user, 72 'certificate' => $conduit_cert, 73 )); 74 75 $this->conduit = $conduit; 76 } 77 78 // Instantiate Protocol Adapter, for now follow same technique as 79 // handler instantiation 80 $this->protocolAdapter = newv($protocol_adapter_class, array()); 81 $this->protocolAdapter 82 ->setConfig($this->config) 83 ->connect(); 84 85 $this->runLoop(); 86 87 $this->protocolAdapter->disconnect(); 88 } 89 90 public function getConfig($key, $default = null) { 91 return idx($this->config, $key, $default); 92 } 93 94 private function runLoop() { 95 do { 96 $this->stillWorking(); 97 98 $messages = $this->protocolAdapter->getNextMessages($this->pollFrequency); 99 if (count($messages) > 0) { 100 foreach ($messages as $message) { 101 $this->routeMessage($message); 102 } 103 } 104 105 foreach ($this->handlers as $handler) { 106 $handler->runBackgroundTasks(); 107 } 108 } while (!$this->shouldExit()); 109 110 } 111 112 public function writeMessage(PhabricatorBotMessage $message) { 113 return $this->protocolAdapter->writeMessage($message); 114 } 115 116 private function routeMessage(PhabricatorBotMessage $message) { 117 $ignore = $this->getConfig('ignore'); 118 if ($ignore) { 119 $sender = $message->getSender(); 120 if ($sender && in_array($sender->getName(), $ignore)) { 121 return; 122 } 123 } 124 125 if ($message->getCommand() == 'LOG') { 126 $this->log('[LOG] '.$message->getBody()); 127 } 128 129 foreach ($this->handlers as $handler) { 130 try { 131 $handler->receiveMessage($message); 132 } catch (Exception $ex) { 133 phlog($ex); 134 } 135 } 136 } 137 138 public function getAdapter() { 139 return $this->protocolAdapter; 140 } 141 142 public function getConduit() { 143 if (empty($this->conduit)) { 144 throw new Exception( 145 "This bot is not configured with a Conduit uplink. Set 'conduit.uri', ". 146 "'conduit.user' and 'conduit.cert' in the configuration to connect."); 147 } 148 return $this->conduit; 149 } 150 151 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |