diff --git a/src/Module/OStatus/Subscribe.php b/src/Module/OStatus/Subscribe.php new file mode 100644 index 0000000000..52bd19aef2 --- /dev/null +++ b/src/Module/OStatus/Subscribe.php @@ -0,0 +1,164 @@ +. + * + */ + +namespace Friendica\Module\OStatus; + +use Friendica\App; +use Friendica\Core\L10n; +use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; +use Friendica\Core\Protocol; +use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Model\APContact; +use Friendica\Model\Contact; +use Friendica\Module\Response; +use Friendica\Navigation\SystemMessages; +use Friendica\Network\HTTPClient\Capability\ICanSendHttpRequests; +use Friendica\Network\HTTPClient\Client\HttpClientAccept; +use Friendica\Protocol\ActivityPub; +use Friendica\Util\Profiler; +use Psr\Log\LoggerInterface; + +class Subscribe extends \Friendica\BaseModule +{ + /** @var IHandleUserSessions */ + private $session; + /** @var SystemMessages */ + private $systemMessages; + /** @var ICanSendHttpRequests */ + private $httpClient; + /** @var IManagePersonalConfigValues */ + private $pConfig; + /** @var App\Page */ + private $page; + + public function __construct(App\Page $page, IManagePersonalConfigValues $pConfig, ICanSendHttpRequests $httpClient, SystemMessages $systemMessages, IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) + { + parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + + $this->session = $session; + $this->systemMessages = $systemMessages; + $this->httpClient = $httpClient; + $this->pConfig = $pConfig; + $this->page = $page; + } + + protected function content(array $request = []): string + { + if (!$this->session->getLocalUserId()) { + $this->systemMessages->addNotice($this->t('Permission denied.')); + $this->baseUrl->redirect('login'); + } + + $o = '

' . $this->t('Subscribing to contacts') . '

'; + + $uid = $this->session->getLocalUserId(); + + $counter = intval($request['counter'] ?? 0); + + if ($this->pConfig->get($uid, 'ostatus', 'legacy_friends') == '') { + if (empty($request['url'])) { + $this->pConfig->delete($uid, 'ostatus', 'legacy_contact'); + return $o . $this->t('No contact provided.'); + } + + $contact = Contact::getByURL($request['url']); + if (!$contact) { + $this->pConfig->delete($uid, 'ostatus', 'legacy_contact'); + return $o . $this->t('Couldn\'t fetch information for contact.'); + } + + if ($contact['network'] == Protocol::OSTATUS) { + $api = $contact['baseurl'] . '/api/'; + + // Fetching friends + $curlResult = $this->httpClient->get($api . 'statuses/friends.json?screen_name=' . $contact['nick'], HttpClientAccept::JSON); + + if (!$curlResult->isSuccess()) { + $this->pConfig->delete($uid, 'ostatus', 'legacy_contact'); + return $o . $this->t('Couldn\'t fetch friends for contact.'); + } + + $friends = $curlResult->getBody(); + if (empty($friends)) { + $this->pConfig->delete($uid, 'ostatus', 'legacy_contact'); + return $o . $this->t('Couldn\'t fetch following contacts.'); + } + $this->pConfig->set($uid, 'ostatus', 'legacy_friends', $friends); + } elseif ($apcontact = APContact::getByURL($contact['url'])) { + if (empty($apcontact['following'])) { + $this->pConfig->delete($uid, 'ostatus', 'legacy_contact'); + return $o . $this->t('Couldn\'t fetch remote profile.'); + } + $followings = ActivityPub::fetchItems($apcontact['following']); + if (empty($followings)) { + $this->pConfig->delete($uid, 'ostatus', 'legacy_contact'); + return $o . $this->t('Couldn\'t fetch following contacts.'); + } + $this->pConfig->set($uid, 'ostatus', 'legacy_friends', json_encode($followings)); + } else { + $this->pConfig->delete($uid, 'ostatus', 'legacy_contact'); + return $o . $this->t('Unsupported network'); + } + } + + $friends = json_decode($this->pConfig->get($uid, 'ostatus', 'legacy_friends')); + + if (empty($friends)) { + $friends = []; + } + + $total = sizeof($friends); + + if ($counter >= $total) { + $this->page['htmlhead'] = ''; + $this->pConfig->delete($uid, 'ostatus', 'legacy_friends'); + $this->pConfig->delete($uid, 'ostatus', 'legacy_contact'); + $o .= $this->t('Done'); + return $o; + } + + $friend = $friends[$counter++]; + + $url = $friend->statusnet_profile_url ?? $friend; + + $o .= '

' . $counter . '/' . $total . ': ' . $url; + + $probed = Contact::getByURL($url); + if (in_array($probed['network'], Protocol::FEDERATED)) { + $result = Contact::createFromProbeForUser($this->session->getLocalUserId(), $probed['url']); + if ($result['success']) { + $o .= ' - ' . $this->t('success'); + } else { + $o .= ' - ' . $this->t('failed'); + } + } else { + $o .= ' - ' . $this->t('ignored'); + } + + $o .= '

'; + + $o .= '

' . $this->t('Keep this window open until done.') . '

'; + + $this->page['htmlhead'] = ''; + + return $o; + } +} diff --git a/src/Module/Settings/Connectors.php b/src/Module/Settings/Connectors.php index 969d74d054..acd638829a 100644 --- a/src/Module/Settings/Connectors.php +++ b/src/Module/Settings/Connectors.php @@ -140,7 +140,7 @@ class Connectors extends BaseSettings $legacy_contact = $this->pconfig->get($this->session->getLocalUserId(), 'ostatus', 'legacy_contact'); if (!empty($legacy_contact)) { - $this->baseUrl->redirect('ostatus_subscribe?url=' . urlencode($legacy_contact)); + $this->baseUrl->redirect('ostatus/subscribe?url=' . urlencode($legacy_contact)); } $connector_settings_forms = []; diff --git a/static/routes.config.php b/static/routes.config.php index 927b018403..d5bed27569 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -526,8 +526,6 @@ return [ '/openid' => [Module\Security\OpenID::class, [R::GET]], '/opensearch' => [Module\OpenSearch::class, [R::GET]], - '/ostatus/repair' => [Module\OStatus\Repair::class, [R::GET]], - '/parseurl' => [Module\ParseUrl::class, [R::GET]], '/permission/tooltip/{type}/{id:\d+}' => [Module\PermissionTooltip::class, [R::GET]], @@ -569,6 +567,9 @@ return [ '/{sub1}/{sub2}/{url}' => [Module\Proxy::class, [R::GET]], ], + // OStatus stack modules + '/ostatus/repair' => [Module\OStatus\Repair::class, [R::GET ]], + '/ostatus/subscribe' => [Module\OStatus\Subscribe::class, [R::GET ]], '/poco' => [Module\User\PortableContacts::class, [R::GET ]], '/pubsub/{nickname}/{cid:\d+}' => [Module\OStatus\PubSub::class, [R::GET, R::POST]], '/pubsubhubbub/{nickname}' => [Module\OStatus\PubSubHubBub::class, [ R::POST]],