From d091d061151749feddd3751f953f9bec48e382f2 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 8 Dec 2009 06:26:11 +0000 Subject: [PATCH] Notifier works, and bad subscriptions are deleted properly now. --- plugins/RSSCloud/RSSCloudNotifier.php | 78 +++++++++++++++++++++- plugins/RSSCloud/RSSCloudPlugin.php | 7 +- plugins/RSSCloud/RSSCloudRequestNotify.php | 58 ++++++++-------- 3 files changed, 113 insertions(+), 30 deletions(-) diff --git a/plugins/RSSCloud/RSSCloudNotifier.php b/plugins/RSSCloud/RSSCloudNotifier.php index eb3198b5a4..67bd000f00 100644 --- a/plugins/RSSCloud/RSSCloudNotifier.php +++ b/plugins/RSSCloud/RSSCloudNotifier.php @@ -33,6 +33,8 @@ if (!defined('STATUSNET')) { class RSSCloudNotifier { + const MAX_FAILURES = 3; + function challenge($endpoint, $feed) { $code = common_confirmation_code(128); @@ -55,6 +57,11 @@ class RSSCloudNotifier { if ($status >= 200 && $status < 300) { + // NOTE: the spec says that the body must contain the string + // challenge. It doesn't say that the body must contain the + // challenge string ONLY, although that seems to be the way + // the other implementations have interpreted it. + if (strpos($body, $code) !== false) { common_log(LOG_INFO, 'RSSCloud plugin - ' . "success testing notify handler: $endpoint"); @@ -100,10 +107,79 @@ class RSSCloudNotifier { common_log(LOG_INFO, 'RSSCloud plugin - failure notifying ' . $endpoint . ' that feed ' . $feed . ' has changed: got HTTP ' . $status); - common_debug('body = ' . var_export($response->getBody(), true)); return false; } } + function notify($profile) + { + $feed = common_path('api/statuses/user_timeline/') . + $profile->nickname . '.rss'; + + $cloudSub = new RSSCloudSubscription(); + $cloudSub->subscribed = $profile->id; + + if ($cloudSub->find()) { + while ($cloudSub->fetch()) { + $result = $this->postUpdate($cloudSub->url, $feed); + if ($result == false) { + $this->handleFailure($cloudSub); + } + } + } + } + + function handleFailure($cloudSub) + { + $failCnt = $cloudSub->failures + 1; + + if ($failCnt == self::MAX_FAILURES) { + + common_log(LOG_INFO, + 'Deleting RSSCloud subcription (max failure count reached), profile: ' . + $cloudSub->subscribed . + ' handler: ' . + $cloudSub->url); + + // XXX: WTF! ->delete() doesn't work. Clearly, there are some issues with + // the DB_DataObject, or my understanding of it. Have to drop into SQL. + + // $result = $cloudSub->delete(); + + $qry = 'DELETE from rsscloud_subscription' . + ' WHERE subscribed = ' . $cloudSub->subscribed . + ' AND url = \'' . $cloudSub->url . '\''; + + $result = $cloudSub->query($qry); + + if (!$result) { + common_log_db_error($cloudSub, 'DELETE', __FILE__); + common_log(LOG_ERR, 'Could not delete RSSCloud subscription.'); + } + + } else { + + common_debug('Updating failure count on RSSCloud subscription. ' . $failCnt); + + $failCnt = $cloudSub->failures + 1; + + // XXX: ->update() not working either, gar! + + $qry = 'UPDATE rsscloud_subscription' . + ' SET failures = ' . $failCnt . + ' WHERE subscribed = ' . $cloudSub->subscribed . + ' AND url = \'' . $cloudSub->url . '\''; + + common_debug($qry); + + $result = $cloudSub->query($qry); + + if (!$result) { + common_log_db_error($cloudsub, 'UPDATE', __FILE__); + common_log(LOG_ERR, 'Could not update failure count on RSSCloud subscription'); + } + } + } + } diff --git a/plugins/RSSCloud/RSSCloudPlugin.php b/plugins/RSSCloud/RSSCloudPlugin.php index 402fbec2d8..b9187d86c0 100644 --- a/plugins/RSSCloud/RSSCloudPlugin.php +++ b/plugins/RSSCloud/RSSCloudPlugin.php @@ -159,11 +159,16 @@ class RSSCloudPlugin extends Plugin { if (($queue == 'rsscloud') && ($this->_isLocal($notice))) { - // broadcast the notice here common_debug('broadcasting rssCloud bound notice ' . $notice->id); + $profile = $notice->getProfile(); + + $notifier = new RSSCloudNotifier(); + $notifier->notify($profile); + return false; } + return true; } diff --git a/plugins/RSSCloud/RSSCloudRequestNotify.php b/plugins/RSSCloud/RSSCloudRequestNotify.php index 135c316f7b..36959755a7 100644 --- a/plugins/RSSCloud/RSSCloudRequestNotify.php +++ b/plugins/RSSCloud/RSSCloudRequestNotify.php @@ -1,5 +1,4 @@ ip = $_SERVER['REMOTE_ADDR']; $this->port = $this->arg('port'); $this->path = $this->arg('path'); + + if ($this->path[0] != '/') { + $this->path = '/' . $this->path; + } + $this->protocol = $this->arg('protocol'); $this->procedure = $this->arg('notifyProcedure'); $this->domain = $this->arg('domain'); @@ -73,14 +77,10 @@ class RSSCloudRequestNotifyAction extends Action $missing[] = 'port'; } - $path = $this->arg('path'); - if (empty($this->path)) { $missing[] = 'path'; } - $protocol = $this->arg('protocol'); - if (empty($this->protocol)) { $missing[] = 'protocol'; } @@ -127,11 +127,12 @@ class RSSCloudRequestNotifyAction extends Action $this->saveSubscription($feed); } - // XXX: What to do about deleting stale subscriptions? 25 hours seems harsh. - // WordPress doesn't ever remove subscriptions. + // 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.'; + $msg = 'Thanks for the subscription. ' . + 'When the feed(s) update(s) we\'ll notify you.'; $this->showResult(true, $msg); } @@ -164,36 +165,40 @@ class RSSCloudRequestNotifyAction extends Action { common_debug("RSSCloudPlugin - testNotificationHandler()"); + $notifyUrl = $this->getNotifyUrl(); + $notifier = new RSSCloudNotifier(); if (isset($this->domain)) { // 'domain' param set, so we have to use GET and send a challenge - $endpoint = 'http://' . $this->domain . ':' . $this->port . '/' . $this->path; - common_log(LOG_INFO, 'Testing notification handler with challenge: ' . - $endpoint); - - return $notifier->challenge($endpoint, $feed); + $notifyUrl); + return $notifier->challenge($notifyUrl, $feed); } else { - - $endpoint = 'http://' . $this->ip . ':' . $this->port . '/' . $this->path; - common_log(LOG_INFO, 'Testing notification handler: ' . - $endpoint); + $notifyUrl); - return $notifier->postUpdate($endpoint, $feed); + return $notifier->postUpdate($notifyUrl, $feed); } - } + function getNotifyUrl() + { + if (isset($this->domain)) { + return 'http://' . $this->domain . ':' . $this->port . $this->path; + } else { + return 'http://' . $this->ip . ':' . $this->port . $this->path; + } + } + function userFromFeed($feed) { // We only do profile feeds - // XXX: Add cloud element to RSS 1.0 feeds + // XXX: Add cloud element to RSS 1.0 feeds? $path = common_path('api/statuses/user_timeline/'); $valid = '%^' . $path . '(?.*)\.rss$%'; @@ -212,7 +217,9 @@ class RSSCloudRequestNotifyAction extends Action { $user = $this->userFromFeed($feed); - $sub = RSSCloudSubscription::getSubscription($user->id, $this->url); + $notifyUrl = $this->getNotifyUrl(); + + $sub = RSSCloudSubscription::getSubscription($user->id, $notifyUrl); if ($sub) { common_debug("Already subscribed to that!"); @@ -221,19 +228,14 @@ class RSSCloudRequestNotifyAction extends Action $sub = new RSSCloudSubscription(); $sub->subscribed = $user->id; - $sub->url = $this->url; + $sub->url = $notifyUrl; $sub->created = common_sql_now(); - // auto timestamp doesn't seem to work for me - - // $sub->modified = common_sql_now(); - if (!$sub->insert()) { common_log_db_error($sub, 'INSERT', __FILE__); return false; } - DB_DataObject::debugLevel(); } return true; -- 2.39.5