|
|
|
@ -3,9 +3,12 @@ using Microsoft.Extensions.Configuration;
|
|
|
|
|
using Phares.Shared;
|
|
|
|
|
using Serilog;
|
|
|
|
|
using ShellProgressBar;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using View_by_Distance.Metadata.Models;
|
|
|
|
|
using View_by_Distance.Rename.Models;
|
|
|
|
|
using View_by_Distance.Shared.Models;
|
|
|
|
|
using View_by_Distance.Shared.Models.Methods;
|
|
|
|
|
using View_by_Distance.Shared.Models.Stateless.Methods;
|
|
|
|
|
|
|
|
|
|
namespace View_by_Distance.Rename;
|
|
|
|
|
|
|
|
|
@ -18,7 +21,7 @@ public class Rename
|
|
|
|
|
List<FileHolder> FileHolders,
|
|
|
|
|
bool FfmpegFilesPresent,
|
|
|
|
|
DateTime? DateTimeOriginal,
|
|
|
|
|
DateTime?[] DateTimes,
|
|
|
|
|
DateTime[] DateTimes,
|
|
|
|
|
int? Id);
|
|
|
|
|
|
|
|
|
|
private readonly AppSettings _AppSettings;
|
|
|
|
@ -85,7 +88,7 @@ public class Rename
|
|
|
|
|
if (string.IsNullOrEmpty(directory))
|
|
|
|
|
continue;
|
|
|
|
|
fileName = Path.GetFileName(file);
|
|
|
|
|
if (!fileName.EndsWith(".id"))
|
|
|
|
|
if (!fileName.EndsWith(".paddedId"))
|
|
|
|
|
continue;
|
|
|
|
|
lines = File.ReadAllLines(file);
|
|
|
|
|
if (lines.Length < 2)
|
|
|
|
@ -99,20 +102,23 @@ public class Rename
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<Record> GetRecords(int offset, ProgressBar progressBar, string[] files)
|
|
|
|
|
private List<Record> GetRecords(B_Metadata metadata, int offset, ProgressBar progressBar, string[] files)
|
|
|
|
|
{
|
|
|
|
|
List<Record> results = new();
|
|
|
|
|
int? id;
|
|
|
|
|
string? message;
|
|
|
|
|
string? directory;
|
|
|
|
|
DateTime?[] dateTimes;
|
|
|
|
|
DateTime[] dateTimes;
|
|
|
|
|
FileHolder fileHolder;
|
|
|
|
|
string[]? ffmpegFiles;
|
|
|
|
|
bool isIgnoreExtension;
|
|
|
|
|
DateTime? dateTimeOriginal;
|
|
|
|
|
bool isValidImageFormatExtension;
|
|
|
|
|
ASCIIEncoding asciiEncoding = new();
|
|
|
|
|
bool nameWithoutExtensionIsIdFormat;
|
|
|
|
|
bool nameWithoutExtensionIsPaddedIdFormat;
|
|
|
|
|
IReadOnlyList<MetadataExtractor.Directory> directories;
|
|
|
|
|
int sortOrderOnlyLengthIndex = IDirectory.GetSortOrderOnlyLengthIndex();
|
|
|
|
|
for (int i = 0; i < files.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
progressBar.Tick();
|
|
|
|
@ -122,12 +128,13 @@ public class Rename
|
|
|
|
|
directory = Path.GetDirectoryName(files[i]);
|
|
|
|
|
if (string.IsNullOrEmpty(directory))
|
|
|
|
|
continue;
|
|
|
|
|
if (fileHolder.ExtensionLowered == ".id" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null)
|
|
|
|
|
if (fileHolder.ExtensionLowered == ".paddedId" || fileHolder.ExtensionLowered == ".lsv" || fileHolder.DirectoryName is null)
|
|
|
|
|
continue;
|
|
|
|
|
if (files.Contains($"{fileHolder.FullName}.id"))
|
|
|
|
|
if (files.Contains($"{fileHolder.FullName}.paddedId"))
|
|
|
|
|
continue;
|
|
|
|
|
nameWithoutExtensionIsIdFormat = Shared.Models.Stateless.Methods.IProperty.NameWithoutExtensionIsIdFormat(fileHolder);
|
|
|
|
|
if (nameWithoutExtensionIsIdFormat)
|
|
|
|
|
nameWithoutExtensionIsPaddedIdFormat = IDirectory.NameWithoutExtensionIsPaddedIdFormat(fileHolder, sortOrderOnlyLengthIndex);
|
|
|
|
|
if (nameWithoutExtensionIsIdFormat || nameWithoutExtensionIsPaddedIdFormat)
|
|
|
|
|
continue;
|
|
|
|
|
isValidImageFormatExtension = _PropertyConfiguration.ValidImageFormatExtensions.Contains(fileHolder.ExtensionLowered);
|
|
|
|
|
isIgnoreExtension = isValidImageFormatExtension && _PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered);
|
|
|
|
@ -157,7 +164,7 @@ public class Rename
|
|
|
|
|
if (fileHolder.DirectoryName is null)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
(dateTimeOriginal, dateTimes, id, message) = Shared.Models.Stateless.Methods.IProperty.Get(fileHolder, isIgnoreExtension, isValidImageFormatExtension, _PropertyConfiguration.PopulatePropertyId);
|
|
|
|
|
(dateTimeOriginal, dateTimes, id, message) = Property.Models.Stateless.IProperty.Get(_PropertyConfiguration.PopulatePropertyId, metadata, fileHolder, isIgnoreExtension, isValidImageFormatExtension, asciiEncoding);
|
|
|
|
|
if (ffmpegFiles is not null)
|
|
|
|
|
{
|
|
|
|
|
fileHolder = new(files[i]);
|
|
|
|
@ -171,11 +178,11 @@ public class Rename
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<(FileHolder, string, string)> GetToDoCollection(ProgressBar progressBar, bool nefPresent, List<Record> records, int length)
|
|
|
|
|
private List<(FileHolder, string, string)> GetToDoCollection(ProgressBar progressBar, bool nefPresent, List<Record> records, int intMinValueLength)
|
|
|
|
|
{
|
|
|
|
|
List<(FileHolder, string, string)> results = new();
|
|
|
|
|
string id;
|
|
|
|
|
int season;
|
|
|
|
|
string paddedId;
|
|
|
|
|
string checkFile;
|
|
|
|
|
bool? isWrongYear;
|
|
|
|
|
DateTime dateTime;
|
|
|
|
@ -189,12 +196,9 @@ public class Rename
|
|
|
|
|
string checkFileExtension;
|
|
|
|
|
DateTime? dateTimeFromName;
|
|
|
|
|
const string jpeg = ".jpeg";
|
|
|
|
|
DateTime?[] metadataDateTimes;
|
|
|
|
|
List<string> distinct = new();
|
|
|
|
|
string[] directoryNameSegments;
|
|
|
|
|
DateTime? dateTimeOriginalByLogic;
|
|
|
|
|
DateTime? metadataDateTimeOriginal;
|
|
|
|
|
IReadOnlyList<MetadataExtractor.Directory> directories;
|
|
|
|
|
foreach (Record record in records)
|
|
|
|
|
{
|
|
|
|
|
progressBar.Tick();
|
|
|
|
@ -205,19 +209,20 @@ public class Rename
|
|
|
|
|
continue;
|
|
|
|
|
if (string.IsNullOrEmpty(fileHolder.DirectoryName))
|
|
|
|
|
continue;
|
|
|
|
|
dateTimeFromName = !record.DateTimes.Any() ? null : record.DateTimes.First();
|
|
|
|
|
if (fileHolder.ExtensionLowered == jpeg)
|
|
|
|
|
{
|
|
|
|
|
if (!record.IsIgnoreExtension && record.IsValidImageFormatExtension)
|
|
|
|
|
{
|
|
|
|
|
if (File.Exists($"{fileHolder.FullName}.id"))
|
|
|
|
|
if (File.Exists($"{fileHolder.FullName}.paddedId"))
|
|
|
|
|
{
|
|
|
|
|
checkFile = Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}.id");
|
|
|
|
|
checkFile = Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}.paddedId");
|
|
|
|
|
if (File.Exists(checkFile))
|
|
|
|
|
continue;
|
|
|
|
|
if (distinct.Contains(checkFile))
|
|
|
|
|
continue;
|
|
|
|
|
distinct.Add(checkFile);
|
|
|
|
|
results.Add(new(new($"{fileHolder.FullName}.id"), fileHolder.DirectoryName, checkFile));
|
|
|
|
|
results.Add(new(new($"{fileHolder.FullName}.paddedId"), fileHolder.DirectoryName, checkFile));
|
|
|
|
|
}
|
|
|
|
|
checkFile = Path.Combine(fileHolder.DirectoryName, $"{fileHolder.NameWithoutExtension}{jpg}");
|
|
|
|
|
if (File.Exists(checkFile))
|
|
|
|
@ -238,7 +243,6 @@ public class Rename
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dateTimeFromName = Shared.Models.Stateless.Methods.IProperty.GetDateTimeFromName(fileHolder);
|
|
|
|
|
minimumDateTime = record.DateTimes.Min();
|
|
|
|
|
if (minimumDateTime is null)
|
|
|
|
|
throw new NotSupportedException();
|
|
|
|
@ -246,24 +250,10 @@ public class Rename
|
|
|
|
|
timeSpan = null;
|
|
|
|
|
else
|
|
|
|
|
timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - record.DateTimeOriginal.Value.Ticks));
|
|
|
|
|
if (timeSpan is not null && timeSpan.Value.TotalMinutes < _AppSettings.MaxMinutesDelta)
|
|
|
|
|
(dateTimeOriginalByLogic, metadataDateTimeOriginal, metadataDateTimes) = (record.DateTimeOriginal, null, Array.Empty<DateTime?>());
|
|
|
|
|
if (timeSpan is null || timeSpan.Value.TotalMinutes > _AppSettings.MaxMinutesDelta)
|
|
|
|
|
timeSpan = null;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (_PropertyConfiguration.IgnoreExtensions.Contains(fileHolder.ExtensionLowered))
|
|
|
|
|
continue;
|
|
|
|
|
try
|
|
|
|
|
{ directories = MetadataExtractor.ImageMetadataReader.ReadMetadata(fileHolder.FullName); }
|
|
|
|
|
catch (Exception) { continue; }
|
|
|
|
|
(metadataDateTimeOriginal, metadataDateTimes) = Metadata.Models.Stateless.Methods.IMetadata.GetDateTimes(fileHolder, directories);
|
|
|
|
|
dateTimeOriginalByLogic = record.DateTimeOriginal is not null ? record.DateTimeOriginal : metadataDateTimeOriginal;
|
|
|
|
|
if (record.FfmpegFilesPresent && dateTimeOriginalByLogic is not null)
|
|
|
|
|
minimumDateTime = dateTimeOriginalByLogic.Value;
|
|
|
|
|
if (dateTimeOriginalByLogic is null)
|
|
|
|
|
timeSpan = null;
|
|
|
|
|
else
|
|
|
|
|
timeSpan = new(Math.Abs(minimumDateTime.Value.Ticks - dateTimeOriginalByLogic.Value.Ticks));
|
|
|
|
|
}
|
|
|
|
|
dateTimeOriginalByLogic = record.DateTimeOriginal;
|
|
|
|
|
if (timeSpan is null || timeSpan.Value.TotalMinutes > _AppSettings.MaxMinutesDelta)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(_AppSettings.DefaultUnknownDirectoryName))
|
|
|
|
@ -287,10 +277,8 @@ public class Rename
|
|
|
|
|
{
|
|
|
|
|
if (dateTimeFromName is not null && isWrongYear is not null && isWrongYear.Value)
|
|
|
|
|
minimumDateTime = dateTimeFromName.Value;
|
|
|
|
|
else if (dateTimeOriginalByLogic is not null)
|
|
|
|
|
minimumDateTime = dateTimeOriginalByLogic.Value;
|
|
|
|
|
else
|
|
|
|
|
minimumDateTime = new DateTime?[] { record.DateTimes.Where(l => l is not null).Min(), metadataDateTimes.Where(l => l is not null).Min() }.Min();
|
|
|
|
|
else if (record.DateTimeOriginal is not null)
|
|
|
|
|
minimumDateTime = record.DateTimeOriginal.Value;
|
|
|
|
|
if (minimumDateTime is null)
|
|
|
|
|
continue;
|
|
|
|
|
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
|
|
|
|
@ -310,9 +298,9 @@ public class Rename
|
|
|
|
|
{
|
|
|
|
|
if (record.Id is null)
|
|
|
|
|
continue;
|
|
|
|
|
id = Shared.Models.Stateless.Methods.IDirectory.GetPaddedId(length, record.Index, record.Id.Value);
|
|
|
|
|
paddedId = IDirectory.GetPaddedId(intMinValueLength, record.Index, record.Id.Value);
|
|
|
|
|
checkFileExtension = fileHolder.ExtensionLowered == jpeg ? jpg : fileHolder.ExtensionLowered;
|
|
|
|
|
checkFile = Path.Combine(seasonDirectory, $"{id}{checkFileExtension}");
|
|
|
|
|
checkFile = Path.Combine(seasonDirectory, $"{paddedId}{checkFileExtension}");
|
|
|
|
|
if (checkFile == fileHolder.FullName)
|
|
|
|
|
continue;
|
|
|
|
|
if (File.Exists(checkFile))
|
|
|
|
@ -359,11 +347,12 @@ public class Rename
|
|
|
|
|
const string fileSearchFilter = "*";
|
|
|
|
|
const string directorySearchFilter = "*";
|
|
|
|
|
List<string> distinctDirectories = new();
|
|
|
|
|
B_Metadata metadata = new(_PropertyConfiguration);
|
|
|
|
|
List<(FileHolder, string)> verifiedToDoCollection = new();
|
|
|
|
|
List<(FileHolder, string, string)> toDoCollection = new();
|
|
|
|
|
int offset = Shared.Models.Stateless.Methods.IDirectory.GetOffset();
|
|
|
|
|
int offset = IDirectory.GetOffset();
|
|
|
|
|
ProgressBarOptions options = new() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true };
|
|
|
|
|
List<string[]> filesCollection = Shared.Models.Stateless.Methods.IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter);
|
|
|
|
|
List<string[]> filesCollection = IDirectory.GetFilesCollection(_PropertyConfiguration.RootDirectory, directorySearchFilter, fileSearchFilter);
|
|
|
|
|
int count = filesCollection.Select(l => l.Length).Sum();
|
|
|
|
|
foreach (string[] files in filesCollection)
|
|
|
|
|
{
|
|
|
|
@ -389,30 +378,29 @@ public class Rename
|
|
|
|
|
progressBar = new(files.Length, message, options);
|
|
|
|
|
nefPresentCheck = files.Any(l => l.EndsWith(".NEF"));
|
|
|
|
|
if (!nefPresentCheck)
|
|
|
|
|
records.AddRange(GetRecords(offset + records.Count, progressBar, files));
|
|
|
|
|
records.AddRange(GetRecords(metadata, offset + records.Count, progressBar, files));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!nefPresent)
|
|
|
|
|
nefPresent = true;
|
|
|
|
|
records.AddRange(GetRecords(offset + records.Count, progressBar, (from l in files where l.EndsWith(".JPG") select l).ToArray()));
|
|
|
|
|
records.AddRange(GetRecords(metadata, offset + records.Count, progressBar, (from l in files where l.EndsWith(".JPG") select l).ToArray()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
progressBar.Dispose();
|
|
|
|
|
}
|
|
|
|
|
if (records.Any())
|
|
|
|
|
{
|
|
|
|
|
int length = 0;
|
|
|
|
|
int intMinValueLength = int.MinValue.ToString().Length;
|
|
|
|
|
foreach (Record record in records)
|
|
|
|
|
{
|
|
|
|
|
if (record.Id is null)
|
|
|
|
|
continue;
|
|
|
|
|
if (length > record.Id.Value.ToString().Length)
|
|
|
|
|
continue;
|
|
|
|
|
length = record.Id.Value.ToString().Length;
|
|
|
|
|
if (intMinValueLength < record.Id.Value.ToString().Length)
|
|
|
|
|
throw new NotSupportedException();
|
|
|
|
|
}
|
|
|
|
|
message = $"{length}) comparing records";
|
|
|
|
|
message = $"{intMinValueLength}) comparing records";
|
|
|
|
|
progressBar = new(records.Count, message, options);
|
|
|
|
|
toDoCollection.AddRange(GetToDoCollection(progressBar, nefPresent, records, length));
|
|
|
|
|
toDoCollection.AddRange(GetToDoCollection(progressBar, nefPresent, records, intMinValueLength));
|
|
|
|
|
progressBar.Dispose();
|
|
|
|
|
}
|
|
|
|
|
foreach ((FileHolder fileHolder, string directory, string to) in toDoCollection)
|
|
|
|
@ -431,7 +419,7 @@ public class Rename
|
|
|
|
|
if (File.Exists(to))
|
|
|
|
|
continue;
|
|
|
|
|
verifiedToDoCollection.Add(new(fileHolder, to));
|
|
|
|
|
File.WriteAllText($"{to}.id", $"{to}{Environment.NewLine}{fileHolder.FullName}");
|
|
|
|
|
File.WriteAllText($"{to}.paddedId", $"{to}{Environment.NewLine}{fileHolder.FullName}");
|
|
|
|
|
}
|
|
|
|
|
ConsoleKey? consoleKey = null;
|
|
|
|
|
log.Information($"Ready to Move {verifiedToDoCollection.Count} files[i](s)?");
|
|
|
|
|