3 * @copyright Copyright (C) 2010-2022, the Friendica project
5 * @license GNU AGPL version 3 or any later version
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.
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.
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/>.
22 namespace Friendica\Model\Contact;
24 use Friendica\Contact\Introduction\Entity;
25 use Friendica\Core\Protocol;
27 use Friendica\Network\HTTPException;
28 use Friendica\Model\Contact;
29 use Friendica\Model\User;
30 use Friendica\Protocol\ActivityPub;
31 use Friendica\Protocol\Diaspora;
32 use Friendica\Util\DateTimeFormat;
37 * Confirms a follow request and sends a notice to the remote contact.
39 * @param Entity\Introduction $introduction
40 * @param bool $duplex Is it a follow back?
41 * @param bool|null $hidden Should this contact be hidden? null = no change
43 * @throws HTTPException\InternalServerErrorException
44 * @throws HTTPException\NotFoundException
45 * @throws \ImagickException
47 public static function confirm(Entity\Introduction $introduction, bool $duplex = false, ?bool $hidden = null): void
49 DI::logger()->info('Confirming follower', ['cid' => $introduction->cid]);
51 $contact = Contact::selectFirst([], ['id' => $introduction->cid, 'uid' => $introduction->uid]);
54 throw new HTTPException\NotFoundException('Contact record not found.');
57 $newRelation = $contact['rel'];
58 $writable = $contact['writable'];
60 if (!empty($contact['protocol'])) {
61 $protocol = $contact['protocol'];
63 $protocol = $contact['network'];
66 if ($protocol == Protocol::ACTIVITYPUB) {
67 ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $contact['uid']);
70 if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) {
72 $newRelation = Contact::FRIEND;
74 $newRelation = Contact::FOLLOWER;
77 if ($newRelation != Contact::FOLLOWER) {
83 'name-date' => DateTimeFormat::utcNow(),
84 'uri-date' => DateTimeFormat::utcNow(),
87 'protocol' => $protocol,
88 'writable' => $writable,
89 'hidden' => $hidden ?? $contact['hidden'],
90 'rel' => $newRelation,
92 Contact::update($fields, ['id' => $contact['id']]);
94 array_merge($contact, $fields);
96 if ($newRelation == Contact::FRIEND) {
97 if ($protocol == Protocol::DIASPORA) {
98 $ret = Diaspora::sendShare(User::getById($contact['uid']), $contact);
99 DI::logger()->info('share returns', ['return' => $ret]);
100 } elseif ($protocol == Protocol::ACTIVITYPUB) {
101 ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $contact['uid']);
107 * Discards the introduction and sends a rejection message to AP contacts.
109 * @param Entity\Introduction $introduction
111 * @throws HTTPException\InternalServerErrorException
112 * @throws \ImagickException
114 public static function discard(Entity\Introduction $introduction): void
116 $contact = Contact::selectFirst([], ['id' => $introduction->cid, 'uid' => $introduction->uid]);
117 if (!empty($contact)) {
118 if (!empty($contact['protocol'])) {
119 $protocol = $contact['protocol'];
121 $protocol = $contact['network'];
124 if ($protocol == Protocol::ACTIVITYPUB) {
125 ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']);