X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2FGServer.php;h=731175ea50c18e14f6d51431da8a5fb106a53ef3;hb=72a3ab6382551811f22391b7e82e7398628b235b;hp=af03041498d56cdb2ecaa36bf9afc3e5ced9a880;hpb=8e65bdd011a412b4012caae1b3a70afdf6e5c22e;p=friendica.git diff --git a/src/Model/GServer.php b/src/Model/GServer.php index af03041498..731175ea50 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -1,6 +1,6 @@ get('system', 'xrd_timeout'); - $curlResult = DI::httpClient()->get($url . '/.well-known/nodeinfo', [HttpClientOptions::TIMEOUT => $xrd_timeout]); + $curlResult = DI::httpClient()->get($url . '/.well-known/nodeinfo', [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if ($curlResult->isTimeout()) { self::setFailure($url); return false; } // On a redirect follow the new host but mark the old one as failure - if ($curlResult->isSuccess() && (parse_url($url, PHP_URL_HOST) != parse_url($curlResult->getRedirectUrl(), PHP_URL_HOST))) { - $curlResult = DI::httpClient()->get($url, [HttpClientOptions::TIMEOUT => $xrd_timeout]); - if (parse_url($url, PHP_URL_HOST) != parse_url($curlResult->getRedirectUrl(), PHP_URL_HOST)) { + if ($curlResult->isSuccess() && !empty($curlResult->getRedirectUrl()) && (parse_url($url, PHP_URL_HOST) != parse_url($curlResult->getRedirectUrl(), PHP_URL_HOST))) { + $curlResult = DI::httpClient()->get($url, [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_HTML]); + if (!empty($curlResult->getRedirectUrl()) && parse_url($url, PHP_URL_HOST) != parse_url($curlResult->getRedirectUrl(), PHP_URL_HOST)) { Logger::info('Found redirect. Mark old entry as failure', ['old' => $url, 'new' => $curlResult->getRedirectUrl()]); self::setFailure($url); self::detect($curlResult->getRedirectUrl(), $network, $only_nodeinfo); @@ -376,6 +378,12 @@ class GServer if (empty($nodeinfo['network']) || in_array($nodeinfo['network'], [Protocol::DFRN, Protocol::ZOT])) { if (!empty($nodeinfo['detection-method'])) { $serverdata['detection-method'] = $nodeinfo['detection-method']; + + foreach (['registered-users', 'active_users_monthly', 'active-halfyear-users', 'local-posts'] as $field) { + if (!empty($nodeinfo[$field])) { + $serverdata[$field] = $nodeinfo[$field]; + } + } } // Fetch the landing page, possibly it reveals some data @@ -386,9 +394,9 @@ class GServer $basedata = ['detection-method' => self::DETECT_MANUAL]; } - $curlResult = DI::httpClient()->get($baseurl, [HttpClientOptions::TIMEOUT => $xrd_timeout]); + $curlResult = DI::httpClient()->get($baseurl, [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_HTML]); if ($curlResult->isSuccess()) { - if ((parse_url($baseurl, PHP_URL_HOST) != parse_url($curlResult->getRedirectUrl(), PHP_URL_HOST))) { + if (!empty($curlResult->getRedirectUrl()) && (parse_url($baseurl, PHP_URL_HOST) != parse_url($curlResult->getRedirectUrl(), PHP_URL_HOST))) { Logger::info('Found redirect. Mark old entry as failure', ['old' => $url, 'new' => $curlResult->getRedirectUrl()]); self::setFailure($url); self::detect($curlResult->getRedirectUrl(), $network, $only_nodeinfo); @@ -410,7 +418,7 @@ class GServer // When the base path doesn't seem to contain a social network we try the complete path. // Most detectable system have to be installed in the root directory. // We checked the base to avoid false positives. - $curlResult = DI::httpClient()->get($url, [HttpClientOptions::TIMEOUT => $xrd_timeout]); + $curlResult = DI::httpClient()->get($url, [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_HTML]); if ($curlResult->isSuccess()) { $urldata = self::analyseRootHeader($curlResult, $serverdata); $urldata = self::analyseRootBody($curlResult, $urldata, $url); @@ -437,7 +445,13 @@ class GServer // All following checks are done for systems that always have got a "host-meta" endpoint. // With this check we don't have to waste time and ressources for dead systems. // Also this hopefully prevents us from receiving abuse messages. - if (empty($serverdata['network']) && !self::validHostMeta($url)) { + $validHostMeta = self::validHostMeta($url); + + if (empty($serverdata['network']) && !$validHostMeta) { + $serverdata = self::detectFromContacts($url, $serverdata); + } + + if (empty($serverdata['network']) && !$validHostMeta) { self::setFailure($url); return false; } @@ -468,6 +482,10 @@ class GServer $serverdata = self::detectGNUSocial($url, $serverdata); } + if (empty($serverdata['network'])) { + $serverdata = self::detectPumpIO($url, $serverdata); + } + $serverdata = array_merge($nodeinfo, $serverdata); } else { $serverdata = $nodeinfo; @@ -491,17 +509,21 @@ class GServer $serverdata['url'] = $url; $serverdata['nurl'] = Strings::normaliseLink($url); - // We take the highest number that we do find - $registeredUsers = $serverdata['registered-users'] ?? 0; + if (in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED])) { + $serverdata = self::detectNetworkViaContacts($url, $serverdata); + } - // On an active server there has to be at least a single user - if (($serverdata['network'] != Protocol::PHANTOM) && ($registeredUsers == 0)) { - $registeredUsers = 1; + if ($serverdata['network'] == Protocol::ACTIVITYPUB) { + $serverdata = self::fetchWeeklyUsage($url, $serverdata); } - if ($serverdata['network'] == Protocol::PHANTOM) { - $serverdata['registered-users'] = max($registeredUsers, 1); - $serverdata = self::detectNetworkViaContacts($url, $serverdata); + $serverdata['registered-users'] = $serverdata['registered-users'] ?? 0; + + // On an active server there has to be at least a single user + if (!in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED]) && ($serverdata['registered-users'] == 0)) { + $serverdata['registered-users'] = 1; + } elseif (in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED])) { + $serverdata['registered-users'] = 0; } $serverdata['next_contact'] = self::getNextUpdateDate(true); @@ -515,11 +537,6 @@ class GServer $ret = DBA::insert('gserver', $serverdata); $id = DBA::lastInsertId(); } else { - // Don't override the network with 'unknown' when there had been a valid entry before - if (($serverdata['network'] == Protocol::PHANTOM) && !empty($gserver['network'])) { - unset($serverdata['network']); - } - $ret = DBA::update('gserver', $serverdata, ['nurl' => $serverdata['nurl']]); $gserver = DBA::selectFirst('gserver', ['id'], ['nurl' => $serverdata['nurl']]); if (DBA::isResult($gserver)) { @@ -527,14 +544,31 @@ class GServer } } - if (!empty($serverdata['network']) && !empty($id) && ($serverdata['network'] != Protocol::PHANTOM)) { + // Count the number of known contacts from this server + if (!empty($id) && !in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED])) { $apcontacts = DBA::count('apcontact', ['gsid' => $id]); - $contacts = DBA::count('contact', ['uid' => 0, 'gsid' => $id]); - $max_users = max($apcontacts, $contacts, $registeredUsers, 1); - if ($max_users > $registeredUsers) { + $contacts = DBA::count('contact', ['uid' => 0, 'gsid' => $id, 'failed' => false]); + $max_users = max($apcontacts, $contacts); + if ($max_users > $serverdata['registered-users']) { Logger::info('Update registered users', ['id' => $id, 'url' => $serverdata['nurl'], 'registered-users' => $max_users]); DBA::update('gserver', ['registered-users' => $max_users], ['id' => $id]); } + + if (empty($serverdata['active-month-users'])) { + $contacts = DBA::count('contact', ["`uid` = ? AND `gsid` = ? AND NOT `failed` AND `last-item` > ?", 0, $id, DateTimeFormat::utc('now - 30 days')]); + if ($contacts > 0) { + Logger::info('Update monthly users', ['id' => $id, 'url' => $serverdata['nurl'], 'monthly-users' => $contacts]); + DBA::update('gserver', ['active-month-users' => $contacts], ['id' => $id]); + } + } + + if (empty($serverdata['active-halfyear-users'])) { + $contacts = DBA::count('contact', ["`uid` = ? AND `gsid` = ? AND NOT `failed` AND `last-item` > ?", 0, $id, DateTimeFormat::utc('now - 180 days')]); + if ($contacts > 0) { + Logger::info('Update halfyear users', ['id' => $id, 'url' => $serverdata['nurl'], 'halfyear-users' => $contacts]); + DBA::update('gserver', ['active-halfyear-users' => $contacts], ['id' => $id]); + } + } } if (!empty($serverdata['network']) && in_array($serverdata['network'], [Protocol::DFRN, Protocol::DIASPORA])) { @@ -554,7 +588,7 @@ class GServer { Logger::info('Discover relay data', ['server' => $server_url]); - $curlResult = DI::httpClient()->get($server_url . '/.well-known/x-social-relay'); + $curlResult = DI::httpClient()->get($server_url . '/.well-known/x-social-relay', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess()) { return; } @@ -649,7 +683,7 @@ class GServer */ private static function fetchStatistics(string $url) { - $curlResult = DI::httpClient()->get($url . '/statistics.json'); + $curlResult = DI::httpClient()->get($url . '/statistics.json', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess()) { return []; } @@ -686,6 +720,21 @@ class GServer } } + if (!empty($data['total_users'])) { + $serverdata['registered-users'] = max($data['total_users'], 1); + } + + if (!empty($data['active_users_monthly'])) { + $serverdata['active-month-users'] = max($data['active_users_monthly'], 0); + } + + if (!empty($data['active_users_halfyear'])) { + $serverdata['active-halfyear-users'] = max($data['active_users_halfyear'], 0); + } + + if (!empty($data['local_posts'])) { + $serverdata['local-posts'] = max($data['local_posts'], 0); + } if (!empty($data['registrations_open'])) { $serverdata['register_policy'] = Register::OPEN; @@ -760,8 +809,7 @@ class GServer */ private static function parseNodeinfo1(string $nodeinfo_url) { - $curlResult = DI::httpClient()->get($nodeinfo_url); - + $curlResult = DI::httpClient()->get($nodeinfo_url, [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess()) { return []; } @@ -800,6 +848,22 @@ class GServer $server['registered-users'] = max($nodeinfo['usage']['users']['total'], 1); } + if (!empty($nodeinfo['usage']['users']['activeMonth'])) { + $server['active-month-users'] = max($nodeinfo['usage']['users']['activeMonth'], 0); + } + + if (!empty($nodeinfo['usage']['users']['activeHalfyear'])) { + $server['active-halfyear-users'] = max($nodeinfo['usage']['users']['activeHalfyear'], 0); + } + + if (!empty($nodeinfo['usage']['localPosts'])) { + $server['local-posts'] = max($nodeinfo['usage']['localPosts'], 0); + } + + if (!empty($nodeinfo['usage']['localComments'])) { + $server['local-comments'] = max($nodeinfo['usage']['localComments'], 0); + } + if (!empty($nodeinfo['protocols']['inbound']) && is_array($nodeinfo['protocols']['inbound'])) { $protocols = []; foreach ($nodeinfo['protocols']['inbound'] as $protocol) { @@ -838,7 +902,7 @@ class GServer */ private static function parseNodeinfo2(string $nodeinfo_url) { - $curlResult = DI::httpClient()->get($nodeinfo_url); + $curlResult = DI::httpClient()->get($nodeinfo_url, [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess()) { return []; } @@ -877,6 +941,22 @@ class GServer $server['registered-users'] = max($nodeinfo['usage']['users']['total'], 1); } + if (!empty($nodeinfo['usage']['users']['activeMonth'])) { + $server['active-month-users'] = max($nodeinfo['usage']['users']['activeMonth'], 0); + } + + if (!empty($nodeinfo['usage']['users']['activeHalfyear'])) { + $server['active-halfyear-users'] = max($nodeinfo['usage']['users']['activeHalfyear'], 0); + } + + if (!empty($nodeinfo['usage']['localPosts'])) { + $server['local-posts'] = max($nodeinfo['usage']['localPosts'], 0); + } + + if (!empty($nodeinfo['usage']['localComments'])) { + $server['local-comments'] = max($nodeinfo['usage']['localComments'], 0); + } + if (!empty($nodeinfo['protocols'])) { $protocols = []; foreach ($nodeinfo['protocols'] as $protocol) { @@ -917,7 +997,7 @@ class GServer */ private static function fetchSiteinfo(string $url, array $serverdata) { - $curlResult = DI::httpClient()->get($url . '/siteinfo.json'); + $curlResult = DI::httpClient()->get($url . '/siteinfo.json', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess()) { return $serverdata; } @@ -956,6 +1036,22 @@ class GServer $serverdata['registered-users'] = max($data['channels_total'], 1); } + if (!empty($data['channels_active_monthly'])) { + $serverdata['active-month-users'] = max($data['channels_active_monthly'], 0); + } + + if (!empty($data['channels_active_halfyear'])) { + $serverdata['active-halfyear-users'] = max($data['channels_active_halfyear'], 0); + } + + if (!empty($data['local_posts'])) { + $serverdata['local-posts'] = max($data['local_posts'], 0); + } + + if (!empty($data['local_comments'])) { + $serverdata['local-comments'] = max($data['local_comments'], 0); + } + if (!empty($data['register_policy'])) { switch ($data['register_policy']) { case 'REGISTER_OPEN': @@ -986,7 +1082,7 @@ class GServer private static function validHostMeta(string $url) { $xrd_timeout = DI::config()->get('system', 'xrd_timeout'); - $curlResult = DI::httpClient()->get($url . '/.well-known/host-meta', [HttpClientOptions::TIMEOUT => $xrd_timeout]); + $curlResult = DI::httpClient()->get($url . '/.well-known/host-meta', [HttpClientOptions::TIMEOUT => $xrd_timeout, HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_XRD_XML]); if (!$curlResult->isSuccess()) { return false; } @@ -1049,16 +1145,18 @@ class GServer return $serverdata; } + $time = time(); foreach ($contacts as $contact) { - $probed = Contact::getByURL($contact); - if (!empty($probed) && in_array($probed['network'], Protocol::FEDERATED)) { + $probed = Contact::getByURL($contact, true); + if (!empty($probed) && !$probed['failed'] && in_array($probed['network'], Protocol::FEDERATED)) { $serverdata['network'] = $probed['network']; break; + } elseif ((time() - $time) > 10) { + // To reduce the stress on remote systems we probe a maximum of 10 seconds + break; } } - $serverdata['registered-users'] = max($serverdata['registered-users'], count($contacts), 1); - return $serverdata; } @@ -1076,7 +1174,7 @@ class GServer { $serverdata['poco'] = ''; - $curlResult = DI::httpClient()->get($url . '/poco'); + $curlResult = DI::httpClient()->get($url . '/poco', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess()) { return $serverdata; } @@ -1106,7 +1204,7 @@ class GServer */ public static function checkMastodonDirectory(string $url, array $serverdata) { - $curlResult = DI::httpClient()->get($url . '/api/v1/directory?limit=1'); + $curlResult = DI::httpClient()->get($url . '/api/v1/directory?limit=1', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess()) { return $serverdata; } @@ -1133,8 +1231,7 @@ class GServer */ private static function detectPeertube(string $url, array $serverdata) { - $curlResult = DI::httpClient()->get($url . '/api/v1/config'); - + $curlResult = DI::httpClient()->get($url . '/api/v1/config', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) { return $serverdata; } @@ -1181,8 +1278,7 @@ class GServer */ private static function detectNextcloud(string $url, array $serverdata) { - $curlResult = DI::httpClient()->get($url . '/status.php'); - + $curlResult = DI::httpClient()->get($url . '/status.php', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) { return $serverdata; } @@ -1205,6 +1301,65 @@ class GServer return $serverdata; } + private static function fetchWeeklyUsage(string $url, array $serverdata) { + $curlResult = DI::httpClient()->get($url . '/api/v1/instance/activity', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); + if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) { + return $serverdata; + } + + $data = json_decode($curlResult->getBody(), true); + if (empty($data)) { + return $serverdata; + } + + $current_week = []; + foreach ($data as $week) { + // Use only data from a full week + if (empty($week['week']) || (time() - $week['week']) < 7 * 24 * 60 * 60) { + continue; + } + + // Most likely the data is sorted correctly. But we better are safe than sorry + if (empty($current_week['week']) || ($current_week['week'] < $week['week'])) { + $current_week = $week; + } + } + + if (!empty($current_week['logins'])) { + $serverdata['active-week-users'] = max($current_week['logins'], 0); + } + + return $serverdata; + } + + /** + * Detects the server network type from contacts of that server + * + * @param string $url URL of the given server + * @param array $serverdata array with server data + * + * @return array server data + */ + private static function detectFromContacts(string $url, array $serverdata) + { + $gserver = DBA::selectFirst('gserver', ['id'], ['nurl' => Strings::normaliseLink($url)]); + if (empty($gserver)) { + return $serverdata; + } + + $contact = Contact::selectFirst(['id'], ['uid' => 0, 'failed' => false, 'gsid' => $gserver['id']]); + + // Via probing we can be sure that the server is responding + if (Contact::updateFromProbe($contact['id'])) { + $contact = Contact::selectFirst(['network', 'failed'], ['id' => $contact['id']]); + if (!$contact['failed'] && in_array($contact['network'], Protocol::FEDERATED)) { + $serverdata['network'] = $contact['network']; + } + } + + return $serverdata; + } + /** * Detects data from a given server url if it was a mastodon alike system * @@ -1215,8 +1370,7 @@ class GServer */ private static function detectMastodonAlikes(string $url, array $serverdata) { - $curlResult = DI::httpClient()->get($url . '/api/v1/instance'); - + $curlResult = DI::httpClient()->get($url . '/api/v1/instance', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) { return $serverdata; } @@ -1281,7 +1435,7 @@ class GServer */ private static function detectHubzilla(string $url, array $serverdata) { - $curlResult = DI::httpClient()->get($url . '/api/statusnet/config.json'); + $curlResult = DI::httpClient()->get($url . '/api/statusnet/config.json', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) { return $serverdata; } @@ -1366,7 +1520,57 @@ class GServer } return $val; - } + } + + /** + * Detect if the URL belongs to a pump.io server + * + * @param string $url URL of the given server + * @param array $serverdata array with server data + * + * @return array server data + */ + private static function detectPumpIO(string $url, array $serverdata) + { + $curlResult = DI::httpClient()->get($url . '/.well-known/host-meta.json', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); + if (!$curlResult->isSuccess()) { + return $serverdata; + } + + $data = json_decode($curlResult->getBody(), true); + if (empty($data['links'])) { + return $serverdata; + + } + + // We are looking for some endpoints that are typical for pump.io + $trust = 0; + foreach ($data['links'] as $link) { + if (empty($link['rel'])) { + continue; + } + if (in_array($link['rel'], ['registration_endpoint', 'dialback', 'http://apinamespace.org/activitypub/whoami'])) { + ++$trust; + } + } + + if ($trust == 3) { + $serverdata['detection-method'] = self::DETECT_PUMPIO; + + $serverdata['platform'] = 'pumpio'; + $serverdata['version'] = ''; + $serverdata['network'] = Protocol::PUMPIO; + + $servers = $curlResult->getHeader('Server'); + foreach ($servers as $server) { + if (preg_match("#pump.io/(.*)\s#U", $server, $matches)) { + $serverdata['version'] = $matches[1]; + } + } + } + + return $serverdata; + } /** * Detect if the URL belongs to a GNU Social server @@ -1379,7 +1583,7 @@ class GServer private static function detectGNUSocial(string $url, array $serverdata) { // Test for GNU Social - $curlResult = DI::httpClient()->get($url . '/api/gnusocial/version.json'); + $curlResult = DI::httpClient()->get($url . '/api/gnusocial/version.json', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') && ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) { $serverdata['platform'] = 'gnusocial'; @@ -1397,7 +1601,7 @@ class GServer } // Test for Statusnet - $curlResult = DI::httpClient()->get($url . '/api/statusnet/version.json'); + $curlResult = DI::httpClient()->get($url . '/api/statusnet/version.json', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') && ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) { @@ -1433,9 +1637,11 @@ class GServer */ private static function detectFriendica(string $url, array $serverdata) { - $curlResult = DI::httpClient()->get($url . '/friendica/json'); + // There is a bug in some versions of Friendica that will return an ActivityStream actor when the content type "application/json" is requested. + // Because of this me must not use ACCEPT_JSON here. + $curlResult = DI::httpClient()->get($url . '/friendica/json', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_DEFAULT]); if (!$curlResult->isSuccess()) { - $curlResult = DI::httpClient()->get($url . '/friendika/json'); + $curlResult = DI::httpClient()->get($url . '/friendika/json', [HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_DEFAULT]); $friendika = true; $platform = 'Friendika'; } else { @@ -1511,6 +1717,10 @@ class GServer return $serverdata; } + // Using only body information we cannot safely detect a lot of systems. + // So we define a list of platforms that we can detect safely. + $valid_platforms = ['friendica', 'friendika', 'diaspora', 'mastodon', 'hubzilla', 'misskey', 'peertube', 'wordpress', 'write.as']; + $doc = new DOMDocument(); @$doc->loadHTML($curlResult->getBody()); $xpath = new DOMXPath($doc); @@ -1560,11 +1770,8 @@ class GServer $serverdata['version'] = $version_part[1]; // We still do need a reliable test if some AP plugin is activated - if (DBA::exists('apcontact', ['baseurl' => $url])) { - $serverdata['network'] = Protocol::ACTIVITYPUB; - } else { - $serverdata['network'] = Protocol::FEED; - } + // By now we just check in a later process for some known contacts + $serverdata['network'] = Protocol::FEED; if ($serverdata['detection-method'] == self::DETECT_MANUAL) { $serverdata['detection-method'] = self::DETECT_BODY; @@ -1624,7 +1831,11 @@ class GServer } } - if (!empty($serverdata['network']) && ($serverdata['detection-method'] == self::DETECT_MANUAL)) { + if (!empty($serverdata['platform']) && in_array($serverdata['detection-method'], [self::DETECT_MANUAL, self::DETECT_BODY]) && !in_array($serverdata['platform'], $valid_platforms)) { + $serverdata['network'] = Protocol::PHANTOM; + $serverdata['version'] = ''; + $serverdata['detection-method'] = self::DETECT_MANUAL; + } elseif (!empty($serverdata['network']) && ($serverdata['detection-method'] == self::DETECT_MANUAL)) { $serverdata['detection-method'] = self::DETECT_BODY; } @@ -1735,7 +1946,7 @@ class GServer $protocols = ['activitypub', 'diaspora', 'dfrn', 'ostatus']; foreach ($protocols as $protocol) { $query = '{nodes(protocol:"' . $protocol . '"){host}}'; - $curlResult = DI::httpClient()->fetch('https://the-federation.info/graphql?query=' . urlencode($query)); + $curlResult = DI::httpClient()->fetch('https://the-federation.info/graphql?query=' . urlencode($query), 0, HttpClient::ACCEPT_JSON); if (!empty($curlResult)) { $data = json_decode($curlResult, true); if (!empty($data['data']['nodes'])) { @@ -1752,8 +1963,7 @@ class GServer if (!empty($accesstoken)) { $api = 'https://instances.social/api/1.0/instances/list?count=0'; - $curlResult = DI::httpClient()->get($api, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . $accesstoken]]]); - + $curlResult = DI::httpClient()->get($api, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . $accesstoken]], HttpClientOptions::ACCEPT_CONTENT => HttpClient::ACCEPT_JSON]); if ($curlResult->isSuccess()) { $servers = json_decode($curlResult->getBody(), true);