relatica/lib/services/fediverse_server_validator....

84 wiersze
2.6 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 {
final knownServers = <String, ServerData>{};
FutureResult<bool, ExecError> checkIfFediverseLink(String url) async {
final uri = Uri.tryParse(url);
if (uri == null) {
return buildErrorResult(
type: ErrorType.parsingError,
message: 'Invalid URL: $url',
);
}
final domain = uri.host;
ServerData? data = knownServers[domain];
if (data != null) {
return Result.ok(data.isFediverse);
}
final serverData = await refreshServerData(domain);
knownServers[domain] = serverData;
return Result.ok(serverData.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));
}
}