diff --git a/doc/Addons.md b/doc/Addons.md index 578cffe7c..7c9b89d34 100644 --- a/doc/Addons.md +++ b/doc/Addons.md @@ -626,7 +626,8 @@ Hook data: Called when unfollowing a remote contact on a non-native network (like Twitter) Hook data: -- **contact** (input): the remote contact (uid = local unfollowing user id) array. +- **contact** (input): the target public contact (uid = 0) array. +- **uid** (input): the id of the source local user. - **result** (output): wether the unfollowing is successful or not. ### revoke_follow @@ -634,7 +635,8 @@ Hook data: Called when making a remote contact on a non-native network (like Twitter) unfollow you. Hook data: -- **contact** (input): the remote contact (uid = local revoking user id) array. +- **contact** (input): the target public contact (uid = 0) array. +- **uid** (input): the id of the source local user. - **result** (output): a boolean value indicating wether the operation was successful or not. ### block diff --git a/mod/unfollow.php b/mod/unfollow.php index 0aa8a87b5..10830bd10 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -122,8 +122,7 @@ function unfollow_process(string $url) $owner = User::getOwnerDataById($uid); if (!$owner) { - (new \Friendica\Module\Security\Logout())->init(); - // NOTREACHED + throw new \Friendica\Network\HTTPException\NotFoundException(); } $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?)", @@ -140,15 +139,10 @@ function unfollow_process(string $url) $return_path = $base_return_path . '/' . $contact['id']; try { - $result = Contact::terminateFriendship($owner, $contact); - - if ($result === false) { - $notice_message = DI::l10n()->t('Unable to unfollow this contact, please retry in a few minutes or contact your administrator.'); - } else { - $notice_message = DI::l10n()->t('Contact was successfully unfollowed'); - } + Contact::unfollow($contact); + $notice_message = DI::l10n()->t('Contact was successfully unfollowed'); } catch (Exception $e) { - DI::logger()->error($e->getMessage(), ['owner' => $owner, 'contact' => $contact]); + DI::logger()->error($e->getMessage(), ['contact' => $contact]); $notice_message = DI::l10n()->t('Unable to unfollow this contact, please contact your administrator'); } diff --git a/src/Console/Contact.php b/src/Console/Contact.php index 11f7f87ce..f051d870a 100644 --- a/src/Console/Contact.php +++ b/src/Console/Contact.php @@ -199,19 +199,18 @@ HELP; throw new RuntimeException('Contact not found'); } - $user = UserModel::getById($contact['uid']); + if (empty($contact['uid'])) { + throw new RuntimeException('Contact must be user-specific (uid != 0)'); + } try { - $result = ContactModel::terminateFriendship($user, $contact); - if ($result === false) { - throw new RuntimeException('Unable to unfollow this contact, please retry in a few minutes or check the logs.'); - } + ContactModel::unfollow($contact); $this->out('Contact was successfully unfollowed'); return true; } catch (\Exception $e) { - DI::logger()->error($e->getMessage(), ['owner' => $user, 'contact' => $contact]); + DI::logger()->error($e->getMessage(), ['contact' => $contact]); throw new RuntimeException('Unable to unfollow this contact, please check the log'); } } diff --git a/src/Core/Protocol.php b/src/Core/Protocol.php index 1b2626525..c141bbc54 100644 --- a/src/Core/Protocol.php +++ b/src/Core/Protocol.php @@ -22,7 +22,6 @@ namespace Friendica\Core; use Friendica\Database\DBA; -use Friendica\DI; use Friendica\Model\User; use Friendica\Network\HTTPException; use Friendica\Protocol\Activity; @@ -171,15 +170,15 @@ class Protocol } /** - * Sends an unfriend message. Does not remove the contact + * Sends an unfollow message. Does not remove the contact * - * @param array $user User unfriending - * @param array $contact Contact unfriended + * @param array $contact Target public contact (uid = 0) array + * @param array $user Source local user array * @return bool|null true if successful, false if not, null if no remote action was performed * @throws HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function terminateFriendship(array $user, array $contact): ?bool + public static function unfollow(array $contact, array $user): ?bool { if (empty($contact['network'])) { throw new \InvalidArgumentException('Missing network key in contact array'); @@ -216,7 +215,8 @@ class Protocol // Catch-all hook for connector addons $hook_data = [ 'contact' => $contact, - 'result' => null + 'uid' => $user['uid'], + 'result' => null, ]; Hook::callAll('unfollow', $hook_data); @@ -226,12 +226,13 @@ class Protocol /** * Revoke an incoming follow from the provided contact * - * @param array $contact Private contact (uid != 0) array + * @param array $contact Target public contact (uid == 0) array + * @param int $uid Source local user id * @return bool|null true if successful, false if not, null if no action was performed * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function revokeFollow(array $contact): ?bool + public static function revokeFollow(array $contact, int $uid): ?bool { if (empty($contact['network'])) { throw new \InvalidArgumentException('Missing network key in contact array'); @@ -243,13 +244,14 @@ class Protocol } if ($protocol == Protocol::ACTIVITYPUB) { - return ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $contact['uid']); + return ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $uid); } // Catch-all hook for connector addons $hook_data = [ 'contact' => $contact, - 'result' => null, + 'uid' => $uid, + 'result' => null, ]; Hook::callAll('revoke_follow', $hook_data); diff --git a/src/Core/Worker.php b/src/Core/Worker.php index d43d8c728..5c23d6445 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -1378,8 +1378,9 @@ class Worker * Defers the current worker entry * * @return boolean had the entry been deferred? + * @throws \Exception */ - public static function defer() + public static function defer(): bool { $queue = DI::app()->getQueue(); @@ -1387,7 +1388,6 @@ class Worker return false; } - $retrial = $queue['retrial']; $id = $queue['id']; $priority = $queue['priority']; diff --git a/src/Model/Contact.php b/src/Model/Contact.php index d80827c93..f0be45772 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -813,37 +813,13 @@ class Contact } /** - * Sends an unfriend message. Removes the contact for two-way unfriending or sharing only protocols (feed an mail) + * Unfollow the remote contact * - * @param array $user User unfriending - * @param array $contact Contact (uid != 0) unfriended - * @param boolean $two_way Revoke eventual inbound follow as well - * @return bool|null true if successful, false if not, null if no remote action was performed + * @param array $contact Target user-specific contact (uid != 0) array * @throws HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function terminateFriendship(array $user, array $contact): ?bool - { - $result = Protocol::terminateFriendship($user, $contact); - - if ($contact['rel'] == Contact::SHARING || in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) { - self::remove($contact['id']); - } else { - self::update(['rel' => Contact::FOLLOWER], ['id' => $contact['id']]); - } - - return $result; - } - - /** - * Revoke follow privileges of the remote user contact - * - * @param array $contact Contact unfriended - * @return bool|null Whether the remote operation is successful or null if no remote operation was performed - * @throws HTTPException\InternalServerErrorException - * @throws \ImagickException - */ - public static function revokeFollow(array $contact): ?bool + public static function unfollow(array $contact): void { if (empty($contact['network'])) { throw new \InvalidArgumentException('Empty network in contact array'); @@ -853,19 +829,69 @@ class Contact throw new \InvalidArgumentException('Unexpected public contact record'); } - $result = Protocol::revokeFollow($contact); - - // A null value here means the remote network doesn't support explicit follow revocation, we can still - // break the locally recorded relationship - if ($result !== false) { - if ($contact['rel'] == self::FRIEND) { - self::update(['rel' => self::SHARING], ['id' => $contact['id']]); - } else { - self::remove($contact['id']); - } + if (in_array($contact['rel'], [self::SHARING, self::FRIEND])) { + $cdata = Contact::getPublicAndUserContactID($contact['id'], $contact['uid']); + Worker::add(PRIORITY_HIGH, 'Contact\Unfollow', $cdata['public'], $contact['uid']); } - return $result; + self::removeSharer($contact); + } + + /** + * Revoke follow privileges of the remote user contact + * + * The local relationship is updated immediately, the eventual remote server is messaged in the background. + * + * @param array $contact User-specific contact array (uid != 0) to revoke the follow from + * @throws HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function revokeFollow(array $contact): void + { + if (empty($contact['network'])) { + throw new \InvalidArgumentException('Empty network in contact array'); + } + + if (empty($contact['uid'])) { + throw new \InvalidArgumentException('Unexpected public contact record'); + } + + if (in_array($contact['rel'], [self::FOLLOWER, self::FRIEND])) { + $cdata = Contact::getPublicAndUserContactID($contact['id'], $contact['uid']); + Worker::add(PRIORITY_HIGH, 'Contact\RevokeFollow', $cdata['public'], $contact['uid']); + } + + self::removeFollower($contact); + } + + /** + * Completely severs a relationship with a contact + * + * @param array $contact User-specific contact (uid != 0) array + * @throws HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function terminateFriendship(array $contact) + { + if (empty($contact['network'])) { + throw new \InvalidArgumentException('Empty network in contact array'); + } + + if (empty($contact['uid'])) { + throw new \InvalidArgumentException('Unexpected public contact record'); + } + + $cdata = Contact::getPublicAndUserContactID($contact['id'], $contact['uid']); + + if (in_array($contact['rel'], [self::SHARING, self::FRIEND])) { + Worker::add(PRIORITY_HIGH, 'Contact\Unfollow', $cdata['public'], $contact['uid']); + } + + if (in_array($contact['rel'], [self::FOLLOWER, self::FRIEND])) { + Worker::add(PRIORITY_HIGH, 'Contact\RevokeFollow', $cdata['public'], $contact['uid']); + } + + self::remove($contact['id']); } @@ -2574,28 +2600,6 @@ class Contact return $result; } - /** - * Unfollow a contact - * - * @param int $cid Public contact id - * @param int $uid User ID - * - * @return bool "true" if unfollowing had been successful - */ - public static function unfollow(int $cid, int $uid) - { - $cdata = self::getPublicAndUserContactID($cid, $uid); - if (empty($cdata['user'])) { - return false; - } - - $contact = self::getById($cdata['user']); - - self::removeSharer([], $contact); - - return true; - } - /** * @param array $importer Owner (local user) data * @param array $contact Existing owner-specific contact data we want to expand the relationship with. Optional. @@ -2744,10 +2748,17 @@ class Contact return null; } + /** + * Update the local relationship when a local user loses a follower + * + * @param array $contact User-specific contact (uid != 0) array + * @throws HTTPException\InternalServerErrorException + * @throws \ImagickException + */ public static function removeFollower(array $contact) { if (in_array($contact['rel'] ?? [], [self::FRIEND, self::SHARING])) { - DBA::update('contact', ['rel' => self::SHARING], ['id' => $contact['id']]); + self::update(['rel' => self::SHARING], ['id' => $contact['id']]); } elseif (!empty($contact['id'])) { self::remove($contact['id']); } else { @@ -2755,12 +2766,19 @@ class Contact } } - public static function removeSharer($importer, $contact) + /** + * Update the local relationship when a local user unfollow a contact. + * Removes the contact for sharing-only protocols (feed and mail). + * + * @param array $contact User-specific contact (uid != 0) array + * @throws HTTPException\InternalServerErrorException + */ + public static function removeSharer(array $contact) { - if (($contact['rel'] == self::FRIEND) || ($contact['rel'] == self::FOLLOWER)) { - self::update(['rel' => self::FOLLOWER], ['id' => $contact['id']]); - } else { + if ($contact['rel'] == self::SHARING || in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) { self::remove($contact['id']); + } else { + self::update(['rel' => self::FOLLOWER], ['id' => $contact['id']]); } } diff --git a/src/Module/Api/Mastodon/Accounts/Block.php b/src/Module/Api/Mastodon/Accounts/Block.php index 94c0e3712..41d0a6f5e 100644 --- a/src/Module/Api/Mastodon/Accounts/Block.php +++ b/src/Module/Api/Mastodon/Accounts/Block.php @@ -59,8 +59,7 @@ class Block extends BaseApi Contact\User::setBlocked($cdata['user'], $uid, true); // Mastodon-expected behavior: relationship is severed on block - Contact::terminateFriendship($owner, $contact); - Contact::revokeFollow($contact); + Contact::terminateFriendship($contact); System::jsonExit(DI::mstdnRelationship()->createFromContactId($this->parameters['id'], $uid)->toArray()); } diff --git a/src/Module/Api/Mastodon/Accounts/Unfollow.php b/src/Module/Api/Mastodon/Accounts/Unfollow.php index db1e049db..29aa82b49 100644 --- a/src/Module/Api/Mastodon/Accounts/Unfollow.php +++ b/src/Module/Api/Mastodon/Accounts/Unfollow.php @@ -40,7 +40,14 @@ class Unfollow extends BaseApi DI::mstdnError()->UnprocessableEntity(); } - Contact::unfollow($this->parameters['id'], $uid); + $cdata = Contact::getPublicAndUserContactID($this->parameters['id'], $uid); + if (empty($cdata['user'])) { + DI::mstdnError()->RecordNotFound(); + } + + $contact = Contact::getById($cdata['user']); + + Contact::unfollow($contact); System::jsonExit(DI::mstdnRelationship()->createFromContactId($this->parameters['id'], $uid)->toArray()); } diff --git a/src/Module/Api/Twitter/Friendships/Destroy.php b/src/Module/Api/Twitter/Friendships/Destroy.php index e2e0dd70c..b730f0663 100644 --- a/src/Module/Api/Twitter/Friendships/Destroy.php +++ b/src/Module/Api/Twitter/Friendships/Destroy.php @@ -22,13 +22,18 @@ namespace Friendica\Module\Api\Twitter\Friendships; use Exception; +use Friendica\App; +use Friendica\Core\L10n; use Friendica\Core\Logger; -use Friendica\DI; +use Friendica\Factory\Api\Twitter\User as TwitterUser; use Friendica\Model\Contact; use Friendica\Model\User; +use Friendica\Module\Api\ApiResponse; use Friendica\Module\Api\Twitter\ContactEndpoint; use Friendica\Module\BaseApi; use Friendica\Network\HTTPException; +use Friendica\Util\Profiler; +use Psr\Log\LoggerInterface; /** * Unfollow Contact @@ -37,6 +42,16 @@ use Friendica\Network\HTTPException; */ class Destroy extends ContactEndpoint { + /** @var TwitterUser */ + private $twitterUser; + + public function __construct(App $app, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, ApiResponse $response, TwitterUser $twitterUser, array $server, array $parameters = []) + { + parent::__construct($app, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->twitterUser = $twitterUser; + } + protected function post(array $request = []) { BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); @@ -66,18 +81,9 @@ class Destroy extends ContactEndpoint $user = $this->twitterUser->createFromContactId($contact_id, $uid, true)->toArray(); try { - $result = Contact::terminateFriendship($owner, $contact); - - if ($result === null) { - Logger::notice(BaseApi::LOG_PREFIX . 'Not supported for {network}', ['module' => 'api', 'action' => 'friendships_destroy', 'network' => $contact['network']]); - throw new HTTPException\ExpectationFailedException('Unfollowing is currently not supported by this contact\'s network.'); - } - - if ($result === false) { - throw new HTTPException\ServiceUnavailableException('Unable to unfollow this contact, please retry in a few minutes or contact your administrator.'); - } + Contact::unfollow($contact); } catch (Exception $e) { - Logger::error(BaseApi::LOG_PREFIX . $e->getMessage(), ['owner' => $owner, 'contact' => $contact]); + Logger::error(BaseApi::LOG_PREFIX . $e->getMessage(), ['contact' => $contact]); throw new HTTPException\InternalServerErrorException('Unable to unfollow this contact, please contact your administrator'); } diff --git a/src/Module/Contact/Revoke.php b/src/Module/Contact/Revoke.php index 59b3bdafa..35cb48149 100644 --- a/src/Module/Contact/Revoke.php +++ b/src/Module/Contact/Revoke.php @@ -38,7 +38,10 @@ use Psr\Log\LoggerInterface; class Revoke extends BaseModule { - /** @var array */ + /** + * User-specific contact (uid != 0) array + * @var array + */ protected $contact; /** @var Database */ @@ -82,14 +85,9 @@ class Revoke extends BaseModule self::checkFormSecurityTokenRedirectOnError('contact/' . $this->parameters['id'], 'contact_revoke'); - $result = Model\Contact::revokeFollow($this->contact); - if ($result === true) { - notice($this->t('Follow was successfully revoked.')); - } elseif ($result === null) { - notice($this->t('Follow was successfully revoked, however the remote contact won\'t be aware of this revokation.')); - } else { - notice($this->t('Unable to revoke follow, please try again later or contact the administrator.')); - } + Model\Contact::revokeFollow($this->contact); + + notice($this->t('Follow was successfully revoked.')); $this->baseUrl->redirect('contact/' . $this->parameters['id']); } diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 50faf987a..2be55b8a5 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1668,7 +1668,7 @@ class DFRN } if ($activity->match($item["verb"], Activity::UNFRIEND)) { Logger::notice("Lost sharer"); - Contact::removeSharer($importer, $contact, $item); + Contact::removeSharer($contact); return false; } } else { diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index ea0b2b674..ad8e2bbef 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -837,8 +837,7 @@ class Diaspora // It is deactivated by now, due to side effects. See issue https://github.com/friendica/friendica/pull/4033 // It is not removed by now. Possibly the code is needed? //if (!$is_comment && $contact["rel"] == Contact::FOLLOWER && in_array($importer["page-flags"], array(User::PAGE_FLAGS_FREELOVE))) { - // DBA::update( - // 'contact', + // Contact::update( // array('rel' => Contact::FRIEND, 'writable' => true), // array('id' => $contact["id"], 'uid' => $contact["uid"]) // ); @@ -2123,8 +2122,7 @@ class Diaspora private static function receiveRequestMakeFriend(array $importer, array $contact) { if ($contact["rel"] == Contact::SHARING) { - DBA::update( - 'contact', + Contact::update( ['rel' => Contact::FRIEND, 'writable' => true], ['id' => $contact["id"], 'uid' => $importer["uid"]] ); diff --git a/src/Worker/Contact/RevokeFollow.php b/src/Worker/Contact/RevokeFollow.php new file mode 100644 index 000000000..726a69b8d --- /dev/null +++ b/src/Worker/Contact/RevokeFollow.php @@ -0,0 +1,51 @@ +. + * + */ + +namespace Friendica\Worker\Contact; + +use Friendica\Core\Protocol; +use Friendica\Core\Worker; +use Friendica\Model\Contact; + +class RevokeFollow +{ + /** + * Issue asynchronous follow revokation message to remote servers. + * The local relationship has already been updated, so we can't use the user-specific contact + * + * @param int $cid Target public contact id + * @param int $uid Source local user id + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function execute(int $cid, int $uid) + { + $contact = Contact::getById($cid); + if (empty($contact)) { + return; + } + + $result = Protocol::revokeFollow($contact, $uid); + if ($result === false) { + Worker::defer(); + } + } +} diff --git a/src/Worker/Contact/Unfollow.php b/src/Worker/Contact/Unfollow.php new file mode 100644 index 000000000..a6d8c5944 --- /dev/null +++ b/src/Worker/Contact/Unfollow.php @@ -0,0 +1,57 @@ +. + * + */ + +namespace Friendica\Worker\Contact; + +use Friendica\Core\Protocol; +use Friendica\Core\Worker; +use Friendica\Model\Contact; +use Friendica\Model\User; + +class Unfollow +{ + /** + * Issue asynchronous unfollow message to remote servers. + * The local relationship has already been updated, so we can't use the user-specific contact. + * + * @param int $cid Target public contact (uid = 0) id + * @param int $uid Source local user id + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws \ImagickException + */ + public static function execute(int $cid, int $uid) + { + $contact = Contact::getById($cid); + if (empty($contact)) { + return; + } + + $owner = User::getOwnerDataById($uid, false); + if (empty($owner)) { + return; + } + + $result = Protocol::unfollow($contact, $owner); + if ($result === false) { + Worker::defer(); + } + } +} diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 488ade222..80628d7db 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -445,7 +445,7 @@ class Notifier $condition = ['network' => Protocol::DFRN, 'uid' => $owner['uid'], 'blocked' => false, 'pending' => false, 'archive' => false, 'rel' => [Contact::FOLLOWER, Contact::FRIEND]]; - $contacts = DBA::toArray(DBA::select('contact', ['id', 'url', 'addr', 'name', 'network', 'protocol'], $condition)); + $contacts = DBA::selectToArray('contact', ['id', 'url', 'addr', 'name', 'network', 'protocol'], $condition); $conversants = array_merge($contacts, $participants); @@ -673,7 +673,7 @@ class Notifier } while($contact = DBA::fetch($contacts_stmt)) { - Protocol::terminateFriendship($owner, $contact, true); + Contact::terminateFriendship($contact); } DBA::close($contacts_stmt); diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 7bf333005..0ec51c216 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 2022.05-dev\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-24 07:09+0000\n" +"POT-Creation-Date: 2022-02-24 09:39-0500\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -268,7 +268,7 @@ msgstr "" #: mod/editpost.php:130 mod/fbrowser.php:117 mod/fbrowser.php:144 #: mod/follow.php:144 mod/photos.php:1010 mod/photos.php:1111 mod/tagrm.php:35 #: mod/tagrm.php:127 mod/unfollow.php:97 src/Content/Conversation.php:373 -#: src/Module/Contact/Revoke.php:110 src/Module/RemoteFollow.php:127 +#: src/Module/Contact/Revoke.php:108 src/Module/RemoteFollow.php:127 msgid "Cancel" msgstr "" @@ -465,7 +465,7 @@ msgid "OStatus support is disabled. Contact can't be added." msgstr "" #: mod/follow.php:138 src/Content/Item.php:452 src/Content/Widget.php:76 -#: src/Model/Contact.php:1057 src/Model/Contact.php:1069 +#: src/Model/Contact.php:1083 src/Model/Contact.php:1095 #: view/theme/vier/theme.php:172 msgid "Connect/Follow" msgstr "" @@ -2038,7 +2038,7 @@ msgid "" "select \"Export account\"" msgstr "" -#: mod/unfollow.php:65 mod/unfollow.php:135 +#: mod/unfollow.php:65 mod/unfollow.php:134 msgid "You aren't following this contact." msgstr "" @@ -2050,17 +2050,11 @@ msgstr "" msgid "Disconnect/Unfollow" msgstr "" -#: mod/unfollow.php:146 -msgid "" -"Unable to unfollow this contact, please retry in a few minutes or contact " -"your administrator." -msgstr "" - -#: mod/unfollow.php:148 +#: mod/unfollow.php:143 msgid "Contact was successfully unfollowed" msgstr "" -#: mod/unfollow.php:152 +#: mod/unfollow.php:146 msgid "Unable to unfollow this contact, please contact your administrator" msgstr "" @@ -2729,31 +2723,31 @@ msgstr "" msgid "Follow Thread" msgstr "" -#: src/Content/Item.php:432 src/Model/Contact.php:1062 +#: src/Content/Item.php:432 src/Model/Contact.php:1088 msgid "View Status" msgstr "" -#: src/Content/Item.php:433 src/Content/Item.php:455 src/Model/Contact.php:996 -#: src/Model/Contact.php:1054 src/Model/Contact.php:1063 +#: src/Content/Item.php:433 src/Content/Item.php:455 src/Model/Contact.php:1022 +#: src/Model/Contact.php:1080 src/Model/Contact.php:1089 #: src/Module/Directory.php:157 src/Module/Settings/Profile/Index.php:225 msgid "View Profile" msgstr "" -#: src/Content/Item.php:434 src/Model/Contact.php:1064 +#: src/Content/Item.php:434 src/Model/Contact.php:1090 msgid "View Photos" msgstr "" -#: src/Content/Item.php:435 src/Model/Contact.php:1055 -#: src/Model/Contact.php:1065 +#: src/Content/Item.php:435 src/Model/Contact.php:1081 +#: src/Model/Contact.php:1091 msgid "Network Posts" msgstr "" -#: src/Content/Item.php:436 src/Model/Contact.php:1056 -#: src/Model/Contact.php:1066 +#: src/Content/Item.php:436 src/Model/Contact.php:1082 +#: src/Model/Contact.php:1092 msgid "View Contact" msgstr "" -#: src/Content/Item.php:437 src/Model/Contact.php:1067 +#: src/Content/Item.php:437 src/Model/Contact.php:1093 msgid "Send PM" msgstr "" @@ -2776,7 +2770,7 @@ msgstr "" msgid "Languages" msgstr "" -#: src/Content/Item.php:447 src/Model/Contact.php:1068 +#: src/Content/Item.php:447 src/Model/Contact.php:1094 msgid "Poke" msgstr "" @@ -3228,7 +3222,7 @@ msgstr "" msgid "Organisations" msgstr "" -#: src/Content/Widget.php:519 src/Model/Contact.php:1472 +#: src/Content/Widget.php:519 src/Model/Contact.php:1498 msgid "News" msgstr "" @@ -4051,81 +4045,81 @@ msgstr "" msgid "Legacy module file not found: %s" msgstr "" -#: src/Model/Contact.php:1058 src/Model/Contact.php:1070 +#: src/Model/Contact.php:1084 src/Model/Contact.php:1096 msgid "UnFollow" msgstr "" -#: src/Model/Contact.php:1076 src/Module/Admin/Users/Pending.php:107 +#: src/Model/Contact.php:1102 src/Module/Admin/Users/Pending.php:107 #: src/Module/Notifications/Introductions.php:130 #: src/Module/Notifications/Introductions.php:202 msgid "Approve" msgstr "" -#: src/Model/Contact.php:1468 +#: src/Model/Contact.php:1494 msgid "Organisation" msgstr "" -#: src/Model/Contact.php:1476 +#: src/Model/Contact.php:1502 msgid "Forum" msgstr "" -#: src/Model/Contact.php:2411 +#: src/Model/Contact.php:2437 msgid "Disallowed profile URL." msgstr "" -#: src/Model/Contact.php:2416 src/Module/Friendica.php:81 +#: src/Model/Contact.php:2442 src/Module/Friendica.php:81 msgid "Blocked domain" msgstr "" -#: src/Model/Contact.php:2421 +#: src/Model/Contact.php:2447 msgid "Connect URL missing." msgstr "" -#: src/Model/Contact.php:2430 +#: src/Model/Contact.php:2456 msgid "" "The contact could not be added. Please check the relevant network " "credentials in your Settings -> Social Networks page." msgstr "" -#: src/Model/Contact.php:2467 +#: src/Model/Contact.php:2493 msgid "The profile address specified does not provide adequate information." msgstr "" -#: src/Model/Contact.php:2469 +#: src/Model/Contact.php:2495 msgid "No compatible communication protocols or feeds were discovered." msgstr "" -#: src/Model/Contact.php:2472 +#: src/Model/Contact.php:2498 msgid "An author or name was not found." msgstr "" -#: src/Model/Contact.php:2475 +#: src/Model/Contact.php:2501 msgid "No browser URL could be matched to this address." msgstr "" -#: src/Model/Contact.php:2478 +#: src/Model/Contact.php:2504 msgid "" "Unable to match @-style Identity Address with a known protocol or email " "contact." msgstr "" -#: src/Model/Contact.php:2479 +#: src/Model/Contact.php:2505 msgid "Use mailto: in front of address to force email check." msgstr "" -#: src/Model/Contact.php:2485 +#: src/Model/Contact.php:2511 msgid "" "The profile address specified belongs to a network which has been disabled " "on this site." msgstr "" -#: src/Model/Contact.php:2490 +#: src/Model/Contact.php:2516 msgid "" "Limited profile. This person will be unable to receive direct/personal " "notifications from you." msgstr "" -#: src/Model/Contact.php:2549 +#: src/Model/Contact.php:2575 msgid "Unable to retrieve contact information." msgstr "" @@ -7518,7 +7512,7 @@ msgstr "" msgid "Toggle Ignored status" msgstr "" -#: src/Module/Contact/Profile.php:466 src/Module/Contact/Revoke.php:107 +#: src/Module/Contact/Profile.php:466 src/Module/Contact/Revoke.php:105 msgid "Revoke Follow" msgstr "" @@ -7526,40 +7520,29 @@ msgstr "" msgid "Revoke the follow from this contact" msgstr "" -#: src/Module/Contact/Revoke.php:59 +#: src/Module/Contact/Revoke.php:62 msgid "Unknown contact." msgstr "" -#: src/Module/Contact/Revoke.php:69 src/Module/Group.php:112 +#: src/Module/Contact/Revoke.php:72 src/Module/Group.php:112 msgid "Contact is deleted." msgstr "" -#: src/Module/Contact/Revoke.php:73 +#: src/Module/Contact/Revoke.php:76 msgid "Contact is being deleted." msgstr "" -#: src/Module/Contact/Revoke.php:87 +#: src/Module/Contact/Revoke.php:90 msgid "Follow was successfully revoked." msgstr "" -#: src/Module/Contact/Revoke.php:89 -msgid "" -"Follow was successfully revoked, however the remote contact won't be aware " -"of this revokation." -msgstr "" - -#: src/Module/Contact/Revoke.php:91 -msgid "" -"Unable to revoke follow, please try again later or contact the administrator." -msgstr "" - -#: src/Module/Contact/Revoke.php:108 +#: src/Module/Contact/Revoke.php:106 msgid "" "Do you really want to revoke this contact's follow? This cannot be undone " "and they will have to manually follow you back again." msgstr "" -#: src/Module/Contact/Revoke.php:109 +#: src/Module/Contact/Revoke.php:107 #: src/Module/Notifications/Introductions.php:142 #: src/Module/OAuth/Acknowledge.php:53 src/Module/Register.php:130 msgid "Yes"