mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-19 14:03:31 +00:00
90 lines
2.8 KiB
Dart
90 lines
2.8 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:result_monad/result_monad.dart';
|
|
|
|
import '../models/exec_error.dart';
|
|
import '../models/server_data.dart';
|
|
import '../utils/network_utils.dart';
|
|
|
|
class FediverseServiceValidator {
|
|
static const softwareTypeDiaspora = 'diaspora';
|
|
|
|
final knownServers = <String, ServerData>{};
|
|
|
|
FutureResult<ServerData, ExecError> getServerData(String url) async {
|
|
final uri = Uri.tryParse(url);
|
|
if (uri == null || uri.scheme != 'https') {
|
|
return buildErrorResult(
|
|
type: ErrorType.parsingError,
|
|
message: 'Invalid URL: $url',
|
|
);
|
|
}
|
|
|
|
final domain = uri.host;
|
|
ServerData? data = knownServers[domain];
|
|
if (data != null) {
|
|
return Result.ok(data);
|
|
}
|
|
|
|
final serverData = await refreshServerData(domain);
|
|
knownServers[domain] = serverData;
|
|
return Result.ok(serverData);
|
|
}
|
|
|
|
FutureResult<bool, ExecError> checkIfFediverseLink(String url) async {
|
|
final dataResult = await getServerData(url);
|
|
return dataResult.mapValue((d) => d.isFediverse);
|
|
}
|
|
|
|
static Future<ServerData> refreshServerData(String domainName) async {
|
|
final uri = Uri.https(
|
|
domainName,
|
|
'/.well-known/nodeinfo',
|
|
);
|
|
final result = await getUrl(uri)
|
|
.andThenSuccessAsync((page) async {
|
|
return jsonDecode(page.data);
|
|
})
|
|
.andThenAsync(
|
|
(json) async =>
|
|
json is Map<String, dynamic> ? Result.ok(json) : Result.error(''),
|
|
)
|
|
.andThenSuccessAsync((json) async => json['links'] ?? [])
|
|
.andThenAsync(
|
|
(nodeInfos) async => nodeInfos.isNotEmpty
|
|
? Result.ok(nodeInfos.last)
|
|
: Result.error(''),
|
|
)
|
|
.andThenAsync((nodeInfo) async {
|
|
final rel = nodeInfo['rel']?.toString() ?? '';
|
|
if (!rel.startsWith('http://nodeinfo.diaspora.software/ns/schema/')) {
|
|
return Result.error('');
|
|
}
|
|
|
|
final nodeInfoUrl = Uri.tryParse(nodeInfo['href'] ?? '');
|
|
if (nodeInfoUrl == null) {
|
|
return Result.error('');
|
|
}
|
|
return await getUrl(nodeInfoUrl);
|
|
})
|
|
.andThenSuccessAsync(
|
|
(nodeInfoData) async => jsonDecode(nodeInfoData.data))
|
|
.andThenSuccessAsync((nodeInfoJson) async {
|
|
final softwareName =
|
|
nodeInfoJson['software']?['name']?.toString() ?? '';
|
|
final softwareVersion =
|
|
nodeInfoJson['software']?['version']?.toString() ?? '';
|
|
final isFediverse =
|
|
softwareName.isNotEmpty && softwareVersion.isNotEmpty;
|
|
return ServerData(
|
|
domainName: domainName,
|
|
isFediverse: isFediverse,
|
|
softwareName: softwareName,
|
|
softwareVersion: softwareVersion,
|
|
);
|
|
});
|
|
|
|
return result.getValueOrElse(
|
|
() => ServerData(domainName: domainName, isFediverse: false));
|
|
}
|
|
}
|