Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/RipSharp.Tests/Metadata/MetadataServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public async Task LookupAsync_Fallbacks_WhenNoApiKeys()
{
Environment.SetEnvironmentVariable("OMDB_API_KEY", null);
Environment.SetEnvironmentVariable("TMDB_API_KEY", null);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var providers = new List<IMetadataProvider>();
var svc = new MetadataService(providers, notifier);

Expand All @@ -49,7 +49,7 @@ public async Task LookupAsync_Fallbacks_WhenNoApiKeys()
[Fact]
public async Task LookupAsync_ReturnsFromFirstProvider_WhenMatch()
{
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider1 = Substitute.For<IMetadataProvider>();
provider1.Name.Returns("Provider1");
provider1.LookupAsync("test", false, null).Returns(new ContentMetadata { Title = "Test Movie", Year = 2020, Type = "movie" });
Expand All @@ -72,7 +72,7 @@ public async Task LookupAsync_ReturnsFromFirstProvider_WhenMatch()
[Fact]
public async Task LookupAsync_TriesSecondProvider_WhenFirstReturnsNull()
{
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider1 = Substitute.For<IMetadataProvider>();
provider1.Name.Returns("Provider1");
provider1.LookupAsync("test", false, null).Returns((ContentMetadata?)null);
Expand All @@ -96,7 +96,7 @@ public async Task LookupAsync_TriesSecondProvider_WhenFirstReturnsNull()
[Fact]
public async Task LookupAsync_UsesTitleVariations_WhenOriginalFails()
{
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = Substitute.For<IMetadataProvider>();
provider.Name.Returns("TestProvider");
provider.LookupAsync("MOVIE_TITLE_2023", Arg.Any<bool>(), Arg.Any<int?>()).Returns((ContentMetadata?)null);
Expand All @@ -117,7 +117,7 @@ public async Task LookupAsync_UsesTitleVariations_WhenOriginalFails()
[Fact]
public async Task LookupAsync_ShowsDifferentMessage_ForSimplifiedTitle()
{
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = Substitute.For<IMetadataProvider>();
provider.Name.Returns("TestProvider");
provider.LookupAsync("SIMPSONS_WS", Arg.Any<bool>(), Arg.Any<int?>()).Returns((ContentMetadata?)null);
Expand All @@ -137,7 +137,7 @@ public async Task LookupAsync_ShowsDifferentMessage_ForSimplifiedTitle()
[Fact]
public async Task LookupAsync_ShowsNormalMessage_ForOriginalTitle()
{
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = Substitute.For<IMetadataProvider>();
provider.Name.Returns("TestProvider");
provider.LookupAsync("Test Movie", Arg.Any<bool>(), Arg.Any<int?>()).Returns(new ContentMetadata { Title = "Test Movie", Year = 2020, Type = "movie" });
Expand Down
16 changes: 8 additions & 8 deletions src/RipSharp.Tests/Metadata/OmdbMetadataProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public async Task LookupAsync_ReturnsMetadata_WhenMovieFound()
{
var json = @"{""Response"":""True"",""Title"":""Inception"",""Year"":""2010"",""Type"":""movie""}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new OmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("inception", isTv: false, year: null);
Expand All @@ -37,7 +37,7 @@ public async Task LookupAsync_ReturnsMetadata_WhenTvSeriesFound()
{
var json = @"{""Response"":""True"",""Title"":""Breaking Bad"",""Year"":""2008-2013"",""Type"":""series""}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new OmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("breaking bad", isTv: true, year: 2008);
Expand All @@ -53,7 +53,7 @@ public async Task LookupAsync_ReturnsNull_WhenResponseIsFalse()
{
var json = @"{""Response"":""False"",""Error"":""Movie not found!""}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new OmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("nonexistent movie", isTv: false, year: null);
Expand All @@ -66,7 +66,7 @@ public async Task LookupAsync_ReturnsNull_WhenJsonMalformed()
{
var json = @"{invalid json}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new OmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("test", isTv: false, year: null);
Expand All @@ -79,7 +79,7 @@ public async Task LookupAsync_ReturnsNull_WhenHttpRequestFails()
{
var handler = new FakeHttpMessageHandler(HttpStatusCode.ServiceUnavailable);
var httpClient = new HttpClient(handler);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new OmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("test", isTv: false, year: null);
Expand All @@ -91,7 +91,7 @@ public async Task LookupAsync_ReturnsNull_WhenHttpRequestFails()
public void Name_ReturnsOMDB()
{
var httpClient = new HttpClient();
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new OmdbMetadataProvider(httpClient, "test-key", notifier);

// Act & Assert
Expand All @@ -104,7 +104,7 @@ public async Task LookupAsync_IncludesYear_WhenProvided()
var json = @"{""Response"":""True"",""Title"":""Dune"",""Year"":""2021"",""Type"":""movie""}";
var handler = new FakeHttpMessageHandler(json);
var httpClient = new HttpClient(handler);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new OmdbMetadataProvider(httpClient, "test-key", notifier);

await provider.LookupAsync("dune", isTv: false, year: 2021);
Expand All @@ -119,7 +119,7 @@ public async Task LookupAsync_HandlesYearParsingFailure()
{
var json = @"{""Response"":""True"",""Title"":""Test"",""Year"":""N/A"",""Type"":""movie""}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new OmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("test", isTv: false, year: 2020);
Expand Down
20 changes: 10 additions & 10 deletions src/RipSharp.Tests/Metadata/TmdbMetadataProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public async Task LookupAsync_ReturnsMetadata_WhenMovieFound()
{
var json = @"{""results"":[{""title"":""The Matrix"",""release_date"":""1999-03-31""}]}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("the matrix", isTv: false, year: null);
Expand All @@ -37,7 +37,7 @@ public async Task LookupAsync_ReturnsMetadata_WhenTvSeriesFound()
{
var json = @"{""results"":[{""name"":""Game of Thrones"",""first_air_date"":""2011-04-17""}]}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("game of thrones", isTv: true, year: null);
Expand All @@ -53,7 +53,7 @@ public async Task LookupAsync_ReturnsNull_WhenNoResultsFound()
{
var json = @"{""results"":[]}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("nonexistent movie", isTv: false, year: null);
Expand All @@ -66,7 +66,7 @@ public async Task LookupAsync_ReturnsNull_WhenJsonMalformed()
{
var json = @"{invalid json}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("test", isTv: false, year: null);
Expand All @@ -79,7 +79,7 @@ public async Task LookupAsync_ReturnsNull_WhenHttpRequestFails()
{
var handler = new FakeHttpMessageHandler(HttpStatusCode.ServiceUnavailable);
var httpClient = new HttpClient(handler);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("test", isTv: false, year: null);
Expand All @@ -91,7 +91,7 @@ public async Task LookupAsync_ReturnsNull_WhenHttpRequestFails()
public void Name_ReturnsTMDB()
{
var httpClient = new HttpClient();
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

// Act & Assert
Expand All @@ -103,7 +103,7 @@ public async Task LookupAsync_HandlesMovieWithoutReleaseDate()
{
var json = @"{""results"":[{""title"":""Upcoming Movie""}]}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("upcoming", isTv: false, year: 2025);
Expand All @@ -118,7 +118,7 @@ public async Task LookupAsync_HandlesTvWithoutAirDate()
{
var json = @"{""results"":[{""name"":""New Series""}]}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("new series", isTv: true, year: 2026);
Expand All @@ -133,7 +133,7 @@ public async Task LookupAsync_HandlesShortDateString()
{
var json = @"{""results"":[{""title"":""Test Movie"",""release_date"":""202""}]}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("test", isTv: false, year: 2020);
Expand All @@ -147,7 +147,7 @@ public async Task LookupAsync_UsesFirstResult_WhenMultipleResults()
{
var json = @"{""results"":[{""title"":""First Movie"",""release_date"":""2020-01-01""},{""title"":""Second Movie"",""release_date"":""2021-01-01""}]}";
var httpClient = CreateHttpClient(json);
var notifier = Substitute.For<IProgressNotifier>();
var notifier = Substitute.For<IConsoleWriter>();
var provider = new TmdbMetadataProvider(httpClient, "test-key", notifier);

var result = await provider.LookupAsync("movie", isTv: false, year: null);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace RipSharp.Abstractions;

public interface IProgressNotifier
/// <summary>
/// Abstraction for writing styled output messages to the console.
/// </summary>
public interface IConsoleWriter
{
void Info(string message);
void Success(string message);
Expand Down
44 changes: 44 additions & 0 deletions src/RipSharp/Abstractions/IProgressDisplay.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
namespace RipSharp.Abstractions;

/// <summary>
/// Abstraction for displaying progress bars and animated progress indicators.
/// </summary>
public interface IProgressDisplay
{
/// <summary>
/// Starts a progress tracking context and executes the provided action.
/// </summary>
Task ExecuteAsync(Func<IProgressContext, Task> action);
}

/// <summary>
/// Context for managing multiple progress tasks.
/// </summary>
public interface IProgressContext
{
/// <summary>
/// Adds a new progress task with the given description and maximum value.
/// </summary>
IProgressTask AddTask(string description, long maxValue);
}

/// <summary>
/// Represents an individual progress task that can be updated.
/// </summary>
public interface IProgressTask
{
/// <summary>
/// Gets or sets the current progress value.
/// </summary>
long Value { get; set; }

/// <summary>
/// Gets or sets the task description (can include markup for styling).
/// </summary>
string Description { get; set; }

/// <summary>
/// Stops the task, marking it as complete.
/// </summary>
void StopTask();
}
17 changes: 9 additions & 8 deletions src/RipSharp/Core/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

using NetEscapades.Configuration.Yaml;

using Spectre.Console;

namespace RipSharp.Core;

Expand All @@ -29,7 +28,8 @@ public static async Task<int> Main(string[] args)
.ConfigureServices((ctx, services) =>
{
services.Configure<AppConfig>(ctx.Configuration);
services.AddSingleton<IProgressNotifier, ConsoleProgressNotifier>();
services.AddSingleton<IConsoleWriter, ConsoleWriter>();
services.AddSingleton<IProgressDisplay, SpectreProgressDisplay>();
services.AddSingleton<IUserPrompt, ConsoleUserPrompt>();
services.AddSingleton<IProcessRunner, ProcessRunner>();
services.AddSingleton<IMakeMkvService, MakeMkvService>();
Expand All @@ -43,7 +43,7 @@ public static async Task<int> Main(string[] args)

services.AddSingleton<IEnumerable<IMetadataProvider>>(sp =>
{
var notifier = sp.GetRequiredService<IProgressNotifier>();
var notifier = sp.GetRequiredService<IConsoleWriter>();
var httpClient = new HttpClient();
var providers = new List<IMetadataProvider>();

Expand All @@ -59,7 +59,7 @@ public static async Task<int> Main(string[] args)

services.AddSingleton<ITvEpisodeTitleProvider>(sp =>
{
var notifier = sp.GetRequiredService<IProgressNotifier>();
var notifier = sp.GetRequiredService<IConsoleWriter>();
if (!string.IsNullOrWhiteSpace(tvdbKey))
return new TvdbMetadataProvider(new HttpClient(), tvdbKey, notifier);
return new NullEpisodeTitleProvider();
Expand All @@ -75,25 +75,26 @@ public static async Task<int> Main(string[] args)

if (options.ShowHelp)
{
RipOptions.DisplayHelp();
RipOptions.DisplayHelp(new ConsoleWriter());
return 0;
}

var ripper = host.Services.GetRequiredService<IDiscRipper>();
var writer = host.Services.GetRequiredService<IConsoleWriter>();
var files = await ripper.ProcessDiscAsync(options);

if (files.Count > 0)
{
AnsiConsole.MarkupLine($"[{ConsoleColors.Success}]Success! Files created:[/]");
writer.Success("Success! Files created:");
foreach (var f in files)
{
AnsiConsole.WriteLine(Markup.Escape(f));
writer.Plain(f);
}
return 0;
}
else
{
AnsiConsole.MarkupLine($"[{ConsoleColors.Error}]Failed to process disc[/]");
writer.Error("Failed to process disc");
return 1;
}
}
Expand Down
Loading
Loading