using OF_DL.Models.Downloads; using OF_DL.Services; using Spectre.Console; namespace OF_DL.CLI; /// /// Spectre.Console implementation of IDownloadEventHandler. /// Handles all CLI-specific display logic for downloads. /// public class SpectreDownloadEventHandler : IDownloadEventHandler { public async Task WithStatusAsync(string statusMessage, Func> work) { T result = default!; await AnsiConsole.Status() .StartAsync($"[red]{Markup.Escape(statusMessage)}[/]", async ctx => { SpectreStatusReporter reporter = new(ctx); result = await work(reporter); }); return result; } public async Task WithProgressAsync(string description, long maxValue, bool showSize, Func> work) { T result = default!; await AnsiConsole.Progress() .Columns(GetProgressColumns(showSize)) .StartAsync(async ctx => { ProgressTask task = ctx.AddTask($"[red]{Markup.Escape(description)}[/]", false); task.MaxValue = maxValue; task.StartTask(); SpectreProgressReporter progressReporter = new(task); result = await work(progressReporter); task.StopTask(); }); return result; } public void OnContentFound(string contentType, int mediaCount, int objectCount) => AnsiConsole.Markup($"[red]Found {mediaCount} Media from {objectCount} {Markup.Escape(contentType)}\n[/]"); public void OnNoContentFound(string contentType) => AnsiConsole.Markup($"[red]Found 0 {Markup.Escape(contentType)}\n[/]"); public void OnDownloadComplete(string contentType, DownloadResult result) => AnsiConsole.Markup( $"[red]{Markup.Escape(contentType)} Already Downloaded: {result.ExistingDownloads} New {Markup.Escape(contentType)} Downloaded: {result.NewDownloads}[/]\n"); public void OnUserStarting(string username) => AnsiConsole.Markup($"[red]\nScraping Data for {Markup.Escape(username)}\n[/]"); public void OnUserComplete(string username, CreatorDownloadResult result) { AnsiConsole.Markup("\n"); AnsiConsole.Write(new BreakdownChart() .FullSize() .AddItem("Paid Posts", result.PaidPostCount, Color.Red) .AddItem("Posts", result.PostCount, Color.Blue) .AddItem("Archived", result.ArchivedCount, Color.Green) .AddItem("Streams", result.StreamsCount, Color.Purple) .AddItem("Stories", result.StoriesCount, Color.Yellow) .AddItem("Highlights", result.HighlightsCount, Color.Orange1) .AddItem("Messages", result.MessagesCount, Color.LightGreen) .AddItem("Paid Messages", result.PaidMessagesCount, Color.Aqua)); AnsiConsole.Markup("\n"); } public void OnPurchasedTabUserComplete(string username, int paidPostCount, int paidMessagesCount) { AnsiConsole.Markup("\n"); AnsiConsole.Write(new BreakdownChart() .FullSize() .AddItem("Paid Posts", paidPostCount, Color.Red) .AddItem("Paid Messages", paidMessagesCount, Color.Aqua)); AnsiConsole.Markup("\n"); } public void OnScrapeComplete(TimeSpan elapsed) => AnsiConsole.Markup($"[green]Scrape Completed in {elapsed.TotalMinutes:0.00} minutes\n[/]"); public void OnMessage(string message) => AnsiConsole.Markup($"[red]{Markup.Escape(message)}\n[/]"); private static ProgressColumn[] GetProgressColumns(bool showScrapeSize) { List progressColumns; if (showScrapeSize) { progressColumns = [ new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn() ]; } else { progressColumns = [ new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn() ]; } return progressColumns.ToArray(); } }