[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/infrastructure/daemon/bot/handler/ -> PhabricatorBotObjectNameHandler.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1