using System; using System.Collections.Generic; using System.IO; using System.Linq; using static AutoTag.cli.Helpers; using TagFile = TagLib.File; namespace AutoTag.cli; internal static class AutoTag { private static void Main(string[] args) { if (args.Length != 3 || args[0] != "albums" && args[0] != "playlists") { Console.WriteLine("Usage: autotag "); Environment.Exit(1); } var type = args[0] == "albums" ? FolderType.Albums : FolderType.Playlists; var inputDir = new Folder(args[1], type); var outputDir = args[2]; switch (inputDir.Type) { case FolderType.Albums: { foreach (var track in Directory.EnumerateFiles(inputDir.Path, "*.*", SearchOption.AllDirectories).Where(IsAllowed)) { Console.WriteLine("<- " + track); var tagFile = TagFile.Create(track); if (tagFile.Tag.Title.Contains(" (Original Mix)")) tagFile.Tag.Title = tagFile.Tag.Title.Replace(" (Original Mix)", ""); if (tagFile.Tag.AlbumArtists.Length == 0) tagFile.Tag.AlbumArtists = new[] { tagFile.Tag.Performers[0] }; if (string.IsNullOrWhiteSpace(tagFile.Tag.Album)) tagFile.Tag.Album = tagFile.Tag.Title; var outputFileDirectory = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), CleanFileName(tagFile.Tag.Album)); Directory.CreateDirectory(outputFileDirectory); if (tagFile.Tag.Track < 1) tagFile.Tag.Track = 1; var outputFilePath = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), CleanFileName(tagFile.Tag.Album), CleanFileName($"{tagFile.Tag.Track}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}")); if (tagFile.Tag.Disc != 0 && tagFile.Tag.Disc != 1) outputFilePath = Path.Combine(outputDir, CleanFileName(tagFile.Tag.AlbumArtists[0]), CleanFileName(tagFile.Tag.Album), CleanFileName($"Disc{tagFile.Tag.Disc} - {tagFile.Tag.Track}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}")); tagFile.Save(); File.Copy(track, outputFilePath, true); var newTagFile = TagFile.Create(outputFilePath); newTagFile.Tag.Comment = null; newTagFile.Tag.Genres = null; newTagFile.Save(); Console.WriteLine("-> " + outputFilePath); Console.WriteLine(); } break; } case FolderType.Playlists: { foreach (var playlist in Directory.GetDirectories(inputDir.Path)) { var tracks = Directory.EnumerateFiles(playlist, "*.*", SearchOption.AllDirectories).Where(IsAllowed).OrderBy(s => s, new AlphanumComparator()); uint i = 1; var trackCount = tracks.Count(); var playlistName = Path.GetFileName(playlist); foreach (var track in tracks) { Console.WriteLine("<- " + track); var tagFile = TagFile.Create(track); var outputFileDirectory = Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName)); Directory.CreateDirectory(outputFileDirectory); var outputFilePath = Path.Combine(outputDir, "Various Artists", CleanFileName(playlistName), CleanFileName(tagFile.Tag.Performers.Length == 0 ? $"{i}. {tagFile.Tag.Title}{Path.GetExtension(track)}" : $"{i}. {tagFile.Tag.Performers[0]} - {tagFile.Tag.Title}{Path.GetExtension(track)}")); tagFile.Save(); File.Copy(track, outputFilePath, true); var newTagFile = TagFile.Create(outputFilePath); newTagFile.Tag.Comment = null; newTagFile.Tag.Genres = null; newTagFile.Tag.Album = playlistName; newTagFile.Tag.Track = i++; newTagFile.Tag.TrackCount = (uint)trackCount; newTagFile.Tag.AlbumArtists = new[] { "Various Artists" }; if (newTagFile.Tag.Performers.Length == 0) newTagFile.Tag.Performers = new[] { "Various Artists" }; newTagFile.Save(); Console.WriteLine("-> " + outputFilePath); Console.WriteLine(); } } break; } default: throw new ArgumentOutOfRangeException(); } } } internal class Folder { public readonly string Path; public readonly FolderType Type; public Folder(string path, FolderType type) { Path = path; Type = type; } } internal enum FolderType { Albums, Playlists } internal static class Helpers { private static readonly List AllowedFileTypes = new() { ".flac", ".opus", ".ogg", ".mp3", ".m4a" }; internal static bool IsAllowed(string filename) => AllowedFileTypes.Any(filename.EndsWith); internal static string CleanFileName(string fileName) { return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty)).Replace(":", " -").Replace("\\", " "); } }