using ApplicationServices; using CommandLine; using DataLayer; using Dinah.Core; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace LibationCli; [Verb("set-status", HelpText = """ Set download statuses throughout library based on whether each book's audio file can be found. """)] public class SetDownloadStatusOptions : OptionsBase { //https://github.com/commandlineparser/commandline/wiki/Option-Groups [Option(shortName: 'd', longName: "downloaded", Group = "Download Status", HelpText = "if the audio file can be found, mark the book 'Downloaded'")] public bool SetDownloaded { get; set; } [Option(shortName: 'p', longName: "download-pending", Group = "Download Status", HelpText = "if the audio file cannot be found, mark the book 'Download Pending' (previously 'Not Downloaded')")] public bool SetDownloadPending { get; set; } /// /// What was called while the status was named "Not Downloaded". Kept /// working so scripts written against the old name survive the rename, and kept out of the help so the /// new name is the only one offered. is what the verb acts on. /// [Option(shortName: 'n', longName: "not-downloaded", Group = "Download Status", Hidden = true)] public bool SetNotDownloadedLegacy { get; set; } /// Whether the run was asked for 'Download Pending', under either flag name. internal bool SetPending => SetDownloadPending || SetNotDownloadedLegacy; [Option('f', "force", HelpText = "Set the download status regardless of whether the book's audio file can be found. Only one download status option may be used with this option.")] public bool Force { get; set; } [Value(0, MetaName = "[asins]", HelpText = "Optional product IDs of books on which to set download status.")] public IEnumerable? Asins { get; set; } protected override async Task ProcessAsync() { if (Force && SetDownloaded && SetPending) { PrintVerbUsage("ERROR:\nWhen run with --force option, only one download status option may be used."); return; } var libraryBooks = DbContexts.GetLibrary_Flat_NoTracking(); if (Asins?.Any() is true) { var asins = Asins.Select(a => a.TrimStart('[').TrimEnd(']').ToLower()).ToArray(); libraryBooks = libraryBooks.Where(lb => lb.Book.AudibleProductId.ToLower().In(asins)).ToList(); if (libraryBooks.Count == 0) { Console.Error.WriteLine("Could not find any books matching asins"); return; } } if (Force) { var status = SetDownloaded ? LiberatedStatus.Liberated : LiberatedStatus.NotLiberated; var num = await libraryBooks.UpdateBookStatusAsync(status); Console.WriteLine($"Set LiberatedStatus to '{status}' on {"book".PluralizeWithCount(num)}"); } else { var bulkSetStatus = new BulkSetDownloadStatus(libraryBooks, SetDownloaded, SetPending); await Task.Run(() => bulkSetStatus.Discover()); await bulkSetStatus.ExecuteAsync(); foreach (var msg in bulkSetStatus.Messages) Console.WriteLine(msg); } } }