diff --git a/plugins/RSSCloud/RSSCloudNotifier.php b/plugins/RSSCloud/RSSCloudNotifier.php index 65bfd032e9..c2130b7b83 100644 --- a/plugins/RSSCloud/RSSCloudNotifier.php +++ b/plugins/RSSCloud/RSSCloudNotifier.php @@ -2,7 +2,7 @@ /** * StatusNet, the distributed open-source microblogging tool * - * Class to ping an rssCloud hub when a feed has been updated + * Class to ping an rssCloud endpoint when a feed has been updated * * PHP version 5 * @@ -40,12 +40,15 @@ class RSSCloudNotifier { $result = $this->httpPost($endpoint, $params); + // XXX: Make all this use CurlClient (lib/curlclient.php) + if ($result) { - common_debug('success notifying cloud'); + common_debug('RSSCloud plugin - success notifying cloud endpoint!'); } else { - common_debug('failure notifying cloud'); + common_debug('RSSClous plugin - failure notifying cloud endpoint!'); } + return $result; } function userAgent() @@ -56,8 +59,6 @@ class RSSCloudNotifier { private function httpPost($url, $params) { - common_debug('params: ' . var_export($params, true)); - $options = array(CURLOPT_URL => $url, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $params, @@ -78,9 +79,6 @@ class RSSCloudNotifier { curl_close($ch); - common_debug('curl response: ' . var_export($response, true)); - common_debug('curl info: ' . var_export($info, true)); - if ($info['http_code'] == 200) { return true; } else { diff --git a/plugins/RSSCloud/RSSCloudPlugin.php b/plugins/RSSCloud/RSSCloudPlugin.php index 50d9060efe..a971c31567 100644 --- a/plugins/RSSCloud/RSSCloudPlugin.php +++ b/plugins/RSSCloud/RSSCloudPlugin.php @@ -40,10 +40,8 @@ class RSSCloudPlugin extends Plugin parent::__construct(); } - function onInitializePlugin(){ - - common_debug("RSSCloudPlugin onInitializePlugin()"); - + function onInitializePlugin() + { $this->domain = common_config('rsscloud', 'domain'); $this->port = common_config('rsscloud', 'port'); $this->path = common_config('rsscloud', 'path'); @@ -52,16 +50,18 @@ class RSSCloudPlugin extends Plugin // set defaults + $local_server = parse_url(common_path('rsscloud/request_notify')); + if (empty($this->domain)) { - $this->domain = 'rpc.rsscloud.org'; + $this->domain = $local_server['host']; } if (empty($this->port)) { - $this->port = '5337'; + $this->port = '80'; } if (empty($this->path)) { - $this->path = '/rsscloud/pleaseNotify'; + $this->path = '/rsscloud/request_notify'; } if (empty($this->funct)) { @@ -84,6 +84,8 @@ class RSSCloudPlugin extends Plugin function onRouterInitialized(&$m) { $m->connect('rsscloud/request_notify', array('action' => 'RSSCloudRequestNotify')); + + // XXX: This is just for end-to-end testing $m->connect('rsscloud/notify', array('action' => 'LoggingAggregator')); return true; @@ -91,8 +93,6 @@ class RSSCloudPlugin extends Plugin function onAutoload($cls) { - common_debug("onAutoload() $cls"); - switch ($cls) { @@ -111,22 +111,26 @@ class RSSCloudPlugin extends Plugin function onStartApiRss($action){ - // XXX: No sure we want every feed to be cloud enabled + // XXX: we want to only cloud enable the user_timeline so we need + // to be even more specific than this... FIXME - $attrs = array('domain' => $this->domain, - 'port' => $this->port, - 'path' => $this->path, - 'registerProcedure' => $this->funct, - 'protocol' => $this->protocol); + if (get_class($action) == 'TwitapistatusesAction') { - // Dipping into XMLWriter to avoid a full end element (). + $attrs = array('domain' => $this->domain, + 'port' => $this->port, + 'path' => $this->path, + 'registerProcedure' => $this->funct, + 'protocol' => $this->protocol); + + // Dipping into XMLWriter to avoid a full end element (). + + $action->xw->startElement('cloud'); + foreach ($attrs as $name => $value) { + $action->xw->writeAttribute($name, $value); + } + $action->xw->endElement(); - $action->xw->startElement('cloud'); - foreach ($attrs as $name => $value) { - $action->xw->writeAttribute($name, $value); } - $action->xw->endElement('cloud'); - } function onEndNoticeSave($notice){ @@ -139,11 +143,10 @@ class RSSCloudPlugin extends Plugin 'argument' => $user->nickname . '.rss')); // XXX: Dave's hub for testing + // $endpoint = 'http://rpc.rsscloud.org:5337/rsscloud/ping'; - $endpoint = 'http://rpc.rsscloud.org:5337/rsscloud/ping'; - - $notifier = new RSSCloudNotifier(); - $notifier->postUpdate($endpoint, $feed); + // $notifier = new RSSCloudNotifier(); + // $notifier->postUpdate($endpoint, $feed); } } diff --git a/plugins/RSSCloud/RSSCloudRequestNotify.php b/plugins/RSSCloud/RSSCloudRequestNotify.php index 1d4087334f..48bd3fb270 100644 --- a/plugins/RSSCloud/RSSCloudRequestNotify.php +++ b/plugins/RSSCloud/RSSCloudRequestNotify.php @@ -1,7 +1,8 @@ ip = $_SERVER['REMOTE_ADDR']; + $this->port = $this->arg('port'); + $this->path = $this->arg('path'); + $this->protocol = $this->arg('protocol'); + $this->procedure = $this->arg('notifyProcedure'); + $this->feeds = $this->getFeeds(); + + $this->subscriber_url = 'http://' . $this->ip . ':' . $this->port . $this->path; + return true; } function handle($args) { parent::handle($args); - + if ($_SERVER['REQUEST_METHOD'] != 'POST') { - showResult(false, 'Request must be POST.'); + $this->showResult(false, 'Request must be POST.'); + return; } - - $ip = $_SERVER['REMOTE_ADDR']; + $missing = array(); - $port = $this->arg('port'); - + if (empty($this->port)) { $missing[] = 'port'; } - + $path = $this->arg('path'); if (empty($this->path)) { $missing[] = 'path'; } - + $protocol = $this->arg('protocol'); if (empty($this->protocol)) { $missing[] = 'protocol'; } - - if (empty($this->notifyProcedure)) { + + if (!isset($this->procedure)) { $missing[] = 'notifyProcedure'; } - + if (!empty($missing)) { $msg = 'The following parameters were missing from the request body: ' . - implode(',', $missing) . '.'; + implode(', ', $missing) . '.'; $this->showResult(false, $msg); + return; } - - $feeds = $this->getFeeds(); - - if (empty($feeds)) { - $this->showResult(false, - 'You must provide at least one feed url (url1, url2, url3 ... urlN).'); + + if (empty($this->feeds)) { + $this->showResult(false, + 'You must provide at least one valid profile feed url (url1, url2, url3 ... urlN).'); + return; } - + $endpoint = $ip . ':' . $port . $path; - - foreach ($feeds as $feed) { - + + foreach ($this->feeds as $feed) { + $this->saveSubscription($feed); } - - + + // XXX: What to do about deleting stale subscriptions? 25 hours seems harsh. + // WordPress doesn't ever remove subscriptions. + + $msg = 'Thanks for the registration. It worked. When the feed(s) update(s) we\'ll notify you. ' . + ' Don\'t forget to re-register after 24 hours, your subscription will expire in 25.'; + + $this->showResult(true, $msg); } - - + function getFeeds() { $feeds = array(); - + foreach ($this->args as $key => $feed ) { if (preg_match('|url\d+|', $key)) { - - // XXX: validate feeds somehow and kick bad ones out - - $feeds[] = $feed; + + if ($this->testFeed($feed)) { + $feeds[] = $feed; + } else { + $msg = 'RSSCloud Plugin - ' . $this->ip . ' tried to subscribe ' . + 'to a non-existent feed: ' . $feed; + common_log(LOG_WARN, $msg); + } } } - + return $feeds; } - - - function checkNotifyHandler() + + function testNotificationHandler($feed) { - + $notifier = new RSSCloudNotifier(); + return $notifier->postUpdate($endpoint, $feed); } - - function validateFeed() + + // returns valid user or false + function testFeed($feed) { + $user = $this->userFromFeed($feed); + + if (!empty($user)) { + + common_debug("Valid feed: $feed"); + + // OK, so this is a valid profile feed url, now let's see if the + // other system reponds to our notifications before we + // add the sub... + + if ($this->testNotificationHandler($feed)) { + return true; + } + } + + return false; } - - function showResult($success, $msg) + + // this actually does the validating and figuring out the + // user, which it returns + function userFromFeed($feed) + { + // We only do profile feeds + + $path = common_path('api/statuses/user_timeline/'); + $valid = '%^' . $path . '(?.*)\.rss$%'; + + if (preg_match($valid, $feed, $matches)) { + $user = User::staticGet('nickname', $matches['nickname']); + if (!empty($user)) { + return $user; + } + } + + return false; + } + + function saveSubscription($feed) + { + // check to see if we already have a profile for this subscriber + + $other = Remote_profile::staticGet('uri', $this->subscriber_url); + + if ($other === false) { + $other->saveProfile(); + } + + $user = userFromFeed($feed); + + $result = subs_subscribe_to($user, $other); + + if ($result != true) { + $msg = "RSSPlugin - got '$result' trying to subscribe " . + "$this->subscriber_url to $user->nickname" . "'s profile feed."; + common_log(LOG_WARN, $msg); + } else { + $msg = 'RSSCloud plugin - subscribe: ' . $this->subscriber_url . + ' subscribed to ' . $feed; + + common_log(LOG_INFO, $msg); + } + } + + function saveProfile() + { + common_debug("Saving remote profile for $this->subscriber_url"); + + // XXX: We need to add a field to Remote_profile to indicate the kind + // of remote profile? i.e: OMB, RSSCloud, PuSH, Twitter + + $remote = new Remote_profile(); + $remote->uri = $this->subscriber_url; + $remote->postnoticeurl = $this->subscriber_url; + $remote->created = DB_DataObject_Cast::dateTime(); + + if (!$remote->insert()) { + throw new Exception(_('RSSCloud plugin - Error inserting remote profile!')); + } + } + + function showResult($success, $msg) { $this->startXML(); $this->elementStart('notifyResult', array('success' => ($success) ? 'true' : 'false', 'msg' => $msg)); $this->endXML(); - } - - + }