]> git.mxchange.org Git - friendica.git/commitdiff
Fix follow/unfollow
authorMichael <heluecht@pirati.ca>
Wed, 31 Jul 2024 04:37:17 +0000 (04:37 +0000)
committerMichael <heluecht@pirati.ca>
Fri, 2 Aug 2024 05:50:01 +0000 (05:50 +0000)
23 files changed:
src/Content/Item.php
src/Model/Circle.php
src/Model/Contact.php
src/Model/Item.php
src/Model/User.php
src/Module/Api/Mastodon/Accounts/Block.php
src/Module/Api/Mastodon/Accounts/Lists.php
src/Module/Api/Mastodon/Accounts/Note.php
src/Module/Api/Mastodon/Accounts/Unfollow.php
src/Module/Api/Mastodon/FollowRequests.php
src/Module/Api/Mastodon/Timelines/ListTimeline.php
src/Module/Api/Twitter/DirectMessages/NewDM.php
src/Module/Api/Twitter/DirectMessagesEndpoint.php
src/Module/Api/Twitter/Friendships/Destroy.php
src/Module/Api/Twitter/Friendships/Show.php
src/Module/Contact.php
src/Module/Contact/Follow.php
src/Module/Contact/Profile.php
src/Module/Contact/Revoke.php
src/Module/Contact/Unfollow.php
src/Util/HTTPSignature.php
src/Worker/Contact/RevokeFollow.php
src/Worker/Contact/Unfollow.php

