public void FindDiscNumberShouldBeTwo(string filename) { var n = ID3TagsHelper.DetermineDiscNumber(new AudioMetaData { Filename = filename }); Assert.Equal(2, n); }
public void Find_Disc_Number_Should_Be_One(string filename) { var n = ID3TagsHelper.DetermineDiscNumber(new AudioMetaData { Filename = filename }); Assert.Equal(1, n); }
public override OperationResult <AudioMetaData> Process(AudioMetaData metaData) { var result = new OperationResult <AudioMetaData>(); var metaDatasForFilesInFolder = GetAudioMetaDatasForDirectory(metaData.FileInfo.Directory); metaData.TrackNumber = (metaData.TrackNumber ?? 0) > 0 ? metaData.TrackNumber : ID3TagsHelper.DetermineTrackNumber(metaData.FileInfo.Name); metaData.TotalTrackNumbers = ID3TagsHelper.DetermineTotalTrackNumbers(metaData.Filename) ?? metaDatasForFilesInFolder.Count(); metaData.Disc = ID3TagsHelper.DetermineDiscNumber(metaData); metaData.TotalDiscCount = ID3TagsHelper.DetermineTotalDiscNumbers(metaDatasForFilesInFolder); result.Data = metaData; result.IsSuccess = true; return(result); }
public override OperationResult <IEnumerable <AudioMetaData> > Process(IEnumerable <AudioMetaData> metaDatas) { var result = new OperationResult <IEnumerable <AudioMetaData> >(); var totalNumberOfMedia = ID3TagsHelper.DetermineTotalDiscNumbers(metaDatas); var folders = metaDatas.GroupBy(x => x.FileInfo.DirectoryName); foreach (var folder in folders) { short looper = 0; foreach (var metaData in folder) { looper++; metaData.TrackNumber = looper; metaData.TotalTrackNumbers = ID3TagsHelper.DetermineTotalTrackNumbers(metaData.Filename) ?? folder.Count(); metaData.Disk = ID3TagsHelper.DetermineDiscNumber(metaData); metaData.TotalDiscCount = totalNumberOfMedia; } } result.Data = metaDatas; result.IsSuccess = true; return(result); }
public void Inspect(bool doCopy, bool isReadOnly, string directoryToInspect, string destination, bool dontAppendSubFolder, bool dontDeleteEmptyFolders, bool dontRunPreScripts) { Configuration.Inspector.IsInReadOnlyMode = isReadOnly; Configuration.Inspector.DoCopyFiles = doCopy; var artistsFound = new List <string>(); var releasesFound = new List <string>(); var mp3FilesFoundCount = 0; Trace.Listeners.Add(new LoggingTraceListener()); Console.BackgroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine($"✨ Inspector Start, UTC [{DateTime.UtcNow.ToString("s")}]"); Console.ResetColor(); string scriptResult = null; // Run PreInspect script if (dontRunPreScripts) { Console.BackgroundColor = ConsoleColor.Blue; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine($"Skipping PreInspectScript."); Console.ResetColor(); } else { scriptResult = RunScript(Configuration.Processing.PreInspectScript, doCopy, isReadOnly, directoryToInspect, destination); if (!string.IsNullOrEmpty(scriptResult)) { Console.BackgroundColor = ConsoleColor.Blue; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine($"PreInspectScript Results: {Environment.NewLine + scriptResult + Environment.NewLine}"); Console.ResetColor(); } } // Create a new destination subfolder for each Inspector run by Current timestamp var dest = Path.Combine(destination, DateTime.UtcNow.ToString("yyyyMMddHHmm")); if (isReadOnly || dontAppendSubFolder) { dest = destination; } // Get all the directorys in the directory var directoryDirectories = Directory.GetDirectories(directoryToInspect, "*.*", SearchOption.AllDirectories); var directories = new List <string> { directoryToInspect }; directories.AddRange(directoryDirectories); directories.Remove(dest); var inspectedImagesInDirectories = new List <string>(); try { var createdDestinationFolder = false; var sw = Stopwatch.StartNew(); foreach (var directory in directories.OrderBy(x => x)) { var directoryInfo = new DirectoryInfo(directory); Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine($"╔ 📂 Inspecting [{directory}]"); Console.ResetColor(); Console.WriteLine("╠╦════════════════════════╣"); // Get all the MP3 files in 'directory' var files = Directory.GetFiles(directory, "*.mp3", SearchOption.TopDirectoryOnly); if (files != null && files.Any()) { if (!isReadOnly && !createdDestinationFolder && !Directory.Exists(dest)) { Directory.CreateDirectory(dest); createdDestinationFolder = true; } // Run directory plugins against current directory foreach (var plugin in DirectoryPlugins.Where(x => !x.IsPostProcessingPlugin) .OrderBy(x => x.Order)) { Console.WriteLine($"╠╬═ Running Directory Plugin {plugin.Description}"); var pluginResult = plugin.Process(directoryInfo); if (!pluginResult.IsSuccess) { Console.WriteLine( $"📛 Plugin Failed: Error [{JsonConvert.SerializeObject(pluginResult)}]"); return; } if (!string.IsNullOrEmpty(pluginResult.Data)) { Console.WriteLine($"╠╣ Directory Plugin Message: {pluginResult.Data}"); } } Console.WriteLine("╠╝"); Console.WriteLine($"╟─ Found [{files.Length}] mp3 Files"); var fileMetaDatas = new List <AudioMetaData>(); var fileInfos = new List <FileInfo>(); // Inspect the found MP3 files in 'directory' foreach (var file in files) { mp3FilesFoundCount++; var fileInfo = new FileInfo(file); Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine($"╟─ 🎵 Inspecting [{fileInfo.FullName}]"); var tagLib = TagsHelper.MetaDataForFile(fileInfo.FullName, true); Console.ForegroundColor = ConsoleColor.Cyan; if (!tagLib?.IsSuccess ?? false) { Console.ForegroundColor = ConsoleColor.DarkYellow; } Console.WriteLine($"╟ (Pre ) : {tagLib.Data}"); Console.ResetColor(); tagLib.Data.Filename = fileInfo.FullName; var originalMetaData = tagLib.Data.Adapt <AudioMetaData>(); if (!originalMetaData.IsValid) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine( $"╟ ❗ INVALID: Missing: {ID3TagsHelper.DetermineMissingRequiredMetaData(originalMetaData)}"); Console.WriteLine($"╟ [{JsonConvert.SerializeObject(tagLib, Newtonsoft.Json.Formatting.Indented)}]"); Console.ResetColor(); } var pluginMetaData = tagLib.Data; // Run all file plugins against the MP3 file modifying the MetaData foreach (var plugin in FilePlugins.OrderBy(x => x.Order)) { Console.WriteLine($"╟┤ Running File Plugin {plugin.Description}"); OperationResult <AudioMetaData> pluginResult = null; pluginResult = plugin.Process(pluginMetaData); if (!pluginResult.IsSuccess) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine( $"📛 Plugin Failed: Error [{JsonConvert.SerializeObject(pluginResult)}]"); Console.ResetColor(); return; } pluginMetaData = pluginResult.Data; } if (!pluginMetaData.IsValid) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine( $"╟ ❗ INVALID: Missing: {ID3TagsHelper.DetermineMissingRequiredMetaData(pluginMetaData)}"); Console.ResetColor(); return; } // See if the MetaData from the Plugins is different from the original if (originalMetaData != null && pluginMetaData != null) { var differences = Comparer.Compare(originalMetaData, pluginMetaData); if (differences.Any()) { var skipDifferences = new List <string> { "AudioMetaDataWeights", "FileInfo", "Images", "TrackArtists" }; var differencesDescription = $"{Environment.NewLine}"; foreach (var difference in differences) { if (skipDifferences.Contains(difference.Name)) { continue; } differencesDescription += $"╟ || {difference.Name} : Was [{difference.OldValue}] Now [{difference.NewValue}]{Environment.NewLine}"; } Console.Write($"╟ ≡ != ID3 Tag Modified: {differencesDescription}"); if (!isReadOnly) { if (!TagsHelper.WriteTags(pluginMetaData, pluginMetaData.Filename)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("📛 WriteTags Failed"); Console.ResetColor(); return; } } else { Console.WriteLine("╟ 🔒 Read Only Mode: Not Modifying File ID3 Tags."); } } else { Console.WriteLine("╟ ≡ == ID3 Tag NOT Modified"); } } else { var oBad = originalMetaData == null; var pBad = pluginMetaData == null; Console.WriteLine( $"╟ !! MetaData comparison skipped. {(oBad ? "Pre MetaData is Invalid" : "")} {(pBad ? "Post MetaData is Invalid" : "")}"); } if (!pluginMetaData.IsValid) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine( $"╟ ❗ INVALID: Missing: {ID3TagsHelper.DetermineMissingRequiredMetaData(pluginMetaData)}"); Console.ResetColor(); } else { Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine($"╟ (Post) : {pluginMetaData}"); Console.ResetColor(); var artistToken = ArtistInspectorToken(tagLib.Data); if (!artistsFound.Contains(artistToken)) { artistsFound.Add(artistToken); } var releaseToken = ReleaseInspectorToken(tagLib.Data); if (!releasesFound.Contains(releaseToken)) { releasesFound.Add(releaseToken); } var newFileName = $"CD{(tagLib.Data.Disc ?? ID3TagsHelper.DetermineDiscNumber(tagLib.Data)).ToString("000")}_{tagLib.Data.TrackNumber.Value.ToString("0000")}.mp3"; // Artist sub folder is created to hold Releases for Artist and Artist Images var artistSubDirectory = directory == dest ? fileInfo.DirectoryName : Path.Combine(dest, artistToken); // Each release is put into a subfolder into the current run Inspector folder to hold MP3 Files and Release Images var subDirectory = directory == dest ? fileInfo.DirectoryName : Path.Combine(dest, artistToken, releaseToken); if (!isReadOnly && !Directory.Exists(subDirectory)) { Directory.CreateDirectory(subDirectory); } // Inspect images if (!inspectedImagesInDirectories.Contains(directoryInfo.FullName)) { // Get all artist images and move to artist folder var foundArtistImages = new List <FileInfo>(); foundArtistImages.AddRange(ImageHelper.FindImagesByName(directoryInfo, tagLib.Data.Artist, SearchOption.TopDirectoryOnly)); foundArtistImages.AddRange(ImageHelper.FindImagesByName(directoryInfo.Parent, tagLib.Data.Artist, SearchOption.TopDirectoryOnly)); foundArtistImages.AddRange(ImageHelper.FindImageTypeInDirectory( directoryInfo.Parent, ImageType.Artist, SearchOption.TopDirectoryOnly)); foundArtistImages.AddRange(ImageHelper.FindImageTypeInDirectory( directoryInfo.Parent, ImageType.ArtistSecondary, SearchOption.TopDirectoryOnly)); foundArtistImages.AddRange(ImageHelper.FindImageTypeInDirectory(directoryInfo, ImageType.Artist, SearchOption.TopDirectoryOnly)); foundArtistImages.AddRange(ImageHelper.FindImageTypeInDirectory(directoryInfo, ImageType.ArtistSecondary, SearchOption.TopDirectoryOnly)); foreach (var artistImage in foundArtistImages) { InspectImage(isReadOnly, doCopy, dest, artistSubDirectory, artistImage); } // Get all release images and move to release folder var foundReleaseImages = new List <FileInfo>(); foundReleaseImages.AddRange( ImageHelper.FindImagesByName(directoryInfo, tagLib.Data.Release)); foundReleaseImages.AddRange( ImageHelper.FindImageTypeInDirectory(directoryInfo, ImageType.Release)); foundReleaseImages.AddRange( ImageHelper.FindImageTypeInDirectory(directoryInfo, ImageType.ReleaseSecondary)); foreach (var foundReleaseImage in foundReleaseImages) { InspectImage(isReadOnly, doCopy, dest, subDirectory, foundReleaseImage); } inspectedImagesInDirectories.Add(directoryInfo.FullName); } // If enabled move MP3 to new folder var newPath = Path.Combine(dest, subDirectory, newFileName.ToFileNameFriendly()); if (isReadOnly) { Console.WriteLine( $"╟ 🔒 Read Only Mode: File would be [{(doCopy ? "Copied" : "Moved")}] to [{newPath}]"); } else { if (!doCopy) { if (fileInfo.FullName != newPath) { if (File.Exists(newPath)) { File.Delete(newPath); } fileInfo.MoveTo(newPath); } } else { fileInfo.CopyTo(newPath, true); } Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine($"╠═ 🚛 {(doCopy ? "Copied" : "Moved")} MP3 File to [{newPath}]"); Console.ResetColor(); } Console.WriteLine("╠════════════════════════╣"); } } } } foreach (var directory in directories.OrderBy(x => x)) { var directoryInfo = new DirectoryInfo(directory); Console.WriteLine($"╠╬═ Post-Processing Directory [{directoryInfo.FullName}] "); // Run post-processing directory plugins against current directory foreach (var plugin in DirectoryPlugins.Where(x => x.IsPostProcessingPlugin).OrderBy(x => x.Order)) { Console.WriteLine($"╠╬═ Running Post-Processing Directory Plugin {plugin.Description}"); var pluginResult = plugin.Process(directoryInfo); if (!pluginResult.IsSuccess) { Console.WriteLine($"📛 Plugin Failed: Error [{JsonConvert.SerializeObject(pluginResult)}]"); return; } if (!string.IsNullOrEmpty(pluginResult.Data)) { Console.WriteLine($"╠╣ Directory Plugin Message: {pluginResult.Data}"); } } } Console.WriteLine("╠╝"); sw.Stop(); Console.WriteLine( $"╚═ Elapsed Time {sw.ElapsedMilliseconds.ToString("0000000")}, Artists {artistsFound.Count()}, Releases {releasesFound.Count()}, MP3s {mp3FilesFoundCount} ═╝"); } catch (Exception ex) { Logger.LogError(ex); Console.WriteLine("📛 Exception: " + ex); } if (!dontDeleteEmptyFolders) { var delEmptyFolderIn = new DirectoryInfo(directoryToInspect); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"❌ Deleting Empty folders in [{delEmptyFolderIn.FullName}]"); Console.ResetColor(); FolderPathHelper.DeleteEmptyFolders(delEmptyFolderIn); } else { Console.WriteLine("🔒 Read Only Mode: Not deleting empty folders."); } // Run PreInspect script scriptResult = RunScript(Configuration.Processing.PostInspectScript, doCopy, isReadOnly, directoryToInspect, destination); if (!string.IsNullOrEmpty(scriptResult)) { Console.BackgroundColor = ConsoleColor.Blue; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine( $"PostInspectScript Results: {Environment.NewLine + scriptResult + Environment.NewLine}"); Console.ResetColor(); } }
public void Inspect(bool doCopy, string folder, string destination) { // Get all the directorys in the directory var folderDirectories = Directory.GetDirectories(folder, "*.*", SearchOption.AllDirectories); var directories = new List <string> { folder }; directories.AddRange(folderDirectories); foreach (var directory in directories) { Console.WriteLine($"╔ ░▒▓ Inspecting [{ directory }] ▓▒░"); Console.WriteLine("╠═╗"); // Get all the MP3 files in the folder var files = Directory.GetFiles(directory, "*.mp3", SearchOption.TopDirectoryOnly); if (files == null || !files.Any()) { continue; } Console.WriteLine($"Found [{ files.Length }] mp3 Files"); Console.WriteLine("╠═╣"); // Get audiometadata and output details including weight/validity foreach (var file in files) { var tagLib = this.TagsHelper.MetaDataForFile(file); Console.WriteLine(tagLib.Data); } Console.WriteLine("╠═╣"); List <AudioMetaData> fileMetaDatas = new List <AudioMetaData>(); List <FileInfo> fileInfos = new List <FileInfo>(); foreach (var file in files) { var fileInfo = new FileInfo(file); var tagLib = this.TagsHelper.MetaDataForFile(fileInfo.FullName); var artistToken = ArtistInspectorToken(tagLib.Data); var releaseToken = ReleaseInspectorToken(tagLib.Data); var newFileName = $"{artistToken}_{releaseToken}_CD{ (tagLib.Data.Disk ?? ID3TagsHelper.DetermineDiscNumber(tagLib.Data)).ToString("000") }_{ tagLib.Data.TrackNumber.Value.ToString("0000") }.mp3"; var subFolder = folder == destination ? fileInfo.DirectoryName : destination; var newPath = Path.Combine(destination, subFolder, newFileName.ToFileNameFriendly()); if (!doCopy) { if (fileInfo.FullName != newPath) { if (File.Exists(newPath)) { File.Delete(newPath); } fileInfo.MoveTo(newPath); } } else { fileInfo.CopyTo(newPath, true); } tagLib.Data.Filename = fileInfo.FullName; fileMetaDatas.Add(tagLib.Data); fileInfos.Add(fileInfo); } // Perform InspectorPlugins IEnumerable <AudioMetaData> pluginMetaData = fileMetaDatas.OrderBy(x => x.Filename); foreach (var plugin in this.Plugins.OrderBy(x => x.Order)) { Console.WriteLine($"╟ Running Plugin { plugin.Description }"); OperationResult <IEnumerable <AudioMetaData> > pluginResult = null; try { pluginResult = plugin.Process(pluginMetaData); } catch (Exception ex) { Console.WriteLine($"Plugin Error: [{ ex.ToString() }]"); } if (!pluginResult.IsSuccess) { Console.WriteLine($"Plugin Failed. Error [{ JsonConvert.SerializeObject(pluginResult)}]"); } pluginMetaData = pluginResult.Data; } // Save all plugin modifications to the MetaData foreach (var metadata in pluginMetaData) { this.TagsHelper.WriteTags(metadata, metadata.Filename); } Console.WriteLine("╠═╣"); // Get audiometadata and output details including weight/validity foreach (var fileInfo in fileInfos) { var tagLib = this.TagsHelper.MetaDataForFile(fileInfo.FullName); if (!tagLib.IsSuccess || !tagLib.Data.IsValid) { Console.WriteLine($"■■ INVALID: {tagLib.Data }"); } else { Console.WriteLine(tagLib.Data); } } Console.WriteLine("╚═╝"); } }