using System.Diagnostics; using System.Text.Json; using View_by_Distance.Metadata.Models.Stateless; using View_by_Distance.Shared.Models.Stateless; namespace View_by_Distance.Metadata.Models; /// // Dictionary>> /// public class B_Metadata { public List AngleBracketCollection { get; } private readonly Serilog.ILogger? _Log; private readonly bool _PropertiesChangedForMetadata; private readonly bool _ForceMetadataLastWriteTimeToCreationTime; private readonly JsonSerializerOptions _WriteIndentedJsonSerializerOptions; public static string DateTimeFormat() => "ddd MMM dd HH:mm:ss yyyy"; public B_Metadata(bool forceMetadataLastWriteTimeToCreationTime, bool propertiesChangedForMetadata) { AngleBracketCollection = new List(); _Log = Serilog.Log.ForContext(); _PropertiesChangedForMetadata = propertiesChangedForMetadata; _ForceMetadataLastWriteTimeToCreationTime = forceMetadataLastWriteTimeToCreationTime; _WriteIndentedJsonSerializerOptions = new JsonSerializerOptions { WriteIndented = true }; } public override string ToString() { string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); return result; } private Dictionary>> GetMetadataCollection(string subFile) { Dictionary>> results = new(); if (_Log is null) throw new Exception($"{nameof(_Log)} is null!"); try { object? @object; string? tagDescription; int type = (int)IExif.Tags.Orientation; List tagNames = new(); string key = nameof(IExif.Tags.Orientation); IReadOnlyList directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(subFile); foreach (MetadataExtractor.Directory directory in directories) { if (!results.ContainsKey(directory.Name)) results.Add(directory.Name, new()); foreach (MetadataExtractor.Tag tag in directory.Tags) { tagNames.Add(tag.Name); if (string.IsNullOrEmpty(tag.Description)) continue; results[directory.Name].Add(new KeyValuePair(string.Concat(tag.Type, '\t', tag.Name), tag.Description)); } if (tagNames.Contains(key) && !results.ContainsKey(key)) { @object = directory.GetObject(type); if (@object is null) continue; tagDescription = @object.ToString(); if (string.IsNullOrEmpty(tagDescription)) continue; results.Add(key, new() { new(string.Concat(type, '\t', key), tagDescription) }); } } } catch (Exception) { _Log.Info(string.Concat(new StackFrame().GetMethod()?.Name, " <", subFile, ">")); } return results; } public (int, List>) GetMetadataCollection(List> subFileTuples, List parseExceptions, string subFile, string relativePath, string fileNameWithoutExtension) { List> results = new(); Dictionary>>? dictionary; string json = string.Empty; string[] changesFrom = Array.Empty(); List dateTimes = (from l in subFileTuples where changesFrom.Contains(l.Item1) select l.Item2).ToList(); FileInfo fileInfo = new(Path.Combine(AngleBracketCollection[0].Replace("<>", "{}"), string.Concat(fileNameWithoutExtension, ".json"))); if (!fileInfo.Exists) { if (fileInfo.Directory?.Parent is null) throw new Exception(); string parentCheck = Path.Combine(fileInfo.Directory.Parent.FullName, fileInfo.Name); if (File.Exists(parentCheck)) { File.Move(parentCheck, fileInfo.FullName); fileInfo.Refresh(); } } if (_ForceMetadataLastWriteTimeToCreationTime && !fileInfo.Exists && File.Exists(Path.ChangeExtension(fileInfo.FullName, ".delete"))) { File.Move(Path.ChangeExtension(fileInfo.FullName, ".delete"), fileInfo.FullName); fileInfo.Refresh(); } if (_ForceMetadataLastWriteTimeToCreationTime && fileInfo.Exists && fileInfo.LastWriteTime != fileInfo.CreationTime) { File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); fileInfo.Refresh(); } if (_PropertiesChangedForMetadata) dictionary = new(); else if (!fileInfo.Exists) dictionary = new(); else if (dateTimes.Any() && dateTimes.Max() > fileInfo.LastWriteTime) dictionary = new(); else { json = File.ReadAllText(fileInfo.FullName); try { dictionary = JsonSerializer.Deserialize>>>(json); if (dictionary is null) throw new Exception(); subFileTuples.Add(new Tuple(nameof(B_Metadata), fileInfo.LastWriteTime)); } catch (Exception) { dictionary = new(); parseExceptions.Add(nameof(B_Metadata)); } } if (dictionary is null || !dictionary.Any()) { dictionary = GetMetadataCollection(subFile); json = JsonSerializer.Serialize(dictionary, _WriteIndentedJsonSerializerOptions); if (Property.Models.Stateless.IPath.WriteAllText(fileInfo.FullName, json, compareBeforeWrite: true)) { if (!_ForceMetadataLastWriteTimeToCreationTime && (!fileInfo.Exists || fileInfo.LastWriteTime == fileInfo.CreationTime)) subFileTuples.Add(new Tuple(nameof(B_Metadata), DateTime.Now)); else { File.SetLastWriteTime(fileInfo.FullName, fileInfo.CreationTime); fileInfo.Refresh(); subFileTuples.Add(new Tuple(nameof(B_Metadata), fileInfo.CreationTime)); } } } foreach (KeyValuePair>> keyValuePair in dictionary) { foreach (KeyValuePair keyValue in keyValuePair.Value) results.Add(new(string.Concat(keyValuePair.Key, '\t', keyValue.Key), keyValue.Value)); } return new(dictionary.Count, results); } public static List> GetFiltered(List> metadataCollection) { List> results = new(); foreach (KeyValuePair keyValuePair in metadataCollection) { if (keyValuePair.Key.Contains("File") || keyValuePair.Key.Contains("JPEG") || keyValuePair.Key.Contains("Orientation") || keyValuePair.Key.Contains("Thumbnail")) continue; results.Add(new(keyValuePair.Key, keyValuePair.Value)); } if (!results.Any()) results = metadataCollection; return results; } public static string GetUniqueImageId(List> metadataCollection) { string result = string.Empty; const string exifSubIFD = "Exif SubIFD"; const string uniqueImageID = "42016\tUnique Image ID"; List uniqueImageIDs = (from l in metadataCollection where l.Key.StartsWith(exifSubIFD) && l.Key.EndsWith(uniqueImageID) select l.Value).ToList(); if (uniqueImageIDs.Any()) result = uniqueImageIDs[0]; return result; } }