index 28d980473a73201b6511297d85296b7ed45ac5ce..6befe978ff4edf085957886c4b2b588c480ec19f 100644 (file)
@@ -547,9 +547,9 @@ class Item
                        $item['private'] = $private_group ? ItemModel::PRIVATE : ItemModel::UNLISTED;
 
                        if ($only_to_group) {
-                               $cdata = Contact::getPublicAndUserContactID($group_contact['id'], $item['uid']);
-                               if (!empty($cdata['user'])) {
-                                       $item['owner-id'] = $cdata['user'];
+                               $pcid = Contact::getPublicContactId($group_contact['id'], $item['uid']);
+                               if ($pcid) {
+                                       $item['owner-id'] = $pcid;
                                        unset($item['owner-link']);
                                        unset($item['owner-name']);
                                        unset($item['owner-avatar']);
index d5fa70fda99c62367190269b46d9e43a367f9a0f..af201030403993d07ffca68aff302b093c094cab 100644 (file)
@@ -290,12 +290,12 @@ class Circle
                        throw new HTTPException\NotFoundException('Circle not found.');
                }
 
-               $cdata = Contact::getPublicAndUserContactID($cid, $circle['uid']);
-               if (empty($cdata['user'])) {
+               $ucid = Contact::getUserContactId($cid, $circle['uid']);
+               if (!$ucid) {
                        throw new HTTPException\NotFoundException('Invalid contact.');
                }
 
-               return DBA::insert('group_member', ['gid' => $gid, 'contact-id' => $cdata['user']], Database::INSERT_IGNORE);
+               return DBA::insert('group_member', ['gid' => $gid, 'contact-id' => $ucid], Database::INSERT_IGNORE);
        }
 
        /**
@@ -318,12 +318,12 @@ class Circle
                        throw new HTTPException\NotFoundException('Circle not found.');
                }
 
-               $cdata = Contact::getPublicAndUserContactID($cid, $circle['uid']);
-               if (empty($cdata['user'])) {
+               $ucid = Contact::getUserContactId($cid, $circle['uid']);
+               if (!$ucid) {
                        throw new HTTPException\NotFoundException('Invalid contact.');
                }
 
-               return DBA::delete('group_member', ['gid' => $gid, 'contact-id' => $cid]);
+               return DBA::delete('group_member', ['gid' => $gid, 'contact-id' => $ucid]);
        }
 
        /**
@@ -347,12 +347,12 @@ class Circle
                }
 
                foreach ($contacts as $cid) {
-                       $cdata = Contact::getPublicAndUserContactID($cid, $circle['uid']);
-                       if (empty($cdata['user'])) {
+                       $ucid = Contact::getUserContactId($cid, $circle['uid']);
+                       if (!$ucid) {
                                throw new HTTPException\NotFoundException('Invalid contact.');
                        }
 
-                       DBA::insert('group_member', ['gid' => $gid, 'contact-id' => $cdata['user']], Database::INSERT_IGNORE);
+                       DBA::insert('group_member', ['gid' => $gid, 'contact-id' => $ucid], Database::INSERT_IGNORE);
                }
        }
 
@@ -379,12 +379,12 @@ class Circle
                $contactIds = [];
 
                foreach ($contacts as $cid) {
-                       $cdata = Contact::getPublicAndUserContactID($cid, $circle['uid']);
-                       if (empty($cdata['user'])) {
+                       $ucid = Contact::getUserContactId($cid, $circle['uid']);
+                       if (!$ucid) {
                                throw new HTTPException\NotFoundException('Invalid contact.');
                        }
 
-                       $contactIds[] = $cdata['user'];
+                       $contactIds[] = $ucid;
                }
 
                // Return status of deletion
index cecd505bde5ad55d8bf405dc98a318315d6e1834..bd9273ea17db310311cc94423e71295ef7d05dd1 100644 (file)
@@ -444,12 +444,12 @@ class Contact
                        return false;
                }
 
-               $cdata = self::getPublicAndUserContactID($cid, $uid);
-               if (empty($cdata['user'])) {
+               $ucid = self::getUserContactId($cid, $uid);
+               if (!$ucid) {
                        return false;
                }
 
-               $condition = ['id' => $cdata['user'], 'rel' => [self::FOLLOWER, self::FRIEND]];
+               $condition = ['id' => $ucid, 'rel' => [self::FOLLOWER, self::FRIEND]];
                if ($strict) {
                        $condition = array_merge($condition, ['pending' => false, 'readonly' => false, 'blocked' => false]);
                }
@@ -495,12 +495,12 @@ class Contact
                        return false;
                }
 
-               $cdata = self::getPublicAndUserContactID($cid, $uid);
-               if (empty($cdata['user'])) {
+               $ucid = self::getUserContactId($cid, $uid);
+               if (!$ucid) {
                        return false;
                }
 
-               $condition = ['id' => $cdata['user'], 'rel' => [self::SHARING, self::FRIEND]];
+               $condition = ['id' => $ucid, 'rel' => [self::SHARING, self::FRIEND]];
                if ($strict) {
                        $condition = array_merge($condition, ['pending' => false, 'readonly' => false, 'blocked' => false]);
                }
@@ -671,6 +671,32 @@ class Contact
                return ['public' => $pcid, 'user' => $ucid];
        }
 
+       /**
+        * Returns the public contact id of a provided contact id
+        *
+        * @param integer $cid
+        * @param integer $uid
+        * @return integer
+        */
+       public static function getPublicContactId(int $cid, int $uid): int
+       {
+               $contact = DBA::selectFirst('account-user-view', ['pid'], ['id' => $cid, 'uid' => [0, $uid]]);
+               return $contact['pid'] ?? 0;
+       }
+
+       /**
+        * Returns the user contact id of a provided contact id
+        *
+        * @param integer $cid
+        * @param integer $uid
+        * @return integer
+        */
+       public static function getUserContactId(int $cid, int $uid): int
+       {
+               $data = self::getPublicAndUserContactID($cid, $uid);
+               return $data['user'] ?? 0;
+       }
+
        /**
         * Helper function for "getPublicAndUserContactID"
         *
@@ -968,13 +994,13 @@ class Contact
                }
 
                if (in_array($contact['rel'], [self::SHARING, self::FRIEND])) {
-                       $cdata = self::getPublicAndUserContactID($contact['id'], $contact['uid']);
-                       if (!empty($cdata['public'])) {
-                               Worker::add(Worker::PRIORITY_HIGH, 'Contact\Unfollow', $cdata['public'], $contact['uid']);
+                       $pcid = self::getPublicContactId($contact['id'], $contact['uid']);
+                       if ($pcid) {
+                               Worker::add(Worker::PRIORITY_HIGH, 'Contact\Unfollow', $pcid, $contact['uid']);
                        }
                }
 
-               self::removeSharer($contact);
+               self::removeSharer($contact, false);
        }
 
        /**
@@ -998,13 +1024,13 @@ class Contact
                }
 
                if (in_array($contact['rel'], [self::FOLLOWER, self::FRIEND])) {
-                       $cdata = self::getPublicAndUserContactID($contact['id'], $contact['uid']);
-                       if (!empty($cdata['public'])) {
-                               Worker::add(Worker::PRIORITY_HIGH, 'Contact\RevokeFollow', $cdata['public'], $contact['uid']);
+                       $pcid = self::getPublicContactId($contact['id'], $contact['uid']);
+                       if ($pcid) {
+                               Worker::add(Worker::PRIORITY_HIGH, 'Contact\RevokeFollow', $pcid, $contact['uid']);
                        }
                }
 
-               self::removeFollower($contact);
+               self::removeFollower($contact, false);
        }
 
        /**
@@ -1025,14 +1051,14 @@ class Contact
                        throw new \InvalidArgumentException('Unexpected public contact record');
                }
 
-               $cdata = self::getPublicAndUserContactID($contact['id'], $contact['uid']);
+               $pcid = self::getPublicContactId($contact['id'], $contact['uid']);
 
-               if (in_array($contact['rel'], [self::SHARING, self::FRIEND]) && !empty($cdata['public'])) {
-                       Worker::add(Worker::PRIORITY_HIGH, 'Contact\Unfollow', $cdata['public'], $contact['uid']);
+               if (in_array($contact['rel'], [self::SHARING, self::FRIEND]) && $pcid) {
+                       Worker::add(Worker::PRIORITY_HIGH, 'Contact\Unfollow', $pcid, $contact['uid']);
                }
 
-               if (in_array($contact['rel'], [self::FOLLOWER, self::FRIEND]) && !empty($cdata['public'])) {
-                       Worker::add(Worker::PRIORITY_HIGH, 'Contact\RevokeFollow', $cdata['public'], $contact['uid']);
+               if (in_array($contact['rel'], [self::FOLLOWER, self::FRIEND]) && $pcid) {
+                       Worker::add(Worker::PRIORITY_HIGH, 'Contact\RevokeFollow', $pcid, $contact['uid']);
                }
 
                self::remove($contact['id']);
@@ -3009,6 +3035,10 @@ class Contact
         */
        public static function getProtocol(string $url, string $network): string
        {
+               if (self::isLocal($url)) {
+                       return Protocol::ACTIVITYPUB;
+               }
+
                if ($network != Protocol::DFRN) {
                        return $network;
                }
@@ -3400,16 +3430,21 @@ class Contact
         * Update the local relationship when a local user loses a follower
         *
         * @param array $contact User-specific contact (uid != 0) array
+        * @param bool  $delete  Delete if set, otherwise set relation to "nothing" when contact had been a follower
         * @return void
         * @throws HTTPException\InternalServerErrorException
         * @throws \ImagickException
         */
-       public static function removeFollower(array $contact)
+       public static function removeFollower(array $contact, bool $delete = true)
        {
                if (in_array($contact['rel'] ?? [], [self::FRIEND, self::SHARING])) {
                        self::update(['rel' => self::SHARING], ['id' => $contact['id']]);
                } elseif (!empty($contact['id'])) {
-                       self::remove($contact['id']);
+                       if ($delete) {
+                               self::remove($contact['id']);
+                       } else {
+                               self::update(['rel' => self::NOTHING, 'pending' => false], ['id' => $contact['id']]);
+                       }
                } else {
                        DI::logger()->info('Couldn\'t remove follower because of invalid contact array', ['contact' => $contact]);
                        return;
@@ -3419,9 +3454,9 @@ class Contact
 
                self::clearFollowerFollowingEndpointCache($contact['uid']);
 
-               $cdata = self::getPublicAndUserContactID($contact['id'], $contact['uid']);
-               if (!empty($cdata['public'])) {
-                       DI::notification()->deleteForUserByVerb($contact['uid'], Activity::FOLLOW, ['actor-id' => $cdata['public']]);
+               $pcid = self::getPublicContactId($contact['id'], $contact['uid']);
+               if ($pcid) {
+                       DI::notification()->deleteForUserByVerb($contact['uid'], Activity::FOLLOW, ['actor-id' => $pcid]);
                }
        }
 
@@ -3430,14 +3465,19 @@ class Contact
         * Removes the contact for sharing-only protocols (feed and mail).
         *
         * @param array $contact User-specific contact (uid != 0) array
+        * @param bool  $delete  Delete if set, otherwise set relation to "nothing" when contact had been a sharer
         * @throws HTTPException\InternalServerErrorException
         */
-       public static function removeSharer(array $contact)
+       public static function removeSharer(array $contact, bool $delete = true)
        {
                self::clearFollowerFollowingEndpointCache($contact['uid']);
 
-               if ($contact['rel'] == self::SHARING || in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) {
-                       self::remove($contact['id']);
+               if (in_array($contact['rel'], [self::SHARING, self::NOTHING]) || in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) {
+                       if ($delete) {
+                               self::remove($contact['id']);
+                       } else {
+                               self::update(['rel' => self::NOTHING, 'pending' => false], ['id' => $contact['id']]);
+                       }
                } else {
                        self::update(['rel' => self::FOLLOWER, 'pending' => false], ['id' => $contact['id']]);
                }
index 9910da7f6e185c39d2c6b1ad894929d2b5edfe88..0da392df636e830c0db5c5533da04f70aae8c8cc 100644 (file)
@@ -556,9 +556,9 @@ class Item
                }
 
                if (!empty($item['causer-id']) && Contact::isSharing($item['causer-id'], $item['uid'], true)) {
-                       $cdata = Contact::getPublicAndUserContactID($item['causer-id'], $item['uid']);
-                       if (!empty($cdata['user'])) {
-                               return $cdata['user'];
+                       $ucid = Contact::getUserContactId($item['causer-id'], $item['uid']);
+                       if ($ucid) {
+                               return $ucid;
                        }
                }
 
@@ -2632,12 +2632,12 @@ class Item
                        return;
                }
 
-               $cdata = Contact::getPublicAndUserContactID($item['author-id'], $item['uid']);
-               if (empty($cdata['user']) || ($cdata['user'] != $item['contact-id'])) {
+               $ucid = Contact::getUserContactId($item['author-id'], $item['uid']);
+               if (!$ucid || ($ucid != $item['contact-id'])) {
                        return;
                }
 
-               if (!DBA::exists('contact', ['id' => $cdata['user'], 'remote_self' => LocalRelationship::MIRROR_NATIVE_RESHARE])) {
+               if (!DBA::exists('contact', ['id' => $ucid, 'remote_self' => LocalRelationship::MIRROR_NATIVE_RESHARE])) {
                        return;
                }
 
index 551699ef6e565d0bc7eac31c07b9579444430475..5deccdef34c9aa6c1f1b403b47293423a6c32d56 100644 (file)
@@ -412,6 +412,29 @@ class User
                return 0;
        }
 
+       /**
+        * Returns the user id of a given contact id
+        *
+        * @param int $cid
+        *
+        * @return integer user id
+        * @throws Exception
+        */
+       public static function getIdForContactId(int $cid): int
+       {
+               $account = Contact::selectFirstAccountUser(['pid', 'self', 'uid'], ['id' => $cid]);
+               if (empty($account['pid'])) {
+                       return 0;
+               }
+
+               if ($account['self']) {
+                       return $account['uid'];
+               }
+
+               $self = Contact::selectFirstAccountUser(['uid'], ['pid' => $cid, 'self' => true]);
+               return $self['uid'] ?? 0;
+       }
+
        /**
         * Get a user based on its email
         *
index 4c5abc247519261ce07870145593026d0f3701df..43cf322553ea114b4ad9562b694f6d920e1df0b0 100644 (file)
@@ -43,9 +43,9 @@ class Block extends BaseApi
 
                Contact\User::setBlocked($this->parameters['id'], $uid, true);
 
-               $cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid);
-               if (!empty($cdata['user'])) {
-                       $contact = Contact::getById($cdata['user']);
+               $ucid = Contact::getUserContactId($this->parameters['id'], $uid);
+               if ($ucid) {
+                       $contact = Contact::getById($ucid);
                        if (!empty($contact)) {
                                // Mastodon-expected behavior: relationship is severed on block
                                Contact::terminateFriendship($contact);
index 6a1538630789ee165885dafef3458d4f1a2b4408..3de59606123276f6cf0b36e87bfa7f9c28f1be0b 100644 (file)
@@ -51,9 +51,9 @@ class Lists extends BaseApi
 
                $lists = [];
 
-               $cdata = Contact::getPublicAndUserContactID($id, $uid);
-               if (!empty($cdata['user'])) {
-                       $circles = DBA::select('group_member', ['gid'], ['contact-id' => $cdata['user']]);
+               $ucid = Contact::getUserContactId($id, $uid);
+               if ($ucid) {
+                       $circles = DBA::select('group_member', ['gid'], ['contact-id' => $ucid]);
                        while ($circle = DBA::fetch($circles)) {
                                $lists[] = DI::mstdnList()->createFromCircleId($circle['gid']);
                        }
index a101c1519e1fc0c188f7392905828ad761b5d34e..dbb5c6e03347606e89f49cc0f77e13f3cf6a0206 100644 (file)
@@ -45,12 +45,12 @@ class Note extends BaseApi
                        'comment' => '',
                ], $request);
 
-               $cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid);
-               if (empty($cdata['user'])) {
+               $ucid = Contact::getUserContactId($this->parameters['id'], $uid);
+               if (!$ucid) {
                        $this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
                }
 
-               Contact::update(['info' => $request['comment']], ['id' => $cdata['user']]);
+               Contact::update(['info' => $request['comment']], ['id' => $ucid]);
 
                $this->jsonExit(DI::mstdnRelationship()->createFromContactId($this->parameters['id'], $uid)->toArray());
        }
index b898f85f18d1dbb89e4eb21598e75d41793e88ae..1c8c5a8921b20b8b1708f6b0067756e57e6385a1 100644 (file)
@@ -40,12 +40,12 @@ class Unfollow extends BaseApi
                        $this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
                }
 
-               $cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid);
-               if (empty($cdata['user'])) {
+               $ucid = Contact::getUserContactId($this->parameters['id'], $uid);
+               if (!$ucid) {
                        $this->logAndJsonError(404, $this->errorFactory->RecordNotFound());
                }
 
-               $contact = Contact::getById($cdata['user']);
+               $contact = Contact::getById($ucid);
 
                Contact::unfollow($contact);
 
index 1a6c247a6ddc38a7c8fda11270a931a38cd18823..5d9ad2bdfda7358d6cbac13645f93248ef764a41 100644 (file)
@@ -21,7 +21,6 @@
 
 namespace Friendica\Module\Api\Mastodon;
 
-use Friendica\Core\System;
 use Friendica\DI;
 use Friendica\Model\Contact;
 use Friendica\Module\BaseApi;
@@ -47,12 +46,12 @@ class FollowRequests extends BaseApi
                $this->checkAllowedScope(self::SCOPE_FOLLOW);
                $uid = self::getCurrentUserID();
 
-               $cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid);
-               if (empty($cdata['user'])) {
+               $ucid = Contact::getUserContactId($this->parameters['id'], $uid);
+               if (!$ucid) {
                        throw new HTTPException\NotFoundException('Contact not found');
                }
 
-               $introduction = DI::intro()->selectForContact($cdata['user']);
+               $introduction = DI::intro()->selectForContact($ucid);
 
                $contactId = $introduction->cid;
 
index ea44ee821db62e9ecea1ead87effa4dd02d74ba7..2dc0b7bb6352e90f38a89439ba1960b8062bc492 100644 (file)
@@ -110,8 +110,7 @@ class ListTimeline extends BaseApi
 
        private function getStatusesForGroup(int $uid, array $request): array
        {
-               $cdata = Contact::getPublicAndUserContactID((int)substr($this->parameters['id'], 6), $uid);
-               $cid = $cdata['public'];
+               $cid = Contact::getPublicContactId((int)substr($this->parameters['id'], 6), $uid);
 
                $condition = ["(`uid` = ? OR (`uid` = ? AND NOT `global`))", 0, $uid];
 
index 29226c9a9c4c235283519bded38408b59063875d..49764304d3802065398829b980795e911d6dafa6 100644 (file)
@@ -81,9 +81,9 @@ class NewDM extends BaseApi
                        }
                }
 
-               $cdata = Contact::getPublicAndUserContactID($cid, $uid);
+               $ucid = Contact::getUserContactId($cid, $uid);
 
-               $id = Mail::send($uid, $cdata['user'], $request['text'], $sub, $replyto);
+               $id = Mail::send($uid, $ucid, $request['text'], $sub, $replyto);
 
                if ($id > -1) {
                        $ret = $this->directMessage->createFromMailId($id, $uid, $this->getRequestValue($request, 'getText', ''));
index ec4ef65411f0892760576bf808904dd0aeaffce6..b94393eabfa40d01b98393ff9e741307df94f221 100644 (file)
@@ -88,9 +88,9 @@ abstract class DirectMessagesEndpoint extends BaseApi
 
                $cid = BaseApi::getContactIDForSearchterm($this->getRequestValue($request, 'screen_name', ''), $this->getRequestValue($request, 'profileurl', ''), $this->getRequestValue($request, 'user_id', 0), 0);
                if (!empty($cid)) {
-                       $cdata = Contact::getPublicAndUserContactID($cid, $uid);
-                       if (!empty($cdata['user'])) {
-                               $condition = DBA::mergeConditions($condition, ["`contact-id` = ?", $cdata['user']]);
+                       $ucid = Contact::getUserContactId($cid, $uid);
+                       if ($ucid) {
+                               $condition = DBA::mergeConditions($condition, ["`contact-id` = ?", $ucid]);
                        }
                }
 
index 619fbf33862dbb80d0c4913e03326228b99497aa..e02448f765d6b429794b6cf037b799b25dae37f0 100644 (file)
@@ -71,13 +71,13 @@ class Destroy extends ContactEndpoint
                }
 
                // Get Contact by given id
-               $cdata = Contact::getPublicAndUserContactID($contact_id, $uid);
-               if (!empty($cdata['user'])) {
+               $ucid = Contact::getUserContactId($contact_id, $uid);
+               if (!$ucid) {
                        Logger::notice(BaseApi::LOG_PREFIX . 'Not following contact', ['module' => 'api', 'action' => 'friendships_destroy']);
                        throw new HTTPException\NotFoundException('Not following Contact');
                }
 
-               $contact = Contact::getById($cdata['user']);
+               $contact = Contact::getById($ucid);
                $user    = $this->twitterUser->createFromContactId($contact_id, $uid, true)->toArray();
 
                try {
index 23af79d2ae0b66db2c2a433be39ae890af14cf92..304b83609775b60c0dfb1f424e0a5e57e2546d92 100644 (file)
@@ -55,9 +55,9 @@ class Show extends ContactEndpoint
                $following = false;
 
                if ($source_cid == Contact::getPublicIdByUserId($uid)) {
-                       $cdata = Contact::getPublicAndUserContactID($target_cid, $uid);
-                       if (!empty($cdata['user'])) {
-                               $usercontact = Contact::getById($cdata['user'], ['rel']);
+                       $ucid = Contact::getUserContactId($target_cid, $uid);
+                       if ($ucid) {
+                               $usercontact = Contact::getById($ucid, ['rel']);
                                switch ($usercontact['rel'] ?? Contact::NOTHING) {
                                        case Contact::FOLLOWER:
                                                $follower  = true;
index d58fde062378c812960ba2be613ff72b34711dc0..1455bd5e4f06769b46d4636ff1d530d233952719 100644 (file)
@@ -253,7 +253,7 @@ class Contact extends BaseModule
                                $sql_extra = " AND `archive` AND NOT `blocked` AND NOT `pending`";
                                break;
                        case 'pending':
-                               $sql_extra = " AND `pending` AND NOT `archive` AND NOT `failed` AND ((`rel` = ?)
+                               $sql_extra = " AND `pending` AND NOT `archive` AND ((`rel` = ?)
                                        OR `id` IN (SELECT `contact-id` FROM `intro` WHERE `intro`.`uid` = ? AND NOT `ignore`))";
                                $sql_values[] = Model\Contact::SHARING;
                                $sql_values[] = DI::userSession()->getLocalUserId();
index ac5f323be99b35e386380386a35768628636a41c..9aae85f85eb37dbf97fc4ef1b01ecc4525842623 100644 (file)
@@ -215,7 +215,7 @@ class Follow extends BaseModule
 
                        $this->baseUrl->redirect($returnPath);
                } elseif (!empty($result['cid'])) {
-                       $this->baseUrl->redirect('contact/' . $result['cid']);
+                       $this->baseUrl->redirect('contact/' . Contact::getPublicContactId($result['cid'], $this->session->getLocalUserId()));
                }
 
                $this->sysMessages->addNotice($this->t('The contact could not be added.'));
index 3531c1dafd2c7358a705d9daaf3ba6f7755ebf89..66076034b7789456c843d9dccf19b8c0dec13399 100644 (file)
@@ -91,8 +91,8 @@ class Profile extends BaseModule
 
                // Backward compatibility: The update still needs a user-specific contact ID
                // Change to user-contact table check by version 2022.03
-               $cdata = Contact::getPublicAndUserContactID($contact_id, $this->session->getLocalUserId());
-               if (empty($cdata['user']) || !$this->db->exists('contact', ['id' => $cdata['user'], 'deleted' => false])) {
+               $ucid = Contact::getUserContactId($contact_id, $this->session->getLocalUserId());
+               if (!$ucid || !$this->db->exists('contact', ['id' => $ucid, 'deleted' => false])) {
                        return;
                }
 
@@ -134,14 +134,14 @@ class Profile extends BaseModule
                }
 
                if (isset($request['channel_frequency'])) {
-                       Contact\User::setChannelFrequency($cdata['user'], $this->session->getLocalUserId(), $request['channel_frequency']);
+                       Contact\User::setChannelFrequency($ucid, $this->session->getLocalUserId(), $request['channel_frequency']);
                }
 
                if (isset($request['channel_only'])) {
-                       Contact\User::setChannelOnly($cdata['user'], $this->session->getLocalUserId(), $request['channel_only']);
+                       Contact\User::setChannelOnly($ucid, $this->session->getLocalUserId(), $request['channel_only']);
                }
 
-               if (!Contact::update($fields, ['id' => $cdata['user'], 'uid' => $this->session->getLocalUserId()])) {
+               if (!Contact::update($fields, ['id' => $ucid, 'uid' => $this->session->getLocalUserId()])) {
                        $this->systemMessages->addNotice($this->t('Failed to update contact record.'));
                }
        }
@@ -164,6 +164,18 @@ class Profile extends BaseModule
                        throw new HTTPException\NotFoundException($this->t('Contact not found.'));
                }
 
+               // Fetch the protocol from the user's contact.
+               $usercontact = Contact::getById($data['user'], ['network', 'protocol']);
+               if ($this->db->isResult($usercontact)) {
+                       $contact['network']  = $usercontact['network'];
+                       $contact['protocol'] = $usercontact['protocol'];
+               }
+
+               if (empty($contact['network']) && Contact::isLocal($contact['url']) ) {
+                       $contact['network']  = Protocol::DFRN;
+                       $contact['protocol'] = Protocol::ACTIVITYPUB;
+               }
+
                // Don't display contacts that are about to be deleted
                if ($this->db->isResult($contact) && (!empty($contact['deleted']) || !empty($contact['network']) && $contact['network'] == Protocol::PHANTOM)) {
                        throw new HTTPException\NotFoundException($this->t('Contact not found.'));
index 1f3a85a476483bfac8fa1cdba37527e639bd92cc..1036e02aa58a4cd66670089befa3fa02ed844c61 100644 (file)
@@ -30,6 +30,7 @@ use Friendica\Core\Renderer;
 use Friendica\Database\Database;
 use Friendica\DI;
 use Friendica\Model;
+use Friendica\Model\Contact as ModelContact;
 use Friendica\Module\Contact;
 use Friendica\Module\Response;
 use Friendica\Module\Security\Login;
@@ -90,7 +91,7 @@ class Revoke extends BaseModule
 
                DI::sysmsg()->addNotice($this->t('Follow was successfully revoked.'));
 
-               $this->baseUrl->redirect('contact/' . $this->parameters['id']);
+               $this->baseUrl->redirect('contact/' . ModelContact::getPublicContactId($this->parameters['id'], DI::userSession()->getLocalUserId()));
        }
 
        protected function content(array $request = []): string
index eb855d7fb6087e5df9fb18eff55c8a372d845334..17e475e039ada19a5f74e15e5c93c94164fa66a7 100644 (file)
@@ -168,7 +168,7 @@ class Unfollow extends \Friendica\BaseModule
                        $this->baseUrl->redirect($base_return_path);
                }
 
-               $return_path = $base_return_path . '/' . $contact['id'];
+               $return_path = $base_return_path . '/' . Contact::getPublicContactId($contact['id'], $uid);
 
                try {
                        Contact::unfollow($contact);
index 85a3ed396b788f1e33849d918b47f2794232cd3b..89a746017eabe9ff7e839ecbee2163adbe1204e7 100644 (file)
@@ -36,6 +36,7 @@ use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses;
 use Friendica\Network\HTTPClient\Client\HttpClientAccept;
 use Friendica\Network\HTTPClient\Client\HttpClientOptions;
 use Friendica\Network\HTTPClient\Client\HttpClientRequest;
+use Friendica\Protocol\ActivityPub\Receiver;
 
 /**
  * Implements HTTP Signatures per draft-cavage-http-signatures-07.
@@ -315,6 +316,55 @@ class HTTPSignature
                return $postResult;
        }
 
+       /**
+        * Route activities locally
+        *
+        * @param array  $data
+        * @param string $target
+        * @param array  $owner
+        * @return boolean
+        */
+       private static function routeLocal(array $data, string $target, array $owner): bool
+       {
+               $uid = self::getUserIdForInbox($target);
+               if (is_null($uid)) {
+                       return false;
+               }
+
+               $activity = JsonLD::compact($data);
+               $type = JsonLD::fetchElement($activity, '@type');
+               $trust_source = true;
+               $object_data = Receiver::prepareObjectData($activity, $uid, true, $trust_source, $owner['url']);
+               if (empty($object_data)) {
+                       return false;
+               }
+
+               Logger::debug('Process directly', ['uid' => $uid, 'target' => $target, 'type' => $type]);
+               return Receiver::routeActivities($object_data, $type, true, true, $uid);
+       }
+
+       /**
+        * Fetch the user id for a given inbox
+        *
+        * @param string $inbox
+        * @return integer|null
+        */
+       private static function getUserIdForInbox(string $inbox): ?int
+       {
+               $gsid = GServer::getID(DI::baseUrl());
+               if (!$gsid) {
+                       return null;
+               }
+               if (DBA::exists('apcontact', ['gsid' => $gsid, 'sharedinbox' => $inbox])) {
+                       return 0;
+               }
+               $apcontact = DBA::selectFirst('apcontact', ['url'], ['gsid' => $gsid, 'inbox' => $inbox]);
+               if (empty($apcontact['url'])) {
+                       return null;
+               }
+               return User::getIdForURL($apcontact['url']);
+       }
+
        /**
         * Transmit given data to a target for a user
         *
@@ -326,6 +376,10 @@ class HTTPSignature
         */
        public static function transmit(array $data, string $target, array $owner): bool
        {
+               if (DI::baseUrl()->isLocalUrl($target) && self::routeLocal($data, $target, $owner)) {
+                       return true;
+               }
+
                $postResult = self::post($data, $target, $owner);
                $return_code = $postResult->getReturnCode();
 
index e97dc1adaf15d1e5524ca0ad218cfdc2f3ba3e9a..5a8e3971735f53cf51cd37650b5cde8d571e901e 100644 (file)
@@ -42,7 +42,12 @@ class RevokeFollow
         */
        public static function execute(int $cid, int $uid)
        {
-               $contact = Contact::getById($cid);
+               $ucid = Contact::getUserContactId($cid, $uid);
+               if (!$ucid) {
+                       return;
+               }
+
+               $contact = Contact::getById($ucid);
                if (empty($contact)) {
                        return;
                }
@@ -53,7 +58,11 @@ class RevokeFollow
                }
 
                if (!Protocol::revokeFollow($contact, $owner)) {
-                       Worker::defer(self::WORKER_DEFER_LIMIT);
+                       if (!Worker::defer(self::WORKER_DEFER_LIMIT)) {
+                               Contact::removeFollower($contact);
+                       }
+               } else {
+                       Contact::removeFollower($contact);
                }
        }
 }
index 48651b3e5bd16c571b31156dea54ff882e81111c..0cc95274dacf828a213d11840cd00e12b7ae8500 100644 (file)
@@ -41,7 +41,12 @@ class Unfollow
         */
        public static function execute(int $cid, int $uid)
        {
-               $contact = Contact::getById($cid);
+               $ucid = Contact::getUserContactId($cid, $uid);
+               if (!$ucid) {
+                       return;
+               }
+
+               $contact = Contact::getById($ucid);
                if (empty($contact)) {
                        return;
                }
@@ -53,7 +58,11 @@ class Unfollow
 
                $result = Protocol::unfollow($contact, $owner);
                if ($result === false) {
-                       Worker::defer(self::WORKER_DEFER_LIMIT);
+                       if (!Worker::defer(self::WORKER_DEFER_LIMIT)) {
+                               Contact::removeSharer($contact);        
+                       }
+               } else {
+                       Contact::removeSharer($contact);
                }
        }
 }