mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-11 07:11:04 +01:00
Initial PhabricatorIRCFeedNotificationHandler
Summary: Follows Phabricator's feed and puts notifications into channels that are configured. ~~notification.all - bool - 1:1 stories to messages~~ notification.types - array - Specific story types to notify for - ["differential", "maniphest"] notification.verbosity - int - Range of 0-3 for verbosity notification.max_pages - int - Maximum number of pages to go back per poll notification.page_size - int - Size of pages (limit) to poll ~~notification.channels - array - Array of channels to send messages to~~ ~~notification.sleep - int - Seconds to sleep between polls~~ Test Plan: Run phabot with various configuration options Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin, asherkin Differential Revision: https://secure.phabricator.com/D4418
This commit is contained in:
parent
721071e5b3
commit
ff53b7942a
2 changed files with 161 additions and 0 deletions
|
@ -883,6 +883,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php',
|
'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php',
|
||||||
'PhabricatorIRCBot' => 'infrastructure/daemon/irc/PhabricatorIRCBot.php',
|
'PhabricatorIRCBot' => 'infrastructure/daemon/irc/PhabricatorIRCBot.php',
|
||||||
'PhabricatorIRCDifferentialNotificationHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCDifferentialNotificationHandler.php',
|
'PhabricatorIRCDifferentialNotificationHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCDifferentialNotificationHandler.php',
|
||||||
|
'PhabricatorIRCFeedNotificationHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php',
|
||||||
'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCHandler.php',
|
'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCHandler.php',
|
||||||
'PhabricatorIRCLogHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCLogHandler.php',
|
'PhabricatorIRCLogHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCLogHandler.php',
|
||||||
'PhabricatorIRCMacroHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCMacroHandler.php',
|
'PhabricatorIRCMacroHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCMacroHandler.php',
|
||||||
|
@ -2262,6 +2263,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
|
'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
|
||||||
'PhabricatorIRCBot' => 'PhabricatorDaemon',
|
'PhabricatorIRCBot' => 'PhabricatorDaemon',
|
||||||
'PhabricatorIRCDifferentialNotificationHandler' => 'PhabricatorIRCHandler',
|
'PhabricatorIRCDifferentialNotificationHandler' => 'PhabricatorIRCHandler',
|
||||||
|
'PhabricatorIRCFeedNotificationHandler' => 'PhabricatorIRCHandler',
|
||||||
'PhabricatorIRCLogHandler' => 'PhabricatorIRCHandler',
|
'PhabricatorIRCLogHandler' => 'PhabricatorIRCHandler',
|
||||||
'PhabricatorIRCMacroHandler' => 'PhabricatorIRCHandler',
|
'PhabricatorIRCMacroHandler' => 'PhabricatorIRCHandler',
|
||||||
'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler',
|
'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler',
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watches the feed and puts notifications into channel(s) of choice
|
||||||
|
*
|
||||||
|
* @group irc
|
||||||
|
*/
|
||||||
|
final class PhabricatorIRCFeedNotificationHandler
|
||||||
|
extends PhabricatorIRCHandler {
|
||||||
|
|
||||||
|
private $startupDelay = 30;
|
||||||
|
private $lastSeenChronoKey = 0;
|
||||||
|
|
||||||
|
private function shouldShowStory($story) {
|
||||||
|
$story_class = $story['class'];
|
||||||
|
$story_text = $story['text'];
|
||||||
|
|
||||||
|
$show = $this->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']}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue