@ -1,9 +1,7 @@
using CliWrap ;
using Microsoft.Extensions.Configuration ;
using Microsoft.Extensions.Configuration ;
using Phares.Shared ;
using Serilog ;
using ShellProgressBar ;
using System.Text.Json ;
using View_by_Distance.Copy.Distinct.Models ;
using View_by_Distance.Shared.Models ;
using View_by_Distance.Shared.Models.Methods ;
@ -18,6 +16,7 @@ public class CopyDistinct
private readonly Configuration _Configuration ;
private readonly IsEnvironment _IsEnvironment ;
private readonly IConfigurationRoot _ConfigurationRoot ;
private readonly IReadOnlyDictionary < string , string [ ] > _JsonGroups ;
private readonly Property . Models . Configuration _PropertyConfiguration ;
public CopyDistinct ( List < string > args , IsEnvironment isEnvironment , IConfigurationRoot configurationRoot , AppSettings appSettings , string workingDirectory , bool isSilent , IConsole console )
@ -26,43 +25,24 @@ public class CopyDistinct
{ }
if ( console is null )
{ }
bool any = false ;
_AppSettings = appSettings ;
_IsEnvironment = isEnvironment ;
_WorkingDirectory = workingDirectory ;
_ConfigurationRoot = configurationRoot ;
string [ ] directories = new string [ ] { "()" } ;
ILogger ? log = Log . ForContext < CopyDistinct > ( ) ;
Property . Models . Configuration propertyConfiguration = Property . Models . Binder . Configuration . Get ( isEnvironment , configurationRoot ) ;
_JsonGroups = Shared . Models . Stateless . Methods . IPath . GetKeyValuePairs ( propertyConfiguration . ResultAllInOne , appSettings . MoveTo , directories , appSettings . MaxValue ) ;
Configuration configuration = Models . Binder . Configuration . Get ( isEnvironment , configurationRoot , propertyConfiguration ) ;
_PropertyConfiguration = propertyConfiguration ;
_Configuration = configuration ;
propertyConfiguration . Update ( ) ;
string? comparePathRoot = Path . GetDirectoryName ( appSettings . ComparePathsFile ) ;
if ( comparePathRoot is null | | comparePathRoot = = propertyConfiguration . RootDirectory )
throw new Exception ( "Nested isn't allowed!" ) ;
log . Information ( propertyConfiguration . RootDirectory ) ;
Verify ( ) ;
string json = File . ReadAllText ( appSetting s. ComparePathsFile ) ;
MatchNginx [ ] ? matchNginxCollection = JsonSerializer . Deserialize < MatchNginx [ ] > ( json ) ;
if ( matchNginxCollection is null )
throw new NullReferenceException ( nameof ( matchNginxCollection ) ) ;
if ( matchNginxCollection . Any ( ) )
{
bool deleted ;
for ( int i = 1 ; i < 5 ; i + + )
{
deleted = Shared . Models . Stateless . Methods . IPath . DeleteEmptyDirectories ( matchNginxCollection . First ( ) . ConvertedPath ) ;
if ( deleted & & ! any )
any = true ;
}
}
if ( ! any )
{
List < string > lines = CopyDistinctFilesInDirectories ( log , matchNginxCollection ) ;
File . WriteAllLines ( $"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv" , lines ) ;
if ( comparePathRoot ! = Path . GetPathRoot ( matchNginxCollection [ 0 ] . ConvertedPath ) )
_ = Shared . Models . Stateless . Methods . IPath . DeleteEmptyDirectories ( comparePathRoot ) ;
}
List < string > lines = CopyDistinctFilesInDirectorie s( log ) ;
File . WriteAllLines ( $"D:/Tmp/Phares/{DateTime.Now.Ticks}.tsv" , lines ) ;
if ( lines . Any ( ) )
_ = Shared . Models . Stateless . Methods . IPath . DeleteEmptyDirectories ( propertyConfiguration . RootDirectory ) ;
}
private void Verify ( )
@ -81,181 +61,55 @@ public class CopyDistinct
{ }
}
private List < ( FileHolder , string ) > GetToDoCollection ( ProgressBar progressBar , string [ ] files )
private static ( List < string > , List < string > ) Get( List < string [ ] > filesCollection )
{
List < string > results = new ( ) ;
string? directory ;
List < string > directories = new ( ) ;
foreach ( string [ ] files in filesCollection )
{
if ( ! files . Any ( ) )
continue ;
directory = Path . GetDirectoryName ( files . First ( ) ) ;
if ( directory is null )
continue ;
if ( ! directories . Contains ( directory ) )
directories . Add ( directory ) ;
results . AddRange ( files ) ;
}
return ( directories , results ) ;
}
private List < ( FileHolder , string ) > GetToDoCollection ( ProgressBar progressBar , List < string > files )
{
List < ( FileHolder , string ) > results = new ( ) ;
int? id ;
string fileName ;
string? message ;
string directory ;
string checkFile ;
string? directory ;
TimeSpan timeSpan ;
DateTime ? dateTime ;
DateTime ? [ ] dateTimes ;
int directoryIndex ;
FileHolder fileHolder ;
string [ ] ? ffmpegFiles ;
bool isIgnoreExtension ;
string checkFileExtension ;
DateTime ? minimumDateTime ;
const string jpg = ".jpg" ;
const string jpeg = ".jpeg" ;
List < string > distinct = new ( ) ;
bool isValidImageFormatExtension ;
bool nameWithoutExtensionIsIdFormat ;
IReadOnlyList < MetadataExtractor . Directory > directories ;
foreach ( string file in files )
{
progressBar . Tick ( ) ;
fileHolder = new ( file ) ;
if ( file . EndsWith ( ".rename" ) )
{
directory = Path . GetDirectoryName ( file ) ;
if ( string . IsNullOrEmpty ( directory ) )
continue ;
checkFile = Path . Combine ( directory , $"rename_{Path.GetFileName(file[..^7])}" ) ;
if ( File . Exists ( checkFile ) )
continue ;
if ( distinct . Contains ( checkFile ) )
continue ;
distinct . Add ( checkFile ) ;
results . Add ( new ( fileHolder , checkFile ) ) ;
continue ;
}
if ( file . EndsWith ( ".jpg.del" ) )
{
checkFile = file [ . . ^ 4 ] ;
if ( File . Exists ( checkFile ) )
continue ;
if ( distinct . Contains ( checkFile ) )
continue ;
distinct . Add ( checkFile ) ;
results . Add ( new ( fileHolder , checkFile ) ) ;
continue ;
}
if ( fileHolder . ExtensionLowered = = ".id" | | fileHolder . ExtensionLowered = = ".lsv" | | fileHolder . DirectoryName is null )
continue ;
if ( files . Contains ( $"{fileHolder.FullName}.id" ) )
continue ;
isValidImageFormatExtension = _PropertyConfiguration . ValidImageFormatExtensions . Contains ( fileHolder . ExtensionLowered ) ;
isIgnoreExtension = isValidImageFormatExtension & & _PropertyConfiguration . IgnoreExtensions . Contains ( fileHolder . ExtensionLowered ) ;
if ( isIgnoreExtension | | ! isValidImageFormatExtension )
continue ;
nameWithoutExtensionIsIdFormat = Shared . Models . Stateless . Methods . IProperty . NameWithoutExtensionIsIdFormat ( fileHolder ) ;
if ( nameWithoutExtensionIsIdFormat )
continue ;
isValidImageFormatExtension = _PropertyConfiguration . ValidImageFormatExtensions . Contains ( fileHolder . ExtensionLowered ) ;
isIgnoreExtension = isValidImageFormatExtension & & _PropertyConfiguration . IgnoreExtensions . Contains ( fileHolder . ExtensionLowered ) ;
if ( ! isIgnoreExtension & & isValidImageFormatExtension )
ffmpegFiles = null ;
else
{
try
{ directories = MetadataExtractor . ImageMetadataReader . ReadMetadata ( file ) ; }
catch ( Exception ) { continue ; }
CommandTask < CommandResult > result = Cli . Wrap ( "ffmpeg.exe" )
// .WithArguments(new[] { "-ss", "00:00:00", "-t", "00:00:00", "-i", file, "-qscale:v", "2", "-r", "0.01", $"{fileHolder.Name}-%4d.jpg" })
. WithArguments ( new [ ] { "-i" , file , "-vframes" , "1" , $"{fileHolder.Name}-%4d.jpg" } )
. WithWorkingDirectory ( fileHolder . DirectoryName )
. ExecuteAsync ( ) ;
result . Task . Wait ( ) ;
ffmpegFiles = Directory . GetFiles ( fileHolder . DirectoryName , $"{fileHolder.Name}-*.jpg" , SearchOption . TopDirectoryOnly ) ;
if ( ! ffmpegFiles . Any ( ) )
continue ;
fileHolder = new ( ffmpegFiles . First ( ) ) ;
if ( ! fileHolder . Name . EndsWith ( "-0001.jpg" ) )
throw new Exception ( ) ;
isValidImageFormatExtension = _PropertyConfiguration . ValidImageFormatExtensions . Contains ( fileHolder . ExtensionLowered ) ;
isIgnoreExtension = isValidImageFormatExtension & & _PropertyConfiguration . IgnoreExtensions . Contains ( fileHolder . ExtensionLowered ) ;
if ( isIgnoreExtension | | ! isValidImageFormatExtension )
continue ;
if ( fileHolder . DirectoryName is null )
continue ;
}
if ( ! isIgnoreExtension & & isValidImageFormatExtension )
{
if ( fileHolder . ExtensionLowered = = jpeg )
{
if ( File . Exists ( $"{fileHolder.FullName}.id" ) )
{
checkFile = Path . Combine ( fileHolder . DirectoryName , $"{fileHolder.NameWithoutExtension}{jpg}.id" ) ;
if ( File . Exists ( checkFile ) )
continue ;
if ( distinct . Contains ( checkFile ) )
continue ;
distinct . Add ( checkFile ) ;
results . Add ( new ( new ( $"{fileHolder.FullName}.id" ) , checkFile ) ) ;
}
checkFile = Path . Combine ( fileHolder . DirectoryName , $"{fileHolder.NameWithoutExtension}{jpg}" ) ;
if ( File . Exists ( checkFile ) )
continue ;
if ( distinct . Contains ( checkFile ) )
continue ;
distinct . Add ( checkFile ) ;
results . Add ( new ( fileHolder , checkFile ) ) ;
if ( File . Exists ( checkFile ) )
continue ;
File . Move ( fileHolder . FullName , checkFile ) ;
fileHolder = new ( checkFile ) ;
if ( fileHolder . DirectoryName is null )
continue ;
}
}
( dateTimes , id , message ) = Shared . Models . Stateless . Methods . IProperty . Get ( fileHolder , isIgnoreExtension , isValidImageFormatExtension ) ;
minimumDateTime = dateTimes . Min ( ) ;
if ( minimumDateTime is null | | ! isIgnoreExtension & & isValidImageFormatExtension )
{
dateTime = Shared . Models . Stateless . Methods . IProperty . GetDateTimeFromName ( fileHolder ) ;
if ( dateTime is null | | minimumDateTime is null )
timeSpan = new TimeSpan ( 0 ) ;
else
timeSpan = new ( Math . Abs ( minimumDateTime . Value . Ticks - dateTime . Value . Ticks ) ) ;
}
else
{
fileName = Path . GetFileName ( fileHolder . DirectoryName ) ;
if ( fileName . Length < 4 | | ! int . TryParse ( fileName [ . . 4 ] , out int year ) )
year = minimumDateTime . Value . Year ;
if ( _PropertyConfiguration . IgnoreExtensions . Contains ( fileHolder . ExtensionLowered ) )
continue ;
try
{ directories = MetadataExtractor . ImageMetadataReader . ReadMetadata ( file ) ; }
catch ( Exception ) { continue ; }
dateTime = Metadata . Models . Stateless . Methods . IMetadata . GetMinimumDateTime ( dateTimes , year , directories ) ;
timeSpan = new TimeSpan ( int . MaxValue ) ;
}
if ( dateTime is not null & & string . IsNullOrEmpty ( _AppSettings . CopyTo ) )
{
checkFileExtension = fileHolder . ExtensionLowered = = jpeg ? jpg : fileHolder . ExtensionLowered ;
checkFile = Path . Combine ( fileHolder . DirectoryName , $"{dateTime.Value:yyyy-MM-dd}.{dateTime.Value.Ticks}.{fileHolder.Length}{checkFileExtension}" ) ;
if ( checkFile = = fileHolder . FullName )
continue ;
if ( distinct . Contains ( checkFile ) )
continue ;
distinct . Add ( checkFile ) ;
results . Add ( new ( fileHolder , checkFile ) ) ;
if ( ffmpegFiles is not null )
{
foreach ( string ffmpegFile in ffmpegFiles )
File . Delete ( ffmpegFile ) ;
}
directory = Shared . Models . Stateless . Methods . IDirectory . GetDirectory ( fileHolder . NameWithout Extension, 2 ) ;
if ( ! int . TryParse ( directory , out directoryIndex ) )
continue ;
}
if ( id is null )
continue ;
if ( ffmpegFiles is not null )
{
foreach ( string ffmpegFile in ffmpegFiles )
File . Delete ( ffmpegFile ) ;
fileHolder = new ( file ) ;
if ( fileHolder . DirectoryName is null )
continue ;
}
checkFileExtension = fileHolder . ExtensionLowered = = jpeg ? jpg : fileHolder . ExtensionLowered ;
checkFile = Path . Combine ( fileHolder . DirectoryName , $"{id.Value}{checkFileExtension}" ) ;
if ( checkFile = = fileHolder . FullName )
continue ;
if ( File . Exists ( checkFile ) )
{
checkFile = string . Concat ( checkFile , ".del" ) ;
if ( File . Exists ( checkFile ) )
continue ;
}
checkFile = Path . Combine ( _JsonGroups [ "()" ] [ directoryIndex ] , fileHolder . Name ) ;
if ( distinct . Contains ( checkFile ) )
continue ;
distinct . Add ( checkFile ) ;
@ -264,97 +118,11 @@ public class CopyDistinct
return results ;
}
private static List < string > GetAllFiles ( MatchNg inx [ ] matchNginx Collection)
{
List < string > allFiles = new ( ) ;
string [ ] files ;
string directoryName ;
ReadOnlySpan < char > span ;
foreach ( MatchNginx matchNginx in matchNginxCollection )
{
if ( matchNginx . ConvertedPath . Length < 6 )
continue ;
directoryName = Path . GetFileName ( matchNginx . ConvertedPath ) ;
if ( matchNginx . ConvertedPath . Contains ( "!---" ) )
span = "0" ;
else
span = matchNginx . ConvertedPath . AsSpan ( matchNginx . ConvertedPath . Length - 5 , 3 ) ;
if ( directoryName . Length = = 1 & & int . TryParse ( span , out int age ) )
continue ;
if ( File . Exists ( matchNginx . ConvertedPath ) )
continue ;
if ( ! Directory . Exists ( matchNginx . ConvertedPath ) )
continue ;
files = Directory . GetFiles ( matchNginx . ConvertedPath , "*" , SearchOption . AllDirectories ) ;
if ( files . All ( l = > l . EndsWith ( ".id" ) ) )
{
foreach ( string file in files )
File . Delete ( file ) ;
continue ;
}
allFiles . AddRange ( files ) ;
}
return allFiles ;
}
private static void CreateDirectories ( List < string > directories )
{
foreach ( string directory in directories )
{
if ( Directory . Exists ( directory ) )
continue ;
_ = Directory . CreateDirectory ( directory ) ;
}
}
private List < string > CopyInstead ( ILogger log , List < ( FileHolder , string ) > verifiedToDoCollection )
{
List < string > results = new ( ) ;
string copyTo ;
string? directory ;
ConsoleKey ? consoleKey = null ;
List < string > distinctDirectories = new ( ) ;
List < ( FileHolder , string ) > copyCollection = new ( ) ;
foreach ( ( FileHolder fileHolder , string to ) in verifiedToDoCollection )
{
copyTo = $"{_AppSettings.CopyTo}{to[1..]}" ;
directory = Path . GetDirectoryName ( copyTo ) ;
if ( directory is null )
continue ;
copyCollection . Add ( new ( fileHolder , copyTo ) ) ;
if ( distinctDirectories . Contains ( directory ) )
continue ;
distinctDirectories . Add ( directory ) ;
}
CreateDirectories ( distinctDirectories ) ;
log . Information ( $"Ready to Copy {verifiedToDoCollection.Count} file(s)?" ) ;
for ( int y = 0 ; y < int . MaxValue ; y + + )
{
log . Information ( "Press \"Y\" key to copy file(s), \"N\" key to log file(s) or close console to not copy files" ) ;
consoleKey = System . Console . ReadKey ( ) . Key ;
if ( consoleKey is ConsoleKey . Y or ConsoleKey . N )
break ;
}
log . Information ( ". . ." ) ;
if ( consoleKey is null | | consoleKey . Value ! = ConsoleKey . Y )
log . Information ( "Nothing Copied!" ) ;
else
{
foreach ( ( FileHolder fileHolder , string to ) in verifiedToDoCollection )
{
results . Add ( fileHolder . NameWithoutExtension ) ;
File . Copy ( fileHolder . FullName , to ) ;
}
log . Information ( "Done Copying" ) ;
}
return results ;
}
private static List < string > Move ( ILogger log , List < ( FileHolder , string ) > verifiedToDoCollection )
private static List < string > Move ( ILogger log , List < ( FileHolder , str ing ) > toDo Collection)
{
List < string > results = new ( ) ;
ConsoleKey ? consoleKey = null ;
log . Information ( $"Ready to Move {verifiedT oDoCollection.Count} file(s)?" ) ;
log . Information ( $"Ready to Move {t oDoCollection.Count} file(s)?" ) ;
for ( int y = 0 ; y < int . MaxValue ; y + + )
{
log . Information ( "Press \"Y\" key to move file(s), \"N\" key to log file(s) or close console to not move files" ) ;
@ -367,69 +135,31 @@ public class CopyDistinct
log . Information ( "Nothing moved!" ) ;
else
{
foreach ( ( FileHolder fileHolder , string to ) in verifiedT oDoCollection)
foreach ( ( FileHolder fileHolder , string to ) in t oDoCollection)
{
results . Add ( fileHolder . NameWithoutExtension ) ;
try
{ File . Move ( fileHolder . FullName , to ) ; }
{ File . Copy ( fileHolder . FullName , to ) ; }
catch ( Exception ) { }
}
log . Information ( "Done Moving" ) ;
}
return results ;
}
// {
// "_App": " Copy- Distinct",
// "_UserSecretsId": "d862524f-2b48-4f47-b4c3-5a8615814ec2",
// "ComparePathsFile": "C:/Users/lphar/AppData/Local/PharesApps/Drag-Drop-Explorer/2023_24/638220924947919275.json",
// "CopyTo": "",
// "MaxDegreeOfParallelism": 6,
// "Windows": {
// "Configuration": {
// "RootDirectory": "C:/",
// "VerifyToSeason": []
// }
// }
// }
private List < string > CopyDistinctFilesInDirectories ( ILogger log , MatchNginx [ ] matchNginxCollection )
private List < string > CopyDistinctFilesInDirectories ( ILogger log )
{
List < string > results = new ( ) ;
string [ ] files ;
string message ;
List < string > allFiles ;
ProgressBar progressBar ;
List < ( FileHolder , string ) > toDo Collection;
allFiles = GetAllFiles ( matchNginxCollection ) ;
List < ( FileHolder , string ) > verifiedToDoCollection ;
const string fileSearchFilter = "*" ;
string message = nameof ( CopyDistinct ) ;
const string directorySearchFilter = "*" ;
List < string [ ] > filesCollection = Shared . Models . Stateless . Methods . IDirectory . GetFilesCollection ( _PropertyConfiguration . RootDirectory , directorySearchFilter , fileSearchFilter ) ;
( _ , List < string > allFiles ) = Get ( files Collection) ;
ProgressBarOptions options = new ( ) { ProgressCharacter = '─' , ProgressBarOnBottom = true , DisableBottomPercentage = true } ;
for ( int i = 1 ; i < 3 ; i + + )
{
if ( ! allFiles . Any ( ) )
continue ;
message = $"{i}) Renaming files" ;
files = i = = 2 ? allFiles . ToArray ( ) : ( from l in allFiles where l . Contains ( "Rename" , StringComparison . OrdinalIgnoreCase ) select l ) . ToArray ( ) ;
progressBar = new ( files . Length , message , options ) ;
if ( ! files . Any ( ) )
continue ;
toDoCollection = GetToDoCollection ( progressBar , files ) ;
verifiedToDoCollection = new ( ) ;
foreach ( ( FileHolder fileHolder , string to ) in toDoCollection )
{
if ( File . Exists ( to ) )
continue ;
verifiedToDoCollection . Add ( new ( fileHolder , to ) ) ;
if ( string . IsNullOrEmpty ( _AppSettings . CopyTo ) )
File . WriteAllText ( $"{to}.id" , $"{to}{Environment.NewLine}{fileHolder.FullName}" ) ;
}
if ( ! verifiedToDoCollection . Any ( ) )
continue ;
if ( string . IsNullOrEmpty ( _AppSettings . CopyTo ) )
results . AddRange ( Move ( log , toDoCollection ) ) ;
else
results . AddRange ( CopyInstead ( log , toDoCollection ) ) ;
allFiles = GetAllFiles ( matchNginxCollection ) ;
progressBar . Dispose ( ) ;
}
ProgressBar progressBar = new ( allFiles . Count , message , options ) ;
List < ( FileHolder , string ) > toDoCollection = GetToDoCollection ( progressBar , allFiles ) ;
results . AddRange ( Move ( log , toDoCollection ) ) ;
progressBar . Dispose ( ) ;
return results ;
}