]> git.mxchange.org Git - friendica.git/blob - src/Model/Introduction.php
Detection of local requests
[friendica.git] / src / Model / Introduction.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Model;
23
24 use Friendica\BaseModel;
25 use Friendica\Core\Protocol;
26 use Friendica\Database\Database;
27 use Friendica\Network\HTTPException;
28 use Friendica\Protocol\ActivityPub;
29 use Friendica\Protocol\Diaspora;
30 use Friendica\Repository;
31 use Friendica\Util\DateTimeFormat;
32 use Psr\Log\LoggerInterface;
33
34 /**
35  * @property int    uid
36  * @property int    fid
37  * @property int    contact-id
38  * @property bool   knowyou
39  * @property bool   duplex
40  * @property string note
41  * @property string hash
42  * @property string datetime
43  * @property bool   blocked
44  * @property bool   ignore
45  */
46 class Introduction extends BaseModel
47 {
48         /** @var Repository\Introduction */
49         protected $intro;
50
51         public function __construct(Database $dba, LoggerInterface $logger, Repository\Introduction $intro, array $data = [])
52         {
53                 parent::__construct($dba, $logger, $data);
54
55                 $this->intro = $intro;
56         }
57
58         /**
59          * Confirms a follow request and sends a notice to the remote contact.
60          *
61          * @param bool               $duplex       Is it a follow back?
62          * @param bool|null          $hidden       Should this contact be hidden? null = no change
63          * @return bool
64          * @throws HTTPException\InternalServerErrorException
65          * @throws HTTPException\NotFoundException
66          * @throws \ImagickException
67          */
68         public function confirm(bool $duplex = false, bool $hidden = null)
69         {
70                 $this->logger->info('Confirming follower', ['cid' => $this->{'contact-id'}]);
71
72                 $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]);
73
74                 if (!$contact) {
75                         throw new HTTPException\NotFoundException('Contact record not found.');
76                 }
77
78                 $newRelation = $contact['rel'];
79                 $writable = $contact['writable'];
80
81                 if (!empty($contact['protocol'])) {
82                         $protocol = $contact['protocol'];
83                 } else {
84                         $protocol = $contact['network'];
85                 }
86
87                 if ($protocol == Protocol::ACTIVITYPUB) {
88                         ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $contact['uid']);
89                 }
90
91                 if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) {
92                         if ($duplex) {
93                                 $newRelation = Contact::FRIEND;
94                         } else {
95                                 $newRelation = Contact::FOLLOWER;
96                         }
97
98                         if ($newRelation != Contact::FOLLOWER) {
99                                 $writable = 1;
100                         }
101                 }
102
103                 $fields = [
104                         'name-date' => DateTimeFormat::utcNow(),
105                         'uri-date'  => DateTimeFormat::utcNow(),
106                         'blocked'   => false,
107                         'pending'   => false,
108                         'protocol'  => $protocol,
109                         'writable'  => $writable,
110                         'hidden'    => $hidden ?? $contact['hidden'],
111                         'rel'       => $newRelation,
112                 ];
113                 $this->dba->update('contact', $fields, ['id' => $contact['id']]);
114
115                 array_merge($contact, $fields);
116
117                 if ($newRelation == Contact::FRIEND) {
118                         if ($protocol == Protocol::DIASPORA) {
119                                 $ret = Diaspora::sendShare(User::getById($contact['uid']), $contact);
120                                 $this->logger->info('share returns', ['return' => $ret]);
121                         } elseif ($protocol == Protocol::ACTIVITYPUB) {
122                                 ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $contact['uid']);
123                         }
124                 }
125
126                 return $this->intro->delete($this);
127         }
128
129         /**
130          * Silently ignores the introduction, hides it from notifications and prevents the remote contact from submitting
131          * additional follow requests.
132          *
133          * @return bool
134          * @throws \Exception
135          */
136         public function ignore()
137         {
138                 $this->ignore = true;
139
140                 return $this->intro->update($this);
141         }
142
143         /**
144          * Discards the introduction and sends a rejection message to AP contacts.
145          *
146          * @return bool
147          * @throws HTTPException\InternalServerErrorException
148          * @throws HTTPException\NotFoundException
149          * @throws \ImagickException
150          */
151         public function discard()
152         {
153                 // If it is a friend suggestion, the contact is not a new friend but an existing friend
154                 // that should not be deleted.
155                 if (!$this->fid) {
156                         // When the contact entry had been created just for that intro, we want to get rid of it now
157                         $condition = ['id' => $this->{'contact-id'}, 'uid' => $this->uid,
158                                 'self' => false, 'pending' => true, 'rel' => [0, Contact::FOLLOWER]];
159                         if ($this->dba->exists('contact', $condition)) {
160                                 Contact::remove($this->{'contact-id'});
161                         } else {
162                                 $this->dba->update('contact', ['pending' => false], ['id' => $this->{'contact-id'}]);
163                         }
164                 }
165
166                 $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]);
167                 if (!empty($contact)) {
168                         if (!empty($contact['protocol'])) {
169                                 $protocol = $contact['protocol'];
170                         } else {
171                                 $protocol = $contact['network'];
172                         }
173
174                         if ($protocol == Protocol::ACTIVITYPUB) {
175                                 ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']);
176                         }
177                 }
178
179                 return $this->intro->delete($this);
180         }
181 }