[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Looks for Dxxxx, Txxxx and links to them. 5 */ 6 final class PhabricatorBotObjectNameHandler extends PhabricatorBotHandler { 7 8 /** 9 * Map of PHIDs to the last mention of them (as an epoch timestamp); prevents 10 * us from spamming chat when a single object is discussed. 11 */ 12 private $recentlyMentioned = array(); 13 14 public function receiveMessage(PhabricatorBotMessage $original_message) { 15 switch ($original_message->getCommand()) { 16 case 'MESSAGE': 17 $message = $original_message->getBody(); 18 $matches = null; 19 20 $paste_ids = array(); 21 $commit_names = array(); 22 $vote_ids = array(); 23 $file_ids = array(); 24 $object_names = array(); 25 $output = array(); 26 27 $pattern = 28 '@'. 29 '(?<!/)(?:^|\b)'. 30 '(R2D2)'. 31 '(?:\b|$)'. 32 '@'; 33 34 if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) { 35 foreach ($matches as $match) { 36 switch ($match[1]) { 37 case 'R2D2': 38 $output[$match[1]] = pht('beep boop bop'); 39 break; 40 } 41 } 42 } 43 44 $pattern = 45 '@'. 46 '(?<!/)(?:^|\b)'. // Negative lookbehind prevent matching "/D123". 47 '([A-Z])(\d+)'. 48 '(?:\b|$)'. 49 '@'; 50 51 if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) { 52 foreach ($matches as $match) { 53 switch ($match[1]) { 54 case 'P': 55 $paste_ids[] = $match[2]; 56 break; 57 case 'V': 58 $vote_ids[] = $match[2]; 59 break; 60 case 'F': 61 $file_ids[] = $match[2]; 62 break; 63 default: 64 $name = $match[1].$match[2]; 65 switch ($name) { 66 case 'T1000': 67 $output[$name] = pht( 68 'T1000: A mimetic poly-alloy assassin controlled by '. 69 'Skynet'); 70 break; 71 default: 72 $object_names[] = $name; 73 break; 74 } 75 break; 76 } 77 } 78 } 79 80 $pattern = 81 '@'. 82 '(?<!/)(?:^|\b)'. 83 '(r[A-Z]+)([0-9a-z]{0,40})'. 84 '(?:\b|$)'. 85 '@'; 86 if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) { 87 foreach ($matches as $match) { 88 if ($match[2]) { 89 $commit_names[] = $match[1].$match[2]; 90 } else { 91 $object_names[] = $match[1]; 92 } 93 } 94 } 95 96 if ($object_names) { 97 $objects = $this->getConduit()->callMethodSynchronous( 98 'phid.lookup', 99 array( 100 'names' => $object_names, 101 )); 102 foreach ($objects as $object) { 103 $output[$object['phid']] = $object['fullName'].' - '.$object['uri']; 104 } 105 } 106 107 if ($vote_ids) { 108 foreach ($vote_ids as $vote_id) { 109 $vote = $this->getConduit()->callMethodSynchronous( 110 'slowvote.info', 111 array( 112 'poll_id' => $vote_id, 113 )); 114 $output[$vote['phid']] = 'V'.$vote['id'].': '.$vote['question']. 115 ' Come Vote '.$vote['uri']; 116 } 117 } 118 119 if ($file_ids) { 120 foreach ($file_ids as $file_id) { 121 $file = $this->getConduit()->callMethodSynchronous( 122 'file.info', 123 array( 124 'id' => $file_id, 125 )); 126 $output[$file['phid']] = $file['objectName'].': '. 127 $file['uri'].' - '.$file['name']; 128 } 129 } 130 131 if ($paste_ids) { 132 foreach ($paste_ids as $paste_id) { 133 $paste = $this->getConduit()->callMethodSynchronous( 134 'paste.info', 135 array( 136 'paste_id' => $paste_id, 137 )); 138 // Eventually I'd like to show the username of the paster as well, 139 // however that will need something like a user.username_from_phid 140 // since we (ideally) want to keep the bot to Conduit calls...and 141 // not call to Phabricator-specific stuff (like actually loading 142 // the User object and fetching his/her username.) 143 $output[$paste['phid']] = 'P'.$paste['id'].': '.$paste['uri'].' - '. 144 $paste['title']; 145 146 if ($paste['language']) { 147 $output[$paste['phid']] .= ' ('.$paste['language'].')'; 148 } 149 } 150 } 151 152 if ($commit_names) { 153 $commits = $this->getConduit()->callMethodSynchronous( 154 'diffusion.getcommits', 155 array( 156 'commits' => $commit_names, 157 )); 158 foreach ($commits as $commit) { 159 if (isset($commit['error'])) { 160 continue; 161 } 162 $output[$commit['commitPHID']] = $commit['uri']; 163 } 164 } 165 166 foreach ($output as $phid => $description) { 167 168 // Don't mention the same object more than once every 10 minutes 169 // in public channels, so we avoid spamming the chat over and over 170 // again for discsussions of a specific revision, for example. 171 172 $target_name = $original_message->getTarget()->getName(); 173 if (empty($this->recentlyMentioned[$target_name])) { 174 $this->recentlyMentioned[$target_name] = array(); 175 } 176 177 $quiet_until = idx( 178 $this->recentlyMentioned[$target_name], 179 $phid, 180 0) + (60 * 10); 181 182 if (time() < $quiet_until) { 183 // Remain quiet on this channel. 184 continue; 185 } 186 187 $this->recentlyMentioned[$target_name][$phid] = time(); 188 $this->replyTo($original_message, $description); 189 } 190 break; 191 } 192 } 193 194 }
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 |