3 namespace Friendica\Model;
5 use Friendica\BaseModel;
6 use Friendica\Core\Protocol;
7 use Friendica\Database\Database;
8 use Friendica\Network\HTTPException;
9 use Friendica\Protocol\ActivityPub;
10 use Friendica\Protocol\Diaspora;
11 use Friendica\Repository;
12 use Friendica\Util\DateTimeFormat;
13 use Psr\Log\LoggerInterface;
18 * @property int contact-id
19 * @property bool knowyou
20 * @property bool duplex
21 * @property string note
22 * @property string hash
23 * @property string datetime
24 * @property bool blocked
25 * @property bool ignore
27 final class Introduction extends BaseModel
29 /** @var Repository\Introduction */
32 public function __construct(Database $dba, LoggerInterface $logger, Repository\Introduction $intro, array $data = [])
34 parent::__construct($dba, $logger, $data);
36 $this->intro = $intro;
40 * Confirms a follow request and sends a notice to the remote contact.
42 * @param bool $duplex Is it a follow back?
43 * @param bool|null $hidden Should this contact be hidden? null = no change
45 * @throws HTTPException\InternalServerErrorException
46 * @throws HTTPException\NotFoundException
47 * @throws \ImagickException
49 public function confirm(bool $duplex = false, bool $hidden = null)
51 $this->logger->info('Confirming follower', ['cid' => $this->{'contact-id'}]);
53 $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]);
56 throw new HTTPException\NotFoundException('Contact record not found.');
59 $newRelation = $contact['rel'];
60 $writable = $contact['writable'];
62 if (!empty($contact['protocol'])) {
63 $protocol = $contact['protocol'];
65 $protocol = $contact['network'];
68 if ($protocol == Protocol::ACTIVITYPUB) {
69 ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $contact['uid']);
72 if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) {
74 $newRelation = Contact::FRIEND;
76 $newRelation = Contact::FOLLOWER;
79 if ($newRelation != Contact::FOLLOWER) {
85 'name-date' => DateTimeFormat::utcNow(),
86 'uri-date' => DateTimeFormat::utcNow(),
89 'protocol' => $protocol,
90 'writable' => $writable,
91 'hidden' => $hidden ?? $contact['hidden'],
92 'rel' => $newRelation,
94 $this->dba->update('contact', $fields, ['id' => $contact['id']]);
96 array_merge($contact, $fields);
98 if ($newRelation == Contact::FRIEND) {
99 if ($protocol == Protocol::DIASPORA) {
100 $ret = Diaspora::sendShare(Contact::getById($contact['uid']), $contact);
101 $this->logger->info('share returns', ['return' => $ret]);
102 } elseif ($protocol == Protocol::ACTIVITYPUB) {
103 ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $contact['uid']);
107 return $this->intro->delete($this);
111 * Silently ignores the introduction, hides it from notifications and prevents the remote contact from submitting
112 * additional follow requests.
117 public function ignore()
119 $this->ignore = true;
121 return $this->intro->update($this);
125 * Discards the introduction and sends a rejection message to AP contacts.
128 * @throws HTTPException\InternalServerErrorException
129 * @throws HTTPException\NotFoundException
130 * @throws \ImagickException
132 public function discard()
134 // If it is a friend suggestion, the contact is not a new friend but an existing friend
135 // that should not be deleted.
137 // When the contact entry had been created just for that intro, we want to get rid of it now
138 $condition = ['id' => $this->{'contact-id'}, 'uid' => $this->uid,
139 'self' => false, 'pending' => true, 'rel' => [0, Contact::FOLLOWER]];
140 if ($this->dba->exists('contact', $condition)) {
141 Contact::remove($this->{'contact-id'});
143 $this->dba->update('contact', ['pending' => false], ['id' => $this->{'contact-id'}]);
147 $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]);
150 throw new HTTPException\NotFoundException('Contact record not found.');
153 if (!empty($contact['protocol'])) {
154 $protocol = $contact['protocol'];
156 $protocol = $contact['network'];
159 if ($protocol == Protocol::ACTIVITYPUB) {
160 ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']);
163 return $this->intro->delete($this);