]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/RSSCloud/RSSCloudRequestNotify.php
/rsscloud/request_notify should work now
[quix0rs-gnu-social.git] / plugins / RSSCloud / RSSCloudRequestNotify.php
1 <?php
2
3 /**
4  * Action to let RSSCloud aggregators request update notification when
5  * user profile feeds change.
6  *
7  * PHP version 5
8  *
9  * @category Plugin
10  * @package  StatusNet
11  * @author   Zach Copley <zach@status.net>
12  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
13  * @link     http://status.net/
14  *
15  * StatusNet - the distributed open-source microblogging tool
16  * Copyright (C) 2009, StatusNet, Inc.
17  *
18  * This program is free software: you can redistribute it and/or modify
19  * it under the terms of the GNU Affero General Public License as published by
20  * the Free Software Foundation, either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU Affero General Public License for more details.
27  *
28  * You should have received a copy of the GNU Affero General Public License
29  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
30  */
31
32 if (!defined('STATUSNET')) {
33     exit(1);
34 }
35
36 class RSSCloudRequestNotifyAction extends Action
37 {
38     /**
39      * Initialization.
40      *
41      * @param array $args Web and URL arguments
42      *
43      * @return boolean false if user doesn't exist
44      */
45     function prepare($args)
46     {
47         parent::prepare($args);
48
49         $this->ip        = $_SERVER['REMOTE_ADDR'];
50         $this->port      = $this->arg('port');
51         $this->path      = $this->arg('path');
52         $this->protocol  = $this->arg('protocol');
53         $this->procedure = $this->arg('notifyProcedure');
54         $this->feeds     = $this->getFeeds();
55
56         $this->subscriber_url = 'http://' . $this->ip . ':' . $this->port . $this->path;
57
58         return true;
59     }
60
61     function handle($args)
62     {
63         parent::handle($args);
64
65         if ($_SERVER['REQUEST_METHOD'] != 'POST') {
66             $this->showResult(false, 'Request must be POST.');
67             return;
68         }
69
70         $missing = array();
71
72         if (empty($this->port)) {
73             $missing[] = 'port';
74         }
75
76         $path = $this->arg('path');
77
78         if (empty($this->path)) {
79             $missing[] = 'path';
80         }
81
82         $protocol = $this->arg('protocol');
83
84         if (empty($this->protocol)) {
85             $missing[] = 'protocol';
86         }
87
88         if (!isset($this->procedure)) {
89             $missing[] = 'notifyProcedure';
90         }
91
92         if (!empty($missing)) {
93             $msg = 'The following parameters were missing from the request body: ' .
94                 implode(', ', $missing) . '.';
95             $this->showResult(false, $msg);
96             return;
97         }
98
99         if (empty($this->feeds)) {
100             $this->showResult(false,
101                               'You must provide at least one valid profile feed url (url1, url2, url3 ... urlN).');
102             return;
103         }
104
105         $endpoint = $ip . ':' . $port . $path;
106
107         foreach ($this->feeds as $feed) {
108             $this->saveSubscription($feed);
109         }
110
111         // XXX: What to do about deleting stale subscriptions?  25 hours seems harsh.
112         // WordPress doesn't ever remove subscriptions.
113
114         $msg = 'Thanks for the registration. It worked. When the feed(s) update(s) we\'ll notify you. ' .
115                ' Don\'t forget to re-register after 24 hours, your subscription will expire in 25.';
116
117         $this->showResult(true, $msg);
118     }
119
120     function getFeeds()
121     {
122         $feeds = array();
123
124         foreach ($this->args as $key => $feed ) {
125             if (preg_match('|url\d+|', $key)) {
126
127                 if ($this->testFeed($feed)) {
128                     $feeds[] = $feed;
129                 } else {
130                     $msg = 'RSSCloud Plugin - ' . $this->ip . ' tried to subscribe ' .
131                            'to a non-existent feed: ' . $feed;
132                     common_log(LOG_WARN, $msg);
133                 }
134             }
135         }
136
137         return $feeds;
138     }
139
140     function testNotificationHandler($feed)
141     {
142         $notifier = new RSSCloudNotifier();
143         return $notifier->postUpdate($endpoint, $feed);
144     }
145
146     // returns valid user or false
147     function testFeed($feed)
148     {
149         $user = $this->userFromFeed($feed);
150
151         if (!empty($user)) {
152
153             common_debug("Valid feed: $feed");
154
155             // OK, so this is a valid profile feed url, now let's see if the
156             // other system reponds to our notifications before we
157             // add the sub...
158
159             if ($this->testNotificationHandler($feed)) {
160                 return true;
161             }
162         }
163
164         return false;
165     }
166
167     // this actually does the validating and figuring out the
168     // user, which it returns
169     function userFromFeed($feed)
170     {
171         // We only do profile feeds
172
173         $path = common_path('api/statuses/user_timeline/');
174         $valid = '%^' . $path . '(?<nickname>.*)\.rss$%';
175
176         if (preg_match($valid, $feed, $matches)) {
177             $user = User::staticGet('nickname', $matches['nickname']);
178             if (!empty($user)) {
179                 return $user;
180             }
181         }
182
183         return false;
184     }
185
186     function saveSubscription($feed)
187     {
188         // check to see if we already have a profile for this subscriber
189
190         $other = Remote_profile::staticGet('uri', $this->subscriber_url);
191
192         if ($other === false) {
193             $other->saveProfile();
194         }
195
196         $user = userFromFeed($feed);
197
198         $result = subs_subscribe_to($user, $other);
199
200         if ($result != true) {
201             $msg = "RSSPlugin - got '$result' trying to subscribe " .
202                    "$this->subscriber_url to $user->nickname" . "'s profile feed.";
203             common_log(LOG_WARN, $msg);
204         } else {
205             $msg = 'RSSCloud plugin - subscribe: ' . $this->subscriber_url .
206                    ' subscribed to ' . $feed;
207
208             common_log(LOG_INFO, $msg);
209         }
210     }
211
212     function saveProfile()
213     {
214         common_debug("Saving remote profile for $this->subscriber_url");
215
216         // XXX: We need to add a field to Remote_profile to indicate the kind
217         // of remote profile?  i.e: OMB, RSSCloud, PuSH, Twitter
218
219         $remote                = new Remote_profile();
220         $remote->uri           = $this->subscriber_url;
221         $remote->postnoticeurl = $this->subscriber_url;
222         $remote->created       = DB_DataObject_Cast::dateTime();
223
224         if (!$remote->insert()) {
225             throw new Exception(_('RSSCloud plugin - Error inserting remote profile!'));
226         }
227     }
228
229     function showResult($success, $msg)
230     {
231         $this->startXML();
232         $this->elementStart('notifyResult', array('success' => ($success) ? 'true' : 'false',
233                                                   'msg'     => $msg));
234         $this->endXML();
235     }
236
237 }
238
239
240