+ /**
+ * Add relay servers to the list of inboxes
+ *
+ * @param array $inboxes
+ * @return array inboxes with added relay servers
+ */
+ public static function addRelayServerInboxes(array $inboxes = [])
+ {
+ $contacts = DBA::select('apcontact', ['inbox'],
+ ["`type` = ? AND `url` IN (SELECT `url` FROM `contact` WHERE `uid` = ? AND `rel` IN (?, ?))",
+ 'Application', 0, Contact::FOLLOWER, Contact::FRIEND]);
+ while ($contact = DBA::fetch($contacts)) {
+ $inboxes[] = $contact['inbox'];
+ }
+ DBA::close($contacts);
+
+ return $inboxes;
+ }
+
+ /**
+ * Subscribe to a relay
+ *
+ * @param string $url Subscribe actor url
+ * @return bool success
+ */
+ public static function sendRelayFollow(string $url)
+ {
+ $contact = Contact::getByURL($url);
+ if (empty($contact)) {
+ return false;
+ }
+
+ $activity_id = ActivityPub\Transmitter::activityIDFromContact($contact['id']);
+ $success = ActivityPub\Transmitter::sendActivity('Follow', $url, 0, $activity_id);
+ if ($success) {
+ $rel = $contact['rel'] == Contact::SHARING ? Contact::FRIEND : Contact::FOLLOWER;
+ DBA::update('contact', ['rel' => $rel], ['id' => $contact['id']]);
+ }
+
+ return $success;
+ }
+
+ /**
+ * Unsubscribe from a relay
+ *
+ * @param string $url Subscribe actor url
+ * @param bool $force Set the relay status as non follower even if unsubscribe hadn't worked
+ * @return bool success
+ */
+ public static function sendRelayUndoFollow(string $url, bool $force = false)
+ {
+ $contact = Contact::getByURL($url);
+ if (empty($contact)) {
+ return false;
+ }
+
+ $success = self::sendContactUndo($url, $contact['id'], 0);
+ if ($success || $force) {
+ $rel = $contact['rel'] == Contact::FRIEND ? Contact::SHARING : Contact::NOTHING;
+ DBA::update('contact', ['rel' => $rel], ['id' => $contact['id']]);
+ }
+
+ return $success;
+ }
+