mirror of
https://gitlab.com/mysocialportal/fediverse-archiving-tools.git
synced 2024-10-18 08:53:31 +00:00
103 lines
3 KiB
Dart
103 lines
3 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:uuid/uuid.dart';
|
|
|
|
import 'extensions.dart';
|
|
import 'friendica_client.dart';
|
|
import 'models.dart';
|
|
|
|
class ImageArchiver {
|
|
final FriendicaClient client;
|
|
final _images = <String, ImageEntry>{};
|
|
late final Directory imageDirectory;
|
|
|
|
List<ImageEntry> get images => List.unmodifiable(_images.values);
|
|
|
|
ImageArchiver(this.client, Directory baseDirectory) {
|
|
final imageDirPath = p.join(baseDirectory.path, 'images');
|
|
imageDirectory = Directory(imageDirPath);
|
|
imageDirectory.createSync(recursive: true);
|
|
}
|
|
|
|
bool addDirectEntries(ImageEntry entry) {
|
|
final alreadyExists = _images.containsKey(entry.url);
|
|
_images[entry.url] = entry;
|
|
return alreadyExists;
|
|
}
|
|
|
|
Future<List<ImageEntry>> addEntryImages(FriendicaEntry entry) async {
|
|
final imageEntries = <ImageEntry>[];
|
|
for (final imageUrl in entry.images) {
|
|
if (_images.containsKey(imageUrl)) {
|
|
continue;
|
|
}
|
|
final url = Uri.parse(imageUrl);
|
|
final imageResponse = await client.getUrl(url);
|
|
if (imageResponse.isFailure) {
|
|
print(imageResponse.error);
|
|
continue;
|
|
}
|
|
|
|
if (imageResponse.value.statusCode == 200) {
|
|
final contents = <int>[];
|
|
await for (var data in imageResponse.value) {
|
|
contents.addAll(data);
|
|
}
|
|
final extension = calculateExtensions(contents);
|
|
final filename = Uuid().v4().replaceAll('-', '') + extension;
|
|
final filePath = p.join(imageDirectory.path, filename);
|
|
await File(filePath).writeAsBytes(contents);
|
|
final newEntry = ImageEntry(
|
|
postId: entry.id.toString(),
|
|
localFilename: filename,
|
|
url: imageUrl);
|
|
_images[imageUrl] = newEntry;
|
|
imageEntries.add(newEntry);
|
|
} else {
|
|
print(
|
|
'Error response attempting to retrieve image $imageUrl: ${imageResponse.value.statusCode}');
|
|
}
|
|
}
|
|
|
|
return imageEntries;
|
|
}
|
|
|
|
String calculateExtensions(List<int> imageBytes) {
|
|
// Using table from https://www.sparkhound.com/blog/detect-image-file-types-through-byte-arrays
|
|
final bmp = ascii.encode("BM").toList(); // BMP
|
|
final gif = ascii.encode("GIF").toList(); // GIF
|
|
const png = <int>[137, 80, 78, 71]; // PNG
|
|
const tiff = <int>[73, 73, 42]; // TIFF
|
|
const tiff2 = <int>[77, 77, 42]; // TIFF
|
|
const jpeg = <int>[255, 216, 255, 224]; // jpeg
|
|
const jpeg2 = <int>[255, 216, 255, 225]; // jpeg canon
|
|
|
|
final firstFour = imageBytes.sublist(0, 4);
|
|
|
|
if (firstFour.equals(jpeg) || firstFour.equals(jpeg2)) {
|
|
return '.jpg';
|
|
}
|
|
|
|
if (firstFour.equals(png)) {
|
|
return '.png';
|
|
}
|
|
|
|
final firstThree = imageBytes.sublist(0, 3);
|
|
if (firstThree.equals(gif)) {
|
|
return '.gif';
|
|
}
|
|
|
|
if (firstThree.equals(tiff) || firstThree.equals(tiff2)) {
|
|
return '.tif';
|
|
}
|
|
|
|
final firstTwo = imageBytes.sublist(0, 2);
|
|
if (firstTwo.equals(bmp)) {
|
|
return '.bmp';
|
|
}
|
|
|
|
return '';
|
|
}
|
|
}
|