feat: Custom format lists are now grouped by category

When using `--list-custom-formats` with either the `sonarr` or `radarr`
subcommand, custom formats will be grouped according to the respective
tables at the top of the "Collection of custom formats" page.
pull/136/head
Robert Dailey 2 years ago
parent 27b252f405
commit 7a25f79fa8

@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- For both Sonarr and Radarr, the custom formats in the output of `--list-custom-formats` are now
grouped by their category, as determined by the tables at the top of the "Collection of custom
formats" pages in the guide for each service.
## [2.5.0] - 2022-09-11
### Added

@ -9,7 +9,7 @@ public static class NewCf
public static CustomFormatData Data(string name, string trashId, int? score = null)
{
var json = JObject.Parse($"{{'name':'{name}'}}");
return new CustomFormatData(name, trashId, score, new JObject(json));
return new CustomFormatData("", name, trashId, score, new JObject(json));
}
public static ProcessedCustomFormatData Processed(string name, string trashId, int? score = null)
@ -19,7 +19,7 @@ public static class NewCf
public static ProcessedCustomFormatData Processed(string name, string trashId, int? score, JObject json)
{
return new ProcessedCustomFormatData(new CustomFormatData(name, trashId, score, json));
return new ProcessedCustomFormatData(new CustomFormatData("", name, trashId, score, json));
}
public static ProcessedCustomFormatData Processed(string name, string trashId, JObject json)
@ -38,7 +38,7 @@ public static class NewCf
public static ProcessedCustomFormatData Processed(string name, string trashId, JObject json,
TrashIdMapping? cacheEntry)
{
return new ProcessedCustomFormatData(new CustomFormatData(name, trashId, null, json))
return new ProcessedCustomFormatData(new CustomFormatData("", name, trashId, null, json))
{
CacheEntry = cacheEntry
};

@ -1,6 +1,5 @@
using System.Collections.ObjectModel;
using FluentAssertions;
using Newtonsoft.Json.Linq;
using NSubstitute;
using NUnit.Framework;
using Serilog;
@ -9,6 +8,7 @@ using TrashLib.Services.CustomFormat;
using TrashLib.Services.CustomFormat.Models;
using TrashLib.Services.CustomFormat.Models.Cache;
using TrashLib.Services.CustomFormat.Processors.PersistenceSteps;
using TrashLib.TestLibrary;
namespace TrashLib.Tests.CustomFormat;
@ -31,7 +31,7 @@ public class CachePersisterTest
private static ProcessedCustomFormatData QuickMakeCf(string cfName, string trashId, int cfId)
{
var cf = new CustomFormatData(cfName, trashId, null, new JObject());
var cf = NewCf.Data(cfName, trashId);
return new ProcessedCustomFormatData(cf)
{
CacheEntry = new TrashIdMapping(trashId, cfName) {CustomFormatId = cfId}
@ -128,7 +128,7 @@ public class CachePersisterTest
var customFormatData = new List<ProcessedCustomFormatData>
{
new(new CustomFormatData("", "trashid", null, new JObject()))
new(NewCf.Data("", "trashid"))
{CacheEntry = new TrashIdMapping("trashid", "cfname", 10)}
};

@ -0,0 +1,108 @@
using System.IO.Abstractions;
using System.IO.Abstractions.TestingHelpers;
using AutoFixture.NUnit3;
using FluentAssertions;
using NUnit.Framework;
using TestLibrary.AutoFixture;
using TrashLib.Services.CustomFormat.Guide;
using TrashLib.Startup;
namespace TrashLib.Tests.CustomFormat.Guide;
[TestFixture]
[Parallelizable(ParallelScope.All)]
public class CustomFormatCategoryParserTest
{
[Test, AutoMockData]
public void It_works(
[Frozen] IAppPaths paths,
[Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs,
CustomFormatCategoryParser sut)
{
const string markdown = @"
## INDEX
------
| Audio Advanced #1 | Audio Advanced #2 | Anime | Anime |
| ----------------------------------------- | ------------------------------- | --------------------------------------------------------------------- | ----------- |
| [TrueHD ATMOS](#truehd-atmos) | [FLAC](#flac) | [Anime Web Tier 01 (Muxers)](#anime-web-tier-01-muxers) | [v0](#v0) |
| [DTS X](#dts-x) | [PCM](#pcm) | [Anime Web Tier 02 (Top FanSubs)](#anime-web-tier-02-top-fansubs) | [v1](#v1) |
| [ATMOS (undefined)](#atmos-undefined) | [DTS-HD HRA](#dts-hd-hra) | [Anime Web Tier 03 (Official Subs)](#anime-web-tier-03-official-subs) | [v2](#v2) |
| [DD+ ATMOS](#dd-atmos) | [AAC](#aac) | [Anime Web Tier 04 (Official Subs)](#anime-web-tier-04-official-subs) | [v3](#v3) |
| [TrueHD](#truehd) | [DD](#dd) | [Anime Web Tier 05 (FanSubs)](#anime-web-tier-05-fansubs) | [v4](#v4) |
| [DTS-HD MA](#dts-hd-ma) | [MP3](#mp3) | [Anime Web Tier 06 (FanSubs)](#anime-web-tier-06-fansubs) | [VRV](#vrv) |
| [DD+](#ddplus) | [Opus](#opus) | [Anime Raws](#anime-raws) | |
| [DTS-ES](#dts-es) | | [Anime LQ Groups](#anime-lq-groups) | |
| [DTS](#dts) | | | |
| | | | |
------
| Movie Versions | Unwanted |
| --------------------------------------------- | ---------------------------------- |
| [Hybrid](#hybrid) | [BR-DISK](#br-disk) |
| [Remaster](#remaster) | [EVO (no WEBDL)](#evo-no-webdl) |
| [4K Remaster](#4k-remaster) | [LQ](#lq) |
| [Special Editions](#special-edition) | [x265 (720/1080p)](#x265-7201080p) |
| [Criterion Collection](#criterion-collection) | [3D](#3d) |
| [Theatrical Cut](#theatrical-cut) | [No-RlsGroup](#no-rlsgroup) |
| [IMAX](#imax) | [Obfuscated](#obfuscated) |
| [IMAX Enhanced](#imax-enhanced) | [DV (WEBDL)](#dv-webdl) |
| | |
------
";
var file = paths.RepoDirectory
.SubDirectory("docs")
.SubDirectory("Radarr")
.File("Radarr-collection-of-custom-formats.md");
fs.AddFile(file.FullName, new MockFileData(markdown));
var result = sut.Parse(file);
result.Select(x => x.CategoryName).Distinct()
.Should().BeEquivalentTo(
"Anime",
"Audio Advanced #1",
"Audio Advanced #2",
"Movie Versions",
"Unwanted"
);
result.Where(x => x.CategoryName == "Audio Advanced #1").Select(x => (x.CfName, x.CfAnchor))
.Should().BeEquivalentTo(new[]
{
("TrueHD ATMOS", "truehd-atmos"),
("DTS X", "dts-x"),
("ATMOS (undefined)", "atmos-undefined"),
("DD+ ATMOS", "dd-atmos"),
("TrueHD", "truehd"),
("DTS-HD MA", "dts-hd-ma"),
("DD+", "ddplus"),
("DTS-ES", "dts-es"),
("DTS", "dts")
});
result.Where(x => x.CategoryName == "Anime").Select(x => (x.CfName, x.CfAnchor))
.Should().BeEquivalentTo(new[]
{
("Anime Web Tier 01 (Muxers)", "anime-web-tier-01-muxers"),
("Anime Web Tier 02 (Top FanSubs)", "anime-web-tier-02-top-fansubs"),
("Anime Web Tier 03 (Official Subs)", "anime-web-tier-03-official-subs"),
("Anime Web Tier 04 (Official Subs)", "anime-web-tier-04-official-subs"),
("Anime Web Tier 05 (FanSubs)", "anime-web-tier-05-fansubs"),
("Anime Web Tier 06 (FanSubs)", "anime-web-tier-06-fansubs"),
("Anime Raws", "anime-raws"),
("Anime LQ Groups", "anime-lq-groups"),
("v0", "v0"),
("v1", "v1"),
("v2", "v2"),
("v3", "v3"),
("v4", "v4"),
("VRV", "vrv")
});
}
}

@ -1,87 +0,0 @@
using System.IO.Abstractions;
using System.IO.Abstractions.TestingHelpers;
using AutoFixture.NUnit3;
using FluentAssertions;
using NUnit.Framework;
using TestLibrary.AutoFixture;
using TrashLib.Services.CustomFormat.Guide;
using TrashLib.Startup;
namespace TrashLib.Tests.CustomFormat.Guide;
[TestFixture]
[Parallelizable(ParallelScope.All)]
public class CustomFormatGroupParserTest
{
[Test, AutoMockData]
public void It_works(
[Frozen] IAppPaths paths,
[Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs,
CustomFormatGroupParser sut)
{
const string markdown = @"
## INDEX
------
| Audio Advanced #1 | Audio Advanced #2 |
| ----------------------------------------- | ------------------------------- |
| [TrueHD ATMOS](#truehd-atmos) | [FLAC](#flac) |
| [DTS X](#dts-x) | [PCM](#pcm) |
| [ATMOS (undefined)](#atmos-undefined) | [DTS-HD HRA](#dts-hd-hra) |
| [DD+ ATMOS](#dd-atmos) | [AAC](#aac) |
| [TrueHD](#truehd) | [DD](#dd) |
| [DTS-HD MA](#dts-hd-ma) | [MP3](#mp3) |
| [DD+](#ddplus) | [Opus](#opus) |
| [DTS-ES](#dts-es) | |
| [DTS](#dts) | |
| | |
------
| Movie Versions | Unwanted |
| --------------------------------------------- | ---------------------------------- |
| [Hybrid](#hybrid) | [BR-DISK](#br-disk) |
| [Remaster](#remaster) | [EVO (no WEBDL)](#evo-no-webdl) |
| [4K Remaster](#4k-remaster) | [LQ](#lq) |
| [Special Editions](#special-edition) | [x265 (720/1080p)](#x265-7201080p) |
| [Criterion Collection](#criterion-collection) | [3D](#3d) |
| [Theatrical Cut](#theatrical-cut) | [No-RlsGroup](#no-rlsgroup) |
| [IMAX](#imax) | [Obfuscated](#obfuscated) |
| [IMAX Enhanced](#imax-enhanced) | [DV (WEBDL)](#dv-webdl) |
| | |
------
";
var file = paths.RepoDirectory
.SubDirectory("docs")
.SubDirectory("Radarr")
.File("Radarr-collection-of-custom-formats.md");
fs.AddFile(file.FullName, new MockFileData(markdown));
var result = sut.Parse();
result.Keys.Should().BeEquivalentTo(
"Audio Advanced #1",
"Audio Advanced #2",
"Movie Versions",
"Unwanted"
);
result.Should().ContainKey("Audio Advanced #1")
.WhoseValue.Should().BeEquivalentTo(new[]
{
new CustomFormatGroupItem("TrueHD ATMOS", "truehd-atmos"),
new CustomFormatGroupItem("DTS X", "dts-x"),
new CustomFormatGroupItem("ATMOS (undefined)", "atmos-undefined"),
new CustomFormatGroupItem("DD+ ATMOS", "dd-atmos"),
new CustomFormatGroupItem("TrueHD", "truehd"),
new CustomFormatGroupItem("DTS-HD MA", "dts-hd-ma"),
new CustomFormatGroupItem("DD+", "ddplus"),
new CustomFormatGroupItem("DTS-ES", "dts-es"),
new CustomFormatGroupItem("DTS", "dts")
});
}
}

@ -1,3 +1,4 @@
using System.IO.Abstractions;
using System.IO.Abstractions.Extensions;
using System.IO.Abstractions.TestingHelpers;
using FluentAssertions;
@ -20,19 +21,22 @@ public class CustomFormatLoaderTest : IntegrationFixture
var sut = Resolve<ICustomFormatLoader>();
Fs.AddFile("first.json", new MockFileData("{'name':'first','trash_id':'1'}"));
Fs.AddFile("second.json", new MockFileData("{'name':'second','trash_id':'2'}"));
Fs.AddFile("collection_of_cfs.md", new MockFileData(""));
var results = sut.LoadAllCustomFormatsAtPaths(new[] {Fs.CurrentDirectory()});
var dir = Fs.CurrentDirectory();
var results = sut.LoadAllCustomFormatsAtPaths(new[] {dir}, dir.File("collection_of_cfs.md"));
results.Should().BeEquivalentTo(new[]
{
NewCf.Data("first", "1"),
NewCf.Data("second", "2")
NewCf.Data("first", "1") with {FileName = "first.json"},
NewCf.Data("second", "2") with {FileName = "second.json"}
});
}
[Test]
public void Trash_properties_are_removed()
{
Fs.AddFile("collection_of_cfs.md", new MockFileData(""));
Fs.AddFile("first.json", new MockFileData(@"
{
'name':'first',
@ -44,12 +48,14 @@ public class CustomFormatLoaderTest : IntegrationFixture
var sut = Resolve<ICustomFormatLoader>();
var results = sut.LoadAllCustomFormatsAtPaths(new[] {Fs.CurrentDirectory()});
var dir = Fs.CurrentDirectory();
var results = sut.LoadAllCustomFormatsAtPaths(
new[] {dir}, dir.File("collection_of_cfs.md"));
const string expectedExtraJson = @"{'name':'first','extra': 'e1'}";
results.Should()
.ContainSingle().Which.ExtraJson.Should()
.ContainSingle().Which.Json.Should()
.BeEquivalentTo(JObject.Parse(expectedExtraJson), op => op.Using(new JsonEquivalencyStep()));
}
}

@ -39,7 +39,7 @@ public class GuideProcessorTest
public CustomFormatData ReadCustomFormat(string textFile)
{
var parser = new CustomFormatParser();
return parser.ParseCustomFormatData(ReadText(textFile));
return parser.ParseCustomFormatData(ReadText(textFile), "");
}
public string ReadText(string textFile) => Data.ReadData(textFile);

@ -1,6 +1,5 @@
using System.Collections.ObjectModel;
using FluentAssertions;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using TestLibrary.AutoFixture;
using TestLibrary.FluentAssertions;
@ -181,7 +180,7 @@ public class CustomFormatStepTest
var guideCfs = new List<CustomFormatData>
{
new("3D", "id1", null, new JObject())
NewCf.Data("3D", "id1")
};
processor.Process(guideCfs, Array.Empty<CustomFormatConfig>(), cache);
@ -197,7 +196,7 @@ public class CustomFormatStepTest
{
var guideData = new List<CustomFormatData>
{
new("name2", "id1", null, new JObject())
NewCf.Data("name2", "id1")
};
var testConfig = new List<CustomFormatConfig>

@ -9,4 +9,6 @@ public interface IRepoPaths
IReadOnlyCollection<IDirectoryInfo> SonarrQualityPaths { get; }
IReadOnlyCollection<IDirectoryInfo> RadarrQualityPaths { get; }
IReadOnlyCollection<IDirectoryInfo> SonarrCustomFormatPaths { get; }
IFileInfo RadarrCollectionOfCustomFormats { get; }
IFileInfo SonarrCollectionOfCustomFormats { get; }
}

@ -7,5 +7,7 @@ public record RepoPaths(
IReadOnlyCollection<IDirectoryInfo> SonarrReleaseProfilePaths,
IReadOnlyCollection<IDirectoryInfo> RadarrQualityPaths,
IReadOnlyCollection<IDirectoryInfo> SonarrQualityPaths,
IReadOnlyCollection<IDirectoryInfo> SonarrCustomFormatPaths
IReadOnlyCollection<IDirectoryInfo> SonarrCustomFormatPaths,
IFileInfo RadarrCollectionOfCustomFormats,
IFileInfo SonarrCollectionOfCustomFormats
) : IRepoPaths;

@ -24,13 +24,16 @@ public class RepoPathsFactory : IRepoPathsFactory
public IRepoPaths Create()
{
var docs = _paths.RepoDirectory.SubDirectory("docs");
var metadata = _metadata.Value;
return new RepoPaths(
ToDirectoryInfoList(metadata.JsonPaths.Radarr.CustomFormats),
ToDirectoryInfoList(metadata.JsonPaths.Sonarr.ReleaseProfiles),
ToDirectoryInfoList(metadata.JsonPaths.Radarr.Qualities),
ToDirectoryInfoList(metadata.JsonPaths.Sonarr.Qualities),
ToDirectoryInfoList(metadata.JsonPaths.Sonarr.CustomFormats)
ToDirectoryInfoList(metadata.JsonPaths.Sonarr.CustomFormats),
docs.SubDirectory("Radarr").File("Radarr-collection-of-custom-formats.md"),
docs.SubDirectory("Sonarr").File("sonarr-collection-of-custom-formats.md")
);
}
}

@ -14,11 +14,21 @@ public class GuideDataLister : IGuideDataLister
public void ListCustomFormats(IEnumerable<CustomFormatData> customFormats)
{
_console.Output.WriteLine("\nList of Custom Formats in the TRaSH Guides:\n");
_console.Output.WriteLine("\nList of Custom Formats in the TRaSH Guides:");
foreach (var cf in customFormats)
var categories = customFormats
.ToLookup(x => x.Category)
.OrderBy(x => x.Key);
foreach (var cat in categories)
{
_console.Output.WriteLine($" - {cf.TrashId} # {cf.Name}");
var title = cat.Key is not null ? $"{cat.Key}" : "[No Category]";
_console.Output.WriteLine($"\n{title}\n");
foreach (var cf in cat)
{
_console.Output.WriteLine($" - {cf.TrashId} # {cf.Name}");
}
}
_console.Output.WriteLine(

@ -30,5 +30,6 @@ public class CustomFormatAutofacModule : Module
builder.RegisterType<JsonTransactionStep>().As<IJsonTransactionStep>();
builder.RegisterType<CustomFormatApiPersistenceStep>().As<ICustomFormatApiPersistenceStep>();
builder.RegisterType<QualityProfileApiPersistenceStep>().As<IQualityProfileApiPersistenceStep>();
builder.RegisterType<CustomFormatCategoryParser>().As<ICustomFormatCategoryParser>();
}
}

@ -0,0 +1,3 @@
namespace TrashLib.Services.CustomFormat.Guide;
public record CustomFormatCategoryItem(string CategoryName, string CfName, string CfAnchor);

@ -1,34 +1,19 @@
using System.Collections.ObjectModel;
using System.IO.Abstractions;
using System.Text.RegularExpressions;
using Common.Extensions;
using TrashLib.Startup;
namespace TrashLib.Services.CustomFormat.Guide;
public record CustomFormatGroupItem(string Name, string Anchor);
public class CustomFormatGroupParser
public class CustomFormatCategoryParser : ICustomFormatCategoryParser
{
private readonly IAppPaths _paths;
private static readonly Regex TableRegex = new(@"^\s*\|(.*)\|\s*$");
private static readonly Regex LinkRegex = new(@"^\[(.+?)\]\(#(.+?)\)$");
public CustomFormatGroupParser(IAppPaths paths)
public ICollection<CustomFormatCategoryItem> Parse(IFileInfo collectionOfCustomFormatsMdFile)
{
_paths = paths;
}
public IDictionary<string, ReadOnlyCollection<CustomFormatGroupItem>> Parse()
{
var mdFile = _paths.RepoDirectory
.SubDirectory("docs")
.SubDirectory("Radarr")
.File("Radarr-collection-of-custom-formats.md");
var columns = new List<List<string>>();
using var md = mdFile.OpenText();
using var md = collectionOfCustomFormatsMdFile.OpenText();
while (!md.EndOfStream)
{
var rows = ParseTable(md);
@ -41,15 +26,19 @@ public class CustomFormatGroupParser
.Select(x => x.ToList()));
}
return columns.ToDictionary(
x => x[0],
x => x.Skip(1).Select(ParseLink).NotNull().ToList().AsReadOnly());
return columns
.GroupBy(x => x[0], x => x.Skip(1))
.SelectMany(x => x.SelectMany(y => y).Distinct().Select(y => ParseLink(x.Key, y)))
.NotNull()
.ToList();
}
private static CustomFormatGroupItem? ParseLink(string markdownLink)
private static CustomFormatCategoryItem? ParseLink(string categoryName, string markdownLink)
{
var match = LinkRegex.Match(markdownLink);
return match.Success ? new CustomFormatGroupItem(match.Groups[1].Value, match.Groups[2].Value) : null;
return match.Success
? new CustomFormatCategoryItem(categoryName, match.Groups[1].Value, match.Groups[2].Value)
: null;
}
private static IEnumerable<List<string>> ParseTable(TextReader stream)

@ -12,29 +12,44 @@ public class CustomFormatLoader : ICustomFormatLoader
{
private readonly ILogger _log;
private readonly ICustomFormatParser _parser;
private readonly ICustomFormatCategoryParser _categoryParser;
public CustomFormatLoader(ILogger log, ICustomFormatParser parser)
public CustomFormatLoader(ILogger log, ICustomFormatParser parser, ICustomFormatCategoryParser categoryParser)
{
_log = log;
_parser = parser;
_categoryParser = categoryParser;
}
public ICollection<CustomFormatData> LoadAllCustomFormatsAtPaths(IEnumerable<IDirectoryInfo> jsonPaths)
public ICollection<CustomFormatData> LoadAllCustomFormatsAtPaths(
IEnumerable<IDirectoryInfo> jsonPaths,
IFileInfo collectionOfCustomFormats)
{
var categories = _categoryParser.Parse(collectionOfCustomFormats).AsReadOnly();
var jsonFiles = jsonPaths.SelectMany(x => x.GetFiles("*.json"));
return jsonFiles.ToObservable()
.Select(x => Observable.Defer(() => LoadJsonFromFile(x)))
.Select(x => Observable.Defer(() => LoadJsonFromFile(x, categories)))
.Merge(8)
.NotNull()
.ToEnumerable()
.ToList();
}
private IObservable<CustomFormatData?> LoadJsonFromFile(IFileInfo file)
private IObservable<CustomFormatData?> LoadJsonFromFile(IFileInfo file,
IReadOnlyCollection<CustomFormatCategoryItem> categories)
{
return Observable.Using(file.OpenText, x => x.ReadToEndAsync().ToObservable())
.Do(_ => _log.Debug("Parsing CF Json: {Name}", file.Name))
.Select(_parser.ParseCustomFormatData)
.Select(x =>
{
var cf = _parser.ParseCustomFormatData(x, file.Name);
var matchingCategory = categories.FirstOrDefault(y =>
{
var fileName = Path.GetFileNameWithoutExtension(cf.FileName);
return y.CfName.EqualsIgnoreCase(cf.Name) || y.CfAnchor.EqualsIgnoreCase(fileName);
});
return cf with {Category = matchingCategory?.CategoryName};
})
.Catch((JsonException e) =>
{
_log.Warning("Failed to parse JSON file: {File} ({Reason})", file.Name, e.Message);

@ -7,7 +7,7 @@ namespace TrashLib.Services.CustomFormat.Guide;
public class CustomFormatParser : ICustomFormatParser
{
public CustomFormatData ParseCustomFormatData(string guideData)
public CustomFormatData ParseCustomFormatData(string guideData, string fileName)
{
var obj = JObject.Parse(guideData);
@ -29,6 +29,6 @@ public class CustomFormatParser : ICustomFormatParser
trashProperty.Remove();
}
return new CustomFormatData(name, trashId, finalScore, obj);
return new CustomFormatData(fileName, name, trashId, finalScore, obj);
}
}

@ -0,0 +1,8 @@
using System.IO.Abstractions;
namespace TrashLib.Services.CustomFormat.Guide;
public interface ICustomFormatCategoryParser
{
ICollection<CustomFormatCategoryItem> Parse(IFileInfo collectionOfCustomFormatsMdFile);
}

@ -5,5 +5,6 @@ namespace TrashLib.Services.CustomFormat.Guide;
public interface ICustomFormatLoader
{
ICollection<CustomFormatData> LoadAllCustomFormatsAtPaths(IEnumerable<IDirectoryInfo> jsonPaths);
ICollection<CustomFormatData> LoadAllCustomFormatsAtPaths(IEnumerable<IDirectoryInfo> jsonPaths,
IFileInfo collectionOfCustomFormats);
}

@ -4,5 +4,5 @@ namespace TrashLib.Services.CustomFormat.Guide;
public interface ICustomFormatParser
{
CustomFormatData ParseCustomFormatData(string guideData);
CustomFormatData ParseCustomFormatData(string guideData, string fileName);
}

@ -4,8 +4,12 @@ using Newtonsoft.Json.Linq;
namespace TrashLib.Services.CustomFormat.Models;
public record CustomFormatData(
string FileName,
string Name,
string TrashId,
int? Score,
[property: JsonExtensionData] JObject ExtraJson
);
[property: JsonExtensionData] JObject Json
)
{
public string? Category { get; init; }
}

@ -11,7 +11,7 @@ public class ProcessedCustomFormatData
public ProcessedCustomFormatData(CustomFormatData data)
{
_data = data;
Json = _data.ExtraJson;
Json = _data.Json;
}
public string Name => _data.Name;

@ -26,6 +26,8 @@ public class LocalRepoRadarrGuideService : IRadarrGuideService
public ICollection<CustomFormatData> GetCustomFormatData()
{
var paths = _pathsFactory.Create();
return _cfLoader.LoadAllCustomFormatsAtPaths(paths.RadarrCustomFormatPaths);
return _cfLoader.LoadAllCustomFormatsAtPaths(
paths.RadarrCustomFormatPaths,
paths.RadarrCollectionOfCustomFormats);
}
}

@ -38,7 +38,9 @@ public class LocalRepoSonarrGuideService : ISonarrGuideService
public ICollection<CustomFormatData> GetCustomFormatData()
{
var paths = _pathsFactory.Create();
return _cfLoader.LoadAllCustomFormatsAtPaths(paths.SonarrCustomFormatPaths);
return _cfLoader.LoadAllCustomFormatsAtPaths(
paths.SonarrCustomFormatPaths,
paths.SonarrCollectionOfCustomFormats);
}
private IEnumerable<ReleaseProfileData> GetReleaseProfileDataImpl()

Loading…
Cancel
Save