<?php
/**
- * @copyright Copyright (C) 2010-2023, the Friendica project
+ * @copyright Copyright (C) 2010-2024, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
const DETECT_STATUS_PHP = 17; // Nextcloud
const DETECT_V1_CONFIG = 18;
const DETECT_SYSTEM_ACTOR = 20; // Mistpark, Osada, Roadhouse, Zap
+ const DETECT_THREADS = 21;
// Standardized endpoints
const DETECT_STATISTICS_JSON = 100;
* @param string $pattern
*
* @return array
- *
* @throws Exception
*/
public static function listByDomainPattern(string $pattern): array
* @param bool $undetected
*
* @return string
- *
* @throws Exception
*/
public static function getNextUpdateDate(bool $success, string $created = '', string $last_contact = '', bool $undetected = false): string
}
if ($curlResult->isSuccess()) {
- $json = json_decode($curlResult->getBody(), true);
+ $json = json_decode($curlResult->getBodyString(), true);
if (!empty($json) && is_array($json)) {
$data = self::fetchDataFromSystemActor($json, $serverdata);
$serverdata = $data['server'];
if (!$html_fetched && !in_array($serverdata['detection-method'], [self::DETECT_SYSTEM_ACTOR, self::DETECT_AP_COLLECTION])) {
$curlResult = DI::httpClient()->get($url, HttpClientAccept::HTML);
}
- } elseif (!$html_fetched && (strlen($curlResult->getBody()) < 1000)) {
+ } elseif (!$html_fetched && (strlen($curlResult->getBodyString()) < 1000)) {
$curlResult = DI::httpClient()->get($url, HttpClientAccept::HTML);
}
}
}
- if (!$curlResult->isSuccess() || empty($curlResult->getBody())) {
+ if (!$curlResult->isSuccess() || empty($curlResult->getBodyString())) {
self::setFailureByUrl($url);
return false;
}
+ if (in_array($url, ['https://www.threads.net', 'https://threads.net'])) {
+ $serverdata['detection-method'] = self::DETECT_THREADS;
+ $serverdata['network'] = Protocol::ACTIVITYPUB;
+ $serverdata['platform'] = 'threads';
+ }
+
if (($serverdata['network'] == Protocol::PHANTOM) || in_array($serverdata['detection-method'], self::DETECT_UNSPECIFIC)) {
$serverdata = self::detectMastodonAlikes($url, $serverdata);
}
}
$serverdata['registered-users'] = $serverdata['registered-users'] ?? 0;
+ $serverdata['next_contact'] = self::getNextUpdateDate(true, '', '', in_array($serverdata['network'], [Protocol::PHANTOM, Protocol::FEED]));
+ $serverdata['last_contact'] = DateTimeFormat::utcNow();
+ $serverdata['failed'] = false;
// Numbers above a reasonable value (10 millions) are ignored
if ($serverdata['registered-users'] > 10000000) {
* @param string $server_url address of the server
*
* @return void
- *
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function discoverRelay(string $server_url)
return;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (!is_array($data)) {
return;
}
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $serverdata;
}
return [];
}
- $nodeinfo = json_decode($httpResult->getBody(), true);
+ $nodeinfo = json_decode($httpResult->getBodyString(), true);
if (!is_array($nodeinfo) || empty($nodeinfo['links'])) {
return [];
return [];
}
- $nodeinfo = json_decode($curlResult->getBody(), true);
+ $nodeinfo = json_decode($curlResult->getBodyString(), true);
if (!is_array($nodeinfo)) {
return [];
return [];
}
- $nodeinfo = json_decode($curlResult->getBody(), true);
+ $nodeinfo = json_decode($curlResult->getBodyString(), true);
if (!is_array($nodeinfo)) {
return [];
}
}
}
+ // Special treatment for NextCloud, since there you can freely define your software name
+ if (!empty($nodeinfo['rootUrl']) && in_array(parse_url($nodeinfo['rootUrl'], PHP_URL_PATH), ['/index.php/apps/social', '/apps/social'])) {
+ $server['platform'] = 'nextcloud';
+ }
+
if (!empty($nodeinfo['metadata']['nodeName'])) {
$server['site_name'] = $nodeinfo['metadata']['nodeName'];
}
/**
* Parses NodeInfo2 protocol 1.0
*
- * @see https://github.com/jaywink/nodeinfo2/blob/master/PROTOCOL.md
- *
- * @param string $nodeinfo_url address of the nodeinfo path
+ * @param ICanHandleHttpResponses $httpResult
*
* @return array Server data
- *
+ * @see https://github.com/jaywink/nodeinfo2/blob/master/PROTOCOL.md
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function parseNodeinfo210(ICanHandleHttpResponses $httpResult): array
return [];
}
- $nodeinfo = json_decode($httpResult->getBody(), true);
+ $nodeinfo = json_decode($httpResult->getBodyString(), true);
if (!is_array($nodeinfo)) {
return [];
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $serverdata;
}
}
foreach ($tags as $tag) {
- if ((($tag['as:name'] ?? '') == 'Protocol') && (($tag['sc:value'] ?? '') == 'nomad')) {
+ if ((($tag['as:name'] ?? '') == 'Protocol') && in_array('nomad', [$tag['sc:value'] ?? '', $tag['as:content'] ?? ''])) {
return true;
}
}
{
$name = 'nomad';
$curlResult = DI::httpClient()->get($url . '/manifest', 'application/manifest+json');
- if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
+ if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) {
return $name;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $name;
}
private static function getNomadVersion(string $url): string
{
$curlResult = DI::httpClient()->get($url . '/api/z/1.0/version', HttpClientAccept::JSON);
- if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
+ if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) {
return '';
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return '';
}
return false;
}
- $xrd = XML::parseString($curlResult->getBody(), true);
+ $xrd = XML::parseString($curlResult->getBodyString(), true);
if (!is_object($xrd)) {
return false;
}
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $serverdata;
}
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $serverdata;
}
private static function detectPeertube(string $url, array $serverdata): array
{
$curlResult = DI::httpClient()->get($url . '/api/v1/config', HttpClientAccept::JSON);
- if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
+ if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) {
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $serverdata;
}
private static function detectNextcloud(string $url, array $serverdata, bool $validHostMeta): array
{
$curlResult = DI::httpClient()->get($url . '/status.php', HttpClientAccept::JSON);
- if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
+ if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) {
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $serverdata;
}
private static function fetchWeeklyUsage(string $url, array $serverdata): array
{
$curlResult = DI::httpClient()->get($url . '/api/v1/instance/activity', HttpClientAccept::JSON);
- if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
+ if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) {
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $serverdata;
}
private static function detectMastodonAlikes(string $url, array $serverdata): array
{
$curlResult = DI::httpClient()->get($url . '/api/v1/instance', HttpClientAccept::JSON);
- if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
+ if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) {
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data)) {
return $serverdata;
}
private static function detectHubzilla(string $url, array $serverdata): array
{
$curlResult = DI::httpClient()->get($url . '/api/statusnet/config.json', HttpClientAccept::JSON);
- if (!$curlResult->isSuccess() || ($curlResult->getBody() == '')) {
+ if (!$curlResult->isSuccess() || ($curlResult->getBodyString() == '')) {
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data) || empty($data['site'])) {
return $serverdata;
}
{
// Test for GNU Social
$curlResult = DI::httpClient()->get($url . '/api/gnusocial/version.json', HttpClientAccept::JSON);
- if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') &&
- ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) {
+ if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') &&
+ ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) {
$serverdata['platform'] = 'gnusocial';
// Remove junk that some GNU Social servers return
- $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBody());
+ $serverdata['version'] = str_replace(chr(239) . chr(187) . chr(191), '', $curlResult->getBodyString());
$serverdata['version'] = str_replace(["\r", "\n", "\t"], '', $serverdata['version']);
$serverdata['version'] = trim($serverdata['version'], '"');
$serverdata['network'] = Protocol::OSTATUS;
// Test for Statusnet
$curlResult = DI::httpClient()->get($url . '/api/statusnet/version.json', HttpClientAccept::JSON);
- if ($curlResult->isSuccess() && ($curlResult->getBody() != '{"error":"not implemented"}') &&
- ($curlResult->getBody() != '') && (strlen($curlResult->getBody()) < 30)) {
+ if ($curlResult->isSuccess() && ($curlResult->getBodyString() != '{"error":"not implemented"}') &&
+ ($curlResult->getBodyString() != '') && (strlen($curlResult->getBodyString()) < 30)) {
// Remove junk that some GNU Social servers return
- $serverdata['version'] = str_replace(chr(239).chr(187).chr(191), '', $curlResult->getBody());
+ $serverdata['version'] = str_replace(chr(239).chr(187).chr(191), '', $curlResult->getBodyString());
$serverdata['version'] = str_replace(["\r", "\n", "\t"], '', $serverdata['version']);
$serverdata['version'] = trim($serverdata['version'], '"');
return $serverdata;
}
- $data = json_decode($curlResult->getBody(), true);
+ $data = json_decode($curlResult->getBodyString(), true);
if (empty($data) || empty($data['version'])) {
return $serverdata;
}
$api = 'https://instances.social/api/1.0/instances/list?count=0';
$curlResult = DI::httpClient()->get($api, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . $accesstoken]]]);
if ($curlResult->isSuccess()) {
- $servers = json_decode($curlResult->getBody(), true);
+ $servers = json_decode($curlResult->getBodyString(), true);
if (!empty($servers['instances'])) {
foreach ($servers['instances'] as $server) {