]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/OStatus/lib/salmonaction.php
Move some salmon processing to a superclass
[quix0rs-gnu-social.git] / plugins / OStatus / lib / salmonaction.php
1 <?php
2 /*
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2010, StatusNet, Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * @package OStatusPlugin
22  * @author James Walker <james@status.net>
23  */
24
25 if (!defined('STATUSNET')) {
26     exit(1);
27 }
28
29 class SalmonAction extends Action
30 {
31     var $xml      = null;
32     var $activity = null;
33
34     function prepare($args)
35     {
36         StatusNet::setApi(true); // Send smaller error pages
37
38         parent::prepare($args);
39
40         if ($_SERVER['REQUEST_METHOD'] != 'POST') {
41             $this->clientError(_('This method requires a POST.'));
42         }
43
44         if ($_SERVER['CONTENT_TYPE'] != 'application/atom+xml') {
45             $this->clientError(_('Salmon requires application/atom+xml'));
46         }
47
48         $xml = file_get_contents('php://input');
49
50         $dom = DOMDocument::loadXML($xml);
51
52         if ($dom->documentElement->namespaceURI != Activity::ATOM ||
53             $dom->documentElement->localName != 'entry') {
54             $this->clientError(_m('Salmon post must be an Atom entry.'));
55         }
56         // XXX: check the signature
57
58         $this->act = new Activity($dom->documentElement);
59         return true;
60     }
61
62     /**
63      * Check the posted activity type and break out to appropriate processing.
64      */
65
66     function handle($args)
67     {
68         StatusNet::setApi(true); // Send smaller error pages
69
70         // TODO : Insert new $xml -> notice code
71
72         if (Event::handle('StartHandleSalmon', array($this->activity))) {
73             switch ($this->act->verb)
74             {
75             case ActivityVerb::POST:
76                 $this->handlePost();
77                 break;
78             case ActivityVerb::SHARE:
79                 $this->handleShare();
80                 break;
81             case ActivityVerb::FAVORITE:
82                 $this->handleFavorite();
83                 break;
84             case ActivityVerb::FOLLOW:
85             case ActivityVerb::FRIEND:
86                 $this->handleFollow();
87                 break;
88             case ActivityVerb::UNFOLLOW:
89                 $this->handleUnfollow();
90                 break;
91             case ActivityVerb::JOIN:
92                 $this->handleJoin();
93                 break;
94             default:
95                 throw new ClientException(_("Unimplemented."));
96             }
97             Event::handle('EndHandleSalmon', array($this->activity));
98         }
99     }
100
101     function handlePost()
102     {
103         throw new ClientException(_("Unimplemented!"));
104     }
105
106     function handleFollow()
107     {
108         throw new ClientException(_("Unimplemented!"));
109     }
110
111     function handleUnfollow()
112     {
113         throw new ClientException(_("Unimplemented!"));
114     }
115
116     function handleFavorite()
117     {
118         throw new ClientException(_("Unimplemented!"));
119     }
120
121     /**
122      * Remote user doesn't like one of our posts after all!
123      * Confirm the post is ours, and delete a local favorite event.
124      */
125
126     function handleUnfavorite()
127     {
128         throw new ClientException(_("Unimplemented!"));
129     }
130
131     /**
132      * Hmmmm
133      */
134     function handleShare()
135     {
136         throw new ClientException(_("Unimplemented!"));
137     }
138
139     /**
140      * Hmmmm
141      */
142     function handleJoin()
143     {
144         throw new ClientException(_("Unimplemented!"));
145     }
146
147     /**
148      * @return Ostatus_profile
149      */
150     function ensureProfile()
151     {
152         $actor = $this->act->actor;
153         if (empty($actor->id)) {
154             common_log(LOG_ERR, "broken actor: " . var_export($actor, true));
155             throw new Exception("Received a salmon slap from unidentified actor.");
156         }
157
158         return Ostatus_profile::ensureActorProfile($this->act);
159     }
160
161     /**
162      * @fixme merge into Ostatus_profile::ensureActorProfile and friends
163      */
164     function createProfile()
165     {
166         $actor = $this->act->actor;
167
168         $profile = new Profile();
169
170         $profile->nickname = $this->nicknameFromURI($actor->id);
171
172         if (empty($profile->nickname)) {
173             $profile->nickname = common_nicknamize($actor->title);
174         }
175
176         $profile->fullname   = $actor->title;
177         $profile->bio        = $actor->summary; // XXX: is that right?
178         $profile->profileurl = $actor->link; // XXX: is that right?
179         $profile->created    = common_sql_now();
180
181         $id = $profile->insert();
182
183         if (empty($id)) {
184             common_log_db_error($profile, 'INSERT', __FILE__);
185             throw new Exception("Couldn't save new profile for $actor->id\n");
186         }
187
188         // XXX: add avatars
189
190         $op = new Ostatus_profile();
191
192         $op->profile_id = $id;
193         $op->homeuri    = $actor->id;
194         $op->created    = $profile->created;
195
196         // XXX: determine feed URI from source or Webfinger or whatever
197
198         $id = $op->insert();
199
200         if (empty($id)) {
201             common_log_db_error($op, 'INSERT', __FILE__);
202             throw new Exception("Couldn't save new ostatus profile for $actor->id\n");
203         }
204
205         return $profile;
206     }
207
208     /**
209      * @fixme should be merged into Ostatus_profile
210      */
211     function nicknameFromURI($uri)
212     {
213         preg_match('/(\w+):/', $uri, $matches);
214
215         $protocol = $matches[1];
216
217         switch ($protocol) {
218         case 'acct':
219         case 'mailto':
220             if (preg_match("/^$protocol:(.*)?@.*\$/", $uri, $matches)) {
221                 return common_canonical_nickname($matches[1]);
222             }
223             return null;
224         case 'http':
225             return common_url_to_nickname($uri);
226             break;
227         default:
228             return null;
229         }
230     }
231 }