diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 324b22991c..6331372f25 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -883,6 +883,7 @@ phutil_register_library_map(array( 'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php', 'PhabricatorIRCBot' => 'infrastructure/daemon/irc/PhabricatorIRCBot.php', 'PhabricatorIRCDifferentialNotificationHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCDifferentialNotificationHandler.php', + 'PhabricatorIRCFeedNotificationHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php', 'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCHandler.php', 'PhabricatorIRCLogHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCLogHandler.php', 'PhabricatorIRCMacroHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCMacroHandler.php', @@ -2262,6 +2263,7 @@ phutil_register_library_map(array( 'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController', 'PhabricatorIRCBot' => 'PhabricatorDaemon', 'PhabricatorIRCDifferentialNotificationHandler' => 'PhabricatorIRCHandler', + 'PhabricatorIRCFeedNotificationHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCLogHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCMacroHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler', diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php b/src/infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php new file mode 100644 index 0000000000..6f45ed936f --- /dev/null +++ b/src/infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php @@ -0,0 +1,159 @@ +getConfig('notification.types'); + + if ($show) { + $obj_type = str_replace('PhabricatorFeedStory', '', $story_class); + if (!in_array(strtolower($obj_type), $show)) { + return false; + } + } + + $verbosity = $this->getConfig('notification.verbosity', 3); + + $verbs = array(); + + switch ($verbosity) { + case 2: + $verbs[] = array( + 'commented', + 'added', + 'changed', + 'resigned', + 'explained', + 'modified', + 'attached', + 'edited', + 'joined', + 'left', + 'removed' + ); + // fallthrough + case 1: + $verbs[] = array( + 'updated', + 'accepted', + 'requested', + 'planned', + 'claimed', + 'summarized', + 'commandeered', + 'assigned' + ); + // fallthrough + case 0: + $verbs[] = array( + 'created', + 'closed', + 'raised', + 'committed', + 'reopened', + 'deleted' + ); + break; + + case 3: + default: + return true; + break; + } + + $verbs = '/('.implode('|', array_mergev($verbs)).')/'; + + if (preg_match($verbs, $story_text)) { + return true; + } + + return false; + } + + public function receiveMessage(PhabricatorIRCMessage $message) { + return; + } + + public function runBackgroundTasks() { + if ($this->startupDelay > 0) { + // the event loop runs every 1s so delay enough to fully conenct + $this->startupDelay--; + + return; + } + if ($this->lastSeenChronoKey == 0) { + // Since we only want to post notifications about new stories, skip + // everything that's happened in the past when we start up so we'll + // only process real-time stories. + $latest = $this->getConduit()->callMethodSynchronous( + 'feed.query', + array( + 'limit'=>1 + )); + + foreach ($latest as $story) { + if ($story['chronologicalKey'] > $this->lastSeenChronoKey) { + $this->lastSeenChronoKey = $story['chronologicalKey']; + } + } + + return; + } + + $config_max_pages = $this->getConfig('notification.max_pages', 5); + $config_page_size = $this->getConfig('notification.page_size', 10); + + $last_seen_chrono_key = $this->lastSeenChronoKey; + $chrono_key_cursor = 0; + + // Not efficient but works due to feed.query API + for ($max_pages = $config_max_pages; $max_pages > 0; $max_pages--) { + $stories = $this->getConduit()->callMethodSynchronous( + 'feed.query', + array( + 'limit'=>$config_page_size, + 'after'=>$chrono_key_cursor, + 'view'=>'text' + )); + + foreach ($stories as $story) { + if ($story['chronologicalKey'] == $last_seen_chrono_key) { + // Caught up on feed + return; + } + if ($story['chronologicalKey'] > $this->lastSeenChronoKey) { + // Keep track of newest seen story + $this->lastSeenChronoKey = $story['chronologicalKey']; + } + if (!$chrono_key_cursor || + $story['chronologicalKey'] < $chrono_key_cursor) { + // Keep track of oldest story on this page + $chrono_key_cursor = $story['chronologicalKey']; + } + + if (!$story['text'] || + !$this->shouldShowStory($story)) { + continue; + } + + $channels = $this->getConfig('join'); + foreach ($channels as $channel) { + $this->write('PRIVMSG', "{$channel} :{$story['text']}"); + } + } + } + } + +}