]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/OStatus/actions/usersalmon.php
Check the notice context for users in UsersalmonAction
[quix0rs-gnu-social.git] / plugins / OStatus / actions / usersalmon.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 if (!defined('GNUSOCIAL')) { exit(1); }
21
22 /**
23  * @package OStatusPlugin
24  * @author James Walker <james@status.net>
25  */
26 class UsersalmonAction extends SalmonAction
27 {
28     protected function prepare(array $args=array())
29     {
30         parent::prepare($args);
31
32         $this->user = User::getByID($this->trimmed('id'));
33
34         $this->target = $this->user->getProfile();
35
36         // Notice must either be a) in reply to a notice by this user
37         // or b) in reply to a notice to the attention of this user
38         // or c) to the attention of this user
39         // or d) reference the user as an activity:object
40
41         $notice = null;
42
43         if (!empty($this->activity->context->replyToID)) {
44             try {
45                 $notice = Notice::getKV('uri', $this->activity->context->replyToID);
46             } catch (NoResultException $e) {
47                 $notice = false;
48             }
49         }
50
51         if ($notice instanceof Notice &&
52                 ($this->target->sameAs($notice->getProfile())
53                     || array_key_exists($this->target->getID(), $notice->getAttentionProfileIDs())
54                 )) {
55             // In reply to a notice either from or mentioning this user.
56             common_debug('User is the owner or was in the attention list of thr:in-reply-to activity.');
57         } elseif (!empty($this->activity->context->attention) &&
58                    array_key_exists($this->target->getUri(), $this->activity->context->attention)) {
59             // To the attention of this user.
60             common_debug('User was in attention list of salmon slap.');
61         } elseif (!empty($this->activity->objects) && $this->activity->objects[0]->id === $this->target->getUri()) {
62             // The user is the object of this slap (unfollow for example)
63             common_debug('User URI was the id of the salmon slap object.');
64         } else {
65             common_debug('User was NOT found in salmon slap context.');
66             // TRANS: Client exception.
67             throw new ClientException(_m('The owner of this salmon endpoint was not in the context of the carried slap.'));
68         }
69
70         return true;
71     }
72
73     /**
74      * We've gotten a post event on the Salmon backchannel, probably a reply.
75      *
76      * @todo validate if we need to handle this post, then call into
77      * ostatus_profile's general incoming-post handling.
78      */
79     function handlePost()
80     {
81         common_log(LOG_INFO, "Received post of '{$this->activity->objects[0]->id}' from '{$this->activity->actor->id}'");
82
83         // @fixme: process all activity objects?
84         switch ($this->activity->objects[0]->type) {
85         case ActivityObject::ARTICLE:
86         case ActivityObject::BLOGENTRY:
87         case ActivityObject::NOTE:
88         case ActivityObject::STATUS:
89         case ActivityObject::COMMENT:
90             break;
91         default:
92             // TRANS: Client exception thrown when an undefied activity is performed.
93             throw new ClientException(_m('Cannot handle that kind of post.'));
94         }
95
96         try {
97             $this->saveNotice();
98         } catch (AlreadyFulfilledException $e) {
99             return;
100         }
101     }
102
103     /**
104      * We've gotten a follow/subscribe notification from a remote user.
105      * Save a subscription relationship for them.
106      */
107     function handleFollow()
108     {
109         common_log(LOG_INFO, sprintf('Setting up subscription from remote %s to local %s', $this->oprofile->getUri(), $this->target->getNickname()));
110         Subscription::start($this->actor, $this->target);
111     }
112
113     /**
114      * We've gotten an unfollow/unsubscribe notification from a remote user.
115      * Check if we have a subscription relationship for them and kill it.
116      *
117      * @fixme probably catch exceptions on fail?
118      */
119     function handleUnfollow()
120     {
121         common_log(LOG_INFO, sprintf('Canceling subscription from remote %s to local %s', $this->oprofile->getUri(), $this->target->getNickname()));
122         try {
123             Subscription::cancel($this->actor, $this->target);
124         } catch (NoProfileException $e) {
125             common_debug('Could not find profile for Subscription: '.$e->getMessage());
126         }
127     }
128
129     function handleTag()
130     {
131         if ($this->activity->target->type == ActivityObject::_LIST) {
132             if ($this->activity->objects[0]->type != ActivityObject::PERSON) {
133                 // TRANS: Client exception.
134                 throw new ClientException(_m('Not a person object.'));
135             }
136             // this is a peopletag
137             $tagged = User::getKV('uri', $this->activity->objects[0]->id);
138
139             if (!$tagged instanceof User) {
140                 // TRANS: Client exception.
141                 throw new ClientException(_m('Unidentified profile being listed.'));
142             }
143
144             if ($tagged->id !== $this->target->id) {
145                 // TRANS: Client exception.
146                 throw new ClientException(_m('This user is not the one being listed.'));
147             }
148
149             // save the list
150             $list   = Ostatus_profile::ensureActivityObjectProfile($this->activity->target);
151
152             $ptag = $list->localPeopletag();
153             $result = Profile_tag::setTag($ptag->tagger, $tagged->id, $ptag->tag);
154             if (!$result) {
155                 // TRANS: Client exception.
156                 throw new ClientException(_m('The listing could not be saved.'));
157             }
158         }
159     }
160
161     function handleUntag()
162     {
163         if ($this->activity->target->type == ActivityObject::_LIST) {
164             if ($this->activity->objects[0]->type != ActivityObject::PERSON) {
165                 // TRANS: Client exception.
166                 throw new ClientException(_m('Not a person object.'));
167             }
168             // this is a peopletag
169             $tagged = User::getKV('uri', $this->activity->objects[0]->id);
170
171             if (!$tagged instanceof User) {
172                 // TRANS: Client exception.
173                 throw new ClientException(_m('Unidentified profile being unlisted.'));
174             }
175
176             if ($tagged->id !== $this->target->id) {
177                 // TRANS: Client exception.
178                 throw new ClientException(_m('This user is not the one being unlisted.'));
179             }
180
181             // save the list
182             $list   = Ostatus_profile::ensureActivityObjectProfile($this->activity->target);
183
184             $ptag = $list->localPeopletag();
185             $result = Profile_tag::unTag($ptag->tagger, $tagged->id, $ptag->tag);
186
187             if (!$result) {
188                 // TRANS: Client exception.
189                 throw new ClientException(_m('The listing could not be deleted.'));
190             }
191         }
192     }
193
194     /**
195      * @param ActivityObject $object
196      * @return Notice
197      * @throws ClientException on invalid input
198      */
199     function getNotice(ActivityObject $object)
200     {
201         switch ($object->type) {
202         case ActivityObject::ARTICLE:
203         case ActivityObject::BLOGENTRY:
204         case ActivityObject::NOTE:
205         case ActivityObject::STATUS:
206         case ActivityObject::COMMENT:
207             break;
208         default:
209             // TRANS: Client exception.
210             throw new ClientException(_m('Cannot handle that kind of object for liking/faving.'));
211         }
212
213         $notice = Notice::getKV('uri', $object->id);
214
215         if (!$notice instanceof Notice) {
216             // TRANS: Client exception. %s is an object ID.
217             throw new ClientException(sprintf(_m('Notice with ID %s unknown.'),$object->id));
218         }
219
220         if ($notice->profile_id != $this->target->id) {
221             // TRANS: Client exception. %1$s is a notice ID, %2$s is a user ID.
222             throw new ClientException(sprintf(_m('Notice with ID %1$s not posted by %2$s.'), $object->id, $this->target->id));
223         }
224
225         return $notice;
226     }
227 }