diff --git a/src/Model/Introduction.php b/src/Model/Introduction.php new file mode 100644 index 000000000..127765c0c --- /dev/null +++ b/src/Model/Introduction.php @@ -0,0 +1,156 @@ +logger->info('Confirming follower', ['cid' => $this->{'contact-id'}]); + + $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); + + if (!$contact) { + throw new HTTPException\NotFoundException('Contact record not found.'); + } + + $new_relation = $contact['rel']; + $writable = $contact['writable']; + + if (!empty($contact['protocol'])) { + $protocol = $contact['protocol']; + } else { + $protocol = $contact['network']; + } + + if ($protocol == Protocol::ACTIVITYPUB) { + ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $contact['uid']); + } + + if (in_array($protocol, [Protocol::DIASPORA, Protocol::ACTIVITYPUB])) { + if ($duplex) { + $new_relation = Contact::FRIEND; + } else { + $new_relation = Contact::FOLLOWER; + } + + if ($new_relation != Contact::FOLLOWER) { + $writable = 1; + } + } + + $fields = [ + 'name-date' => DateTimeFormat::utcNow(), + 'uri-date' => DateTimeFormat::utcNow(), + 'blocked' => false, + 'pending' => false, + 'protocol' => $protocol, + 'writable' => $writable, + 'hidden' => $hidden ?? $contact['hidden'], + 'rel' => $new_relation, + ]; + $this->dba->update('contact', $fields, ['id' => $contact['id']]); + + array_merge($contact, $fields); + + if ($new_relation == Contact::FRIEND) { + if ($protocol == Protocol::DIASPORA) { + $ret = Diaspora::sendShare(User::getById($contact['uid']), $contact); + $this->logger->info('share returns', ['return' => $ret]); + } elseif ($protocol == Protocol::ACTIVITYPUB) { + ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $contact['uid']); + } + } + + $this->delete(); + } + + /** + * Silently ignores the introduction, hides it from notifications and prevents the remote contact from submitting + * additional follow requests. + * + * Chainable + * + * @return Introduction + * @throws \Exception + */ + public function ignore() + { + $this->dba->update('intro', ['ignore' => true], ['id' => $this->id]); + + return $this; + } + + /** + * Discards the introduction and sends a rejection message to AP contacts. + * + * @throws HTTPException\InternalServerErrorException + * @throws HTTPException\NotFoundException + * @throws \ImagickException + */ + public function discard() + { + // If it is a friend suggestion, the contact is not a new friend but an existing friend + // that should not be deleted. + if (!$this->fid) { + // When the contact entry had been created just for that intro, we want to get rid of it now + $condition = ['id' => $this->{'contact-id'}, 'uid' => $this->uid, + 'self' => false, 'pending' => true, 'rel' => [0, Contact::FOLLOWER]]; + if ($this->dba->exists('contact', $condition)) { + Contact::remove($this->{'contact-id'}); + } else { + $this->dba->update('contact', ['pending' => false], ['id' => $this->{'contact-id'}]); + } + } + + $contact = Contact::selectFirst([], ['id' => $this->{'contact-id'}, 'uid' => $this->uid]); + + if (!$contact) { + throw new HTTPException\NotFoundException('Contact record not found.'); + } + + if (!empty($contact['protocol'])) { + $protocol = $contact['protocol']; + } else { + $protocol = $contact['network']; + } + + if ($protocol == Protocol::ACTIVITYPUB) { + ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']); + } + + $this->delete(); + } +}