kopia lustrzana https://gitlab.com/mysocialportal/relatica
73 wiersze
2.2 KiB
Dart
73 wiersze
2.2 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:html/parser.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:result_monad/result_monad.dart';
|
|
|
|
import '../models/exec_error.dart';
|
|
import '../models/link_preview_data.dart';
|
|
|
|
const ogTitleKey = 'og:title';
|
|
const ogDescriptionKey = 'og:description';
|
|
const ogSiteNameKey = 'og:site_name';
|
|
const ogImageKey = 'og:image';
|
|
|
|
FutureResult<LinkPreviewData, ExecError> getLinkPreview(String url) async {
|
|
final result = await _getOpenGraphData(url);
|
|
return result.andThenSuccess((ogData) {
|
|
final title = ogData.getValue(ogTitleKey);
|
|
final description = ogData.getValue(ogDescriptionKey);
|
|
final siteName = ogData.getValue(ogSiteNameKey);
|
|
final availableImageUrls = ogData.getValues(ogImageKey);
|
|
final selectedImageUrl =
|
|
availableImageUrls.isEmpty ? '' : availableImageUrls.first;
|
|
return LinkPreviewData(
|
|
link: url,
|
|
title: title,
|
|
description: description,
|
|
siteName: siteName,
|
|
availableImageUrls: availableImageUrls,
|
|
selectedImageUrl: selectedImageUrl,
|
|
);
|
|
}).execErrorCast();
|
|
}
|
|
|
|
FutureResult<List<MapEntry<String, String>>, dynamic> _getOpenGraphData(
|
|
String url) async {
|
|
return runCatchingAsync<List<MapEntry<String, String>>>(() async {
|
|
final response = await http.get(Uri.parse(url));
|
|
if (response.statusCode != 200) {
|
|
return buildErrorResult(
|
|
type: ErrorType.serverError,
|
|
message: 'Error getting link preview: ${response.statusCode}',
|
|
);
|
|
}
|
|
|
|
final rawHtml = utf8.decode(response.bodyBytes);
|
|
final htmlDoc = parse(rawHtml);
|
|
final openGraphTags = htmlDoc.head
|
|
?.querySelectorAll("[property*='og:']")
|
|
.map((p) {
|
|
final key = p.attributes['property'] ?? '';
|
|
final value = p.attributes['content'] ?? '';
|
|
return MapEntry(key, value);
|
|
})
|
|
.where((e) => e.key.isNotEmpty)
|
|
.toList();
|
|
return Result.ok(openGraphTags ?? []);
|
|
});
|
|
}
|
|
|
|
extension OpenGraphFinders on List<MapEntry<String, String>> {
|
|
String getValue(String key) {
|
|
return firstWhere(
|
|
(e) => e.key == key,
|
|
orElse: () => const MapEntry('', ''),
|
|
).value;
|
|
}
|
|
|
|
List<String> getValues(String key) {
|
|
return where((e) => e.key == key).map((e) => e.value).toList();
|
|
}
|
|
}
|