From 1d7ea48505f11ec18c2e113abbfb7b4687a1ae5f Mon Sep 17 00:00:00 2001 From: Diego Heras Date: Mon, 2 Nov 2020 01:42:00 +0100 Subject: [PATCH] core: add custom cats in indexers with string categories. resolves #9746 (#10060) * When category ids in the indexer are "strings" we create a unique hash to make it compatible with Torznab * This PR also fix several issues related to custom cats --- src/Jackett.Common/Indexers/BaseIndexer.cs | 10 +- src/Jackett.Common/Indexers/SolidTorrents.cs | 24 +-- .../Models/TorznabCapabilitiesCategories.cs | 157 ++++++++---------- .../Common/Indexers/BaseWebIndexerTests.cs | 14 +- .../Common/Indexers/CardigannIndexerTests.cs | 1 + .../Common/Models/DTO/IndexerTests.cs | 7 +- .../TorznabCapabilitiesCategoriesTests.cs | 72 +++++--- .../Common/Models/TorznabCapabilitiesTests.cs | 8 +- .../TestHelpers/TestCategories.cs | 2 +- 9 files changed, 152 insertions(+), 143 deletions(-) diff --git a/src/Jackett.Common/Indexers/BaseIndexer.cs b/src/Jackett.Common/Indexers/BaseIndexer.cs index c83ab8451..02f8219e1 100644 --- a/src/Jackett.Common/Indexers/BaseIndexer.cs +++ b/src/Jackett.Common/Indexers/BaseIndexer.cs @@ -266,16 +266,8 @@ namespace Jackett.Common.Indexers if (query.Categories.Length == 0) return results; - // TODO: move this code to TorznabCapabilitiesCategories and use indexer tree instead of general // expand parent categories from the query - var expandedQueryCats = new List(); - foreach (var queryCategory in query.Categories) - { - expandedQueryCats.Add(queryCategory); - var parentCat = TorznabCatType.ParentCats.FirstOrDefault(c => c.ID == queryCategory); - if (parentCat != null) - expandedQueryCats.AddRange(parentCat.SubCategories.Select(c => c.ID)); - } + var expandedQueryCats = TorznabCaps.Categories.ExpandTorznabQueryCategories(query); var filteredResults = results.Where(result => result.Category?.Any() != true || diff --git a/src/Jackett.Common/Indexers/SolidTorrents.cs b/src/Jackett.Common/Indexers/SolidTorrents.cs index 170c43091..cf82f1e3b 100644 --- a/src/Jackett.Common/Indexers/SolidTorrents.cs +++ b/src/Jackett.Common/Indexers/SolidTorrents.cs @@ -69,18 +69,18 @@ namespace Jackett.Common.Indexers Language = "en-us"; Type = "public"; - AddCategoryMapping("Audio", TorznabCatType.Audio); - AddCategoryMapping("Video", TorznabCatType.Movies); - AddCategoryMapping("Image", TorznabCatType.OtherMisc); - AddCategoryMapping("Document", TorznabCatType.BooksComics); - AddCategoryMapping("eBook", TorznabCatType.BooksEBook); - AddCategoryMapping("Program", TorznabCatType.PC0day); - AddCategoryMapping("Android", TorznabCatType.PCMobileAndroid); - AddCategoryMapping("Archive", TorznabCatType.Other); - AddCategoryMapping("Diskimage", TorznabCatType.PCISO); - AddCategoryMapping("Sourcecode", TorznabCatType.MoviesOther); - AddCategoryMapping("Database", TorznabCatType.MoviesDVD); - AddCategoryMapping("Unknown", TorznabCatType.Other); + AddCategoryMapping("Audio", TorznabCatType.Audio, "Audio"); + AddCategoryMapping("Video", TorznabCatType.Movies, "Video"); + AddCategoryMapping("Image", TorznabCatType.OtherMisc, "Image"); + AddCategoryMapping("Document", TorznabCatType.BooksComics, "Document"); + AddCategoryMapping("eBook", TorznabCatType.BooksEBook, "eBook"); + AddCategoryMapping("Program", TorznabCatType.PC0day, "Program"); + AddCategoryMapping("Android", TorznabCatType.PCMobileAndroid, "Android"); + AddCategoryMapping("Archive", TorznabCatType.Other, "Archive"); + AddCategoryMapping("Diskimage", TorznabCatType.PCISO, "Diskimage"); + AddCategoryMapping("Sourcecode", TorznabCatType.MoviesOther, "Sourcecode"); + AddCategoryMapping("Database", TorznabCatType.MoviesDVD, "Database"); + AddCategoryMapping("Unknown", TorznabCatType.Other, "Unknown"); } public override async Task ApplyConfiguration(JToken configJson) diff --git a/src/Jackett.Common/Models/TorznabCapabilitiesCategories.cs b/src/Jackett.Common/Models/TorznabCapabilitiesCategories.cs index d2bd97e75..051be0894 100644 --- a/src/Jackett.Common/Models/TorznabCapabilitiesCategories.cs +++ b/src/Jackett.Common/Models/TorznabCapabilitiesCategories.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; +using System.Text; namespace Jackett.Common.Models { @@ -9,7 +11,9 @@ namespace Jackett.Common.Models private readonly List _categoryMapping = new List(); private readonly List _torznabCategoryTree = new List(); - public List GetTrackerCategories() => _categoryMapping.Select(x => x.TrackerCategory).ToList(); + public List GetTrackerCategories() => _categoryMapping + .Where(m => m.NewzNabCategory < 100000) + .Select(m => m.TrackerCategory).Distinct().ToList(); public List GetTorznabCategoryTree(bool sorted = false) { @@ -46,114 +50,57 @@ namespace Jackett.Common.Models public void AddCategoryMapping(string trackerCategory, TorznabCategory torznabCategory, string trackerCategoryDesc = null) { - // add torznab cat _categoryMapping.Add(new CategoryMapping(trackerCategory, trackerCategoryDesc, torznabCategory.ID)); AddTorznabCategoryTree(torznabCategory); - // TODO: fix this. it's only working for integer "trackerCategory" - // create custom cats (1:1 categories) - if (trackerCategoryDesc != null && trackerCategory != null) + if (trackerCategoryDesc == null) + return; + + // create custom cats (1:1 categories) if trackerCategoryDesc is defined + // - if trackerCategory is "integer" we use that number to generate custom category id + // - if trackerCategory is "string" we compute a hash to generate fixed integer id for the custom category + // the hash is not perfect but it should work in most cases. we can't use sequential numbers because + // categories are updated frequently and the id must be fixed to work in 3rd party apps + if (!int.TryParse(trackerCategory, out var trackerCategoryInt)) { - //TODO convert to int.TryParse() to avoid using throw as flow control - try - { - var trackerCategoryInt = int.Parse(trackerCategory); - var customCat = new TorznabCategory(trackerCategoryInt + 100000, trackerCategoryDesc); - AddTorznabCategoryTree(customCat); - } - catch (FormatException) - { - // trackerCategory is not an integer, continue - } + var hashed = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(trackerCategory)); + trackerCategoryInt = BitConverter.ToUInt16(hashed, 0); // id between 0 and 65535 < 100000 } + var customCat = new TorznabCategory(trackerCategoryInt + 100000, trackerCategoryDesc); + _categoryMapping.Add(new CategoryMapping(trackerCategory, trackerCategoryDesc, customCat.ID)); + AddTorznabCategoryTree(customCat); } public List MapTorznabCapsToTrackers(TorznabQuery query, bool mapChildrenCatsToParent = false) { - var result = new List(); - foreach (var cat in query.Categories) - { - // use 1:1 mapping to tracker categories for newznab categories >= 100000 - if (cat >= 100000) - { - result.Add((cat - 100000).ToString()); - continue; - } - - var queryCats = new List { cat }; - var newznabCat = TorznabCatType.AllCats.FirstOrDefault(c => c.ID == cat); - if (newznabCat != null) - { - queryCats.AddRange(newznabCat.SubCategories.Select(c => c.ID)); - } - - if (mapChildrenCatsToParent) - { - var parentNewznabCat = TorznabCatType.AllCats.FirstOrDefault(c => c.SubCategories.Contains(newznabCat)); - if (parentNewznabCat != null) - { - queryCats.Add(parentNewznabCat.ID); - } - } - - foreach (var mapping in _categoryMapping.Where(c => queryCats.Contains(c.NewzNabCategory))) - { - result.Add(mapping.TrackerCategory); - } - } - - return result.Distinct().ToList(); + var expandedQueryCats = ExpandTorznabQueryCategories(query, mapChildrenCatsToParent); + var result = _categoryMapping + .Where(c => expandedQueryCats.Contains(c.NewzNabCategory)) + .Select(mapping => mapping.TrackerCategory).Distinct().ToList(); + return result; } - public ICollection MapTrackerCatToNewznab(string input) + public ICollection MapTrackerCatToNewznab(string trackerCategory) { - if (input == null) + if (string.IsNullOrWhiteSpace(trackerCategory)) return new List(); - var cats = _categoryMapping - .Where(m => m.TrackerCategory != null && m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()) + .Where(m => + !string.IsNullOrWhiteSpace(m.TrackerCategory) && + string.Equals(m.TrackerCategory, trackerCategory, StringComparison.InvariantCultureIgnoreCase)) .Select(c => c.NewzNabCategory).ToList(); - - // 1:1 category mapping - try - { - var trackerCategoryInt = int.Parse(input); - cats.Add(trackerCategoryInt + 100000); - } - catch (FormatException) - { - // input is not an integer, continue - } - return cats; } - public ICollection MapTrackerCatDescToNewznab(string input) + public ICollection MapTrackerCatDescToNewznab(string trackerCategoryDesc) { - var cats = new List(); - if (null != input) - { - var mapping = _categoryMapping - .FirstOrDefault(m => m.TrackerCategoryDesc != null && m.TrackerCategoryDesc.ToLowerInvariant() == input.ToLowerInvariant()); - if (mapping != null) - { - cats.Add(mapping.NewzNabCategory); - - if (mapping.TrackerCategory != null) - { - // 1:1 category mapping - try - { - var trackerCategoryInt = int.Parse(mapping.TrackerCategory); - cats.Add(trackerCategoryInt + 100000); - } - catch (FormatException) - { - // mapping.TrackerCategory is not an integer, continue - } - } - } - } + if (string.IsNullOrWhiteSpace(trackerCategoryDesc)) + return new List(); + var cats = _categoryMapping + .Where(m => + !string.IsNullOrWhiteSpace(m.TrackerCategoryDesc) && + string.Equals(m.TrackerCategoryDesc, trackerCategoryDesc, StringComparison.InvariantCultureIgnoreCase)) + .Select(c => c.NewzNabCategory).ToList(); return cats; } @@ -174,6 +121,36 @@ namespace Jackett.Common.Models rhs.GetTorznabCategoryList().Where(x => x.ID < 100000).ToList().ForEach(AddTorznabCategoryTree); } + /// + /// If there are parent categories in TorznabQuery.Categories the children categories are added + /// + /// Search query + /// If enabled, children categories will add the parent category to the list + /// + public List ExpandTorznabQueryCategories(TorznabQuery query, bool mapChildrenCatsToParent = false) + { + var expandedQueryCats = new List(); + foreach (var queryCategory in query.Categories) + { + expandedQueryCats.Add(queryCategory); + if (queryCategory >= 100000) + continue; + var parentCat = _torznabCategoryTree.FirstOrDefault(c => c.ID == queryCategory); + if (parentCat != null) + // if it's parent cat we add all the children + expandedQueryCats.AddRange(parentCat.SubCategories.Select(c => c.ID)); + else if (mapChildrenCatsToParent) + { + // if it's child cat and mapChildrenCatsToParent is enabled we add the parent + var queryCategoryTorznab = new TorznabCategory(queryCategory, ""); + parentCat = _torznabCategoryTree.FirstOrDefault(c => c.Contains(queryCategoryTorznab)); + if (parentCat != null) + expandedQueryCats.Add(parentCat.ID); + } + } + return expandedQueryCats.Distinct().ToList(); + } + private void AddTorznabCategoryTree(TorznabCategory torznabCategory) { // build the category tree diff --git a/src/Jackett.Test/Common/Indexers/BaseWebIndexerTests.cs b/src/Jackett.Test/Common/Indexers/BaseWebIndexerTests.cs index 7a50685bf..716f58ed8 100644 --- a/src/Jackett.Test/Common/Indexers/BaseWebIndexerTests.cs +++ b/src/Jackett.Test/Common/Indexers/BaseWebIndexerTests.cs @@ -45,6 +45,7 @@ namespace Jackett.Test.Common.Indexers public void TestFilterResults() { var indexer = new TestWebIndexer(); + indexer.AddTestCategories(); var results = new List { new ReleaseInfo @@ -59,12 +60,16 @@ namespace Jackett.Test.Common.Indexers { Category = new List { TorznabCatType.BooksEBook.ID, 100004 } // torznab (mandatory) + custom cat }, + new ReleaseInfo + { + Category = new List { TorznabCatType.AudioLossless.ID } // unsupported category in this indexer + }, new ReleaseInfo() }; var query = new TorznabQuery(); // without categories var filteredResults = indexer._FilterResults(query, results).ToList(); - Assert.AreEqual(4, filteredResults.Count); + Assert.AreEqual(5, filteredResults.Count); query = new TorznabQuery // with child category { @@ -148,11 +153,9 @@ namespace Jackett.Test.Common.Indexers indexer.AddTestCategories(); // you can find more complex tests in TorznabCapabilitiesCategoriesTests.cs - // TODO: this is wrong, custom cat 100001 doesn't exists (it's not defined by us) var torznabCats = indexer._MapTrackerCatToNewznab("1").ToList(); - Assert.AreEqual(2, torznabCats.Count); + Assert.AreEqual(1, torznabCats.Count); Assert.AreEqual(2000, torznabCats[0]); - Assert.AreEqual(100001, torznabCats[1]); } [Test] @@ -163,8 +166,9 @@ namespace Jackett.Test.Common.Indexers // you can find more complex tests in TorznabCapabilitiesCategoriesTests.cs var torznabCats = indexer._MapTrackerCatDescToNewznab("Console/Wii_c").ToList(); - Assert.AreEqual(1, torznabCats.Count); + Assert.AreEqual(2, torznabCats.Count); Assert.AreEqual(1030, torznabCats[0]); + Assert.AreEqual(137107, torznabCats[1]); } } } diff --git a/src/Jackett.Test/Common/Indexers/CardigannIndexerTests.cs b/src/Jackett.Test/Common/Indexers/CardigannIndexerTests.cs index b45a890a5..2a2e20868 100644 --- a/src/Jackett.Test/Common/Indexers/CardigannIndexerTests.cs +++ b/src/Jackett.Test/Common/Indexers/CardigannIndexerTests.cs @@ -99,6 +99,7 @@ namespace Jackett.Test.Common.Indexers TorznabCatType.Books.CopyWithoutSubCategories(), TorznabCatType.Console.CopyWithoutSubCategories(), new TorznabCategory(100044, "Console/Xbox_c"), + new TorznabCategory(137107, "Console/Wii_c"), new TorznabCategory(100045, "Console/Xbox_c2") }; expected[0].SubCategories.Add(TorznabCatType.MoviesSD.CopyWithoutSubCategories()); diff --git a/src/Jackett.Test/Common/Models/DTO/IndexerTests.cs b/src/Jackett.Test/Common/Models/DTO/IndexerTests.cs index 52b08fbdd..c7b6aabb9 100644 --- a/src/Jackett.Test/Common/Models/DTO/IndexerTests.cs +++ b/src/Jackett.Test/Common/Models/DTO/IndexerTests.cs @@ -37,7 +37,7 @@ namespace Jackett.Test.Common.Models.DTO // test Jackett UI categories (internal JSON) var dto = new Indexer(indexer); var dtoCaps = dto.caps.ToList(); - Assert.AreEqual(9, dtoCaps.Count); + Assert.AreEqual(10, dtoCaps.Count); Assert.AreEqual("1000", dtoCaps[0].ID); Assert.AreEqual("1030", dtoCaps[1].ID); Assert.AreEqual("1040", dtoCaps[2].ID); @@ -45,8 +45,9 @@ namespace Jackett.Test.Common.Models.DTO Assert.AreEqual("2030", dtoCaps[4].ID); Assert.AreEqual("7000", dtoCaps[5].ID); Assert.AreEqual("7030", dtoCaps[6].ID); - Assert.AreEqual("100044", dtoCaps[7].ID); - Assert.AreEqual("100040", dtoCaps[8].ID); + Assert.AreEqual("137107", dtoCaps[7].ID); + Assert.AreEqual("100044", dtoCaps[8].ID); + Assert.AreEqual("100040", dtoCaps[9].ID); // movies categories enable potato search Assert.True(dto.potatoenabled); diff --git a/src/Jackett.Test/Common/Models/TorznabCapabilitiesCategoriesTests.cs b/src/Jackett.Test/Common/Models/TorznabCapabilitiesCategoriesTests.cs index 9707e88fd..545611bc7 100644 --- a/src/Jackett.Test/Common/Models/TorznabCapabilitiesCategoriesTests.cs +++ b/src/Jackett.Test/Common/Models/TorznabCapabilitiesCategoriesTests.cs @@ -40,6 +40,7 @@ namespace Jackett.Test.Common.Models TorznabCatType.Books.CopyWithoutSubCategories(), TorznabCatType.Console.CopyWithoutSubCategories(), new TorznabCategory(100044, "Console/Xbox_c"), + new TorznabCategory(137107, "Console/Wii_c"), new TorznabCategory(100040, "Console/Xbox_c2") }; expected[0].SubCategories.Add(TorznabCatType.MoviesSD.CopyWithoutSubCategories()); @@ -55,6 +56,7 @@ namespace Jackett.Test.Common.Models TorznabCatType.Console.CopyWithoutSubCategories(), TorznabCatType.Movies.CopyWithoutSubCategories(), TorznabCatType.Books.CopyWithoutSubCategories(), + new TorznabCategory(137107, "Console/Wii_c"), new TorznabCategory(100044, "Console/Xbox_c"), new TorznabCategory(100040, "Console/Xbox_c2") }; @@ -82,6 +84,7 @@ namespace Jackett.Test.Common.Models TorznabCatType.ConsoleXBox.CopyWithoutSubCategories(), TorznabCatType.ConsoleWii.CopyWithoutSubCategories(), new TorznabCategory(100044, "Console/Xbox_c"), + new TorznabCategory(137107, "Console/Wii_c"), new TorznabCategory(100040, "Console/Xbox_c2") }; TestCategories.CompareCategoryTrees(expected, cats); @@ -97,6 +100,7 @@ namespace Jackett.Test.Common.Models TorznabCatType.MoviesSD.CopyWithoutSubCategories(), TorznabCatType.Books.CopyWithoutSubCategories(), TorznabCatType.BooksComics.CopyWithoutSubCategories(), + new TorznabCategory(137107, "Console/Wii_c"), new TorznabCategory(100044, "Console/Xbox_c"), new TorznabCategory(100040, "Console/Xbox_c2") }; @@ -149,9 +153,7 @@ namespace Jackett.Test.Common.Models expected.Add(new TorznabCategory(100044, "Console/Xbox_c")); TestCategories.CompareCategoryTrees(expected, cats); - // TODO: we should add a way to add custom categories for string categories - // https://github.com/Sonarr/Sonarr/wiki/Implementing-a-Torznab-indexer#caps-endpoint - // add string category with description. it's converted into 1 category + // add string category with description => custom category. it's converted into 2 different categories // - Movies // - MoviesSD // - Books @@ -160,8 +162,10 @@ namespace Jackett.Test.Common.Models // - ConsoleXBox // + ConsoleWii // - Custom Cat "Console/Xbox_c" + // + Custom Cat "Console/Wii_c" tcc.AddCategoryMapping("con_wii", TorznabCatType.ConsoleWii, "Console/Wii_c"); expected[2].SubCategories.Add(TorznabCatType.ConsoleWii.CopyWithoutSubCategories()); + expected.Add(new TorznabCategory(137107, "Console/Wii_c")); TestCategories.CompareCategoryTrees(expected, cats); // add another int category with description that maps to ConsoleXbox (there are 2 tracker cats => 1 torznab cat) @@ -173,6 +177,7 @@ namespace Jackett.Test.Common.Models // - ConsoleXBox (this is not added again) // - ConsoleWii // - Custom Cat "Console/Xbox_c" + // - Custom Cat "Console/Wii_c" // + Custom Cat "Console/Xbox_c2" tcc.AddCategoryMapping("45", TorznabCatType.ConsoleXBox, "Console/Xbox_c2"); expected.Add(new TorznabCategory(100045, "Console/Xbox_c2")); @@ -210,7 +215,7 @@ namespace Jackett.Test.Common.Models Assert.AreEqual("1", trackerCats[0]); // Movies Assert.AreEqual("mov_sd", trackerCats[1]); // Movies SD - query = new TorznabQuery // duplicate category (1 toznab cat => 2 indexer cats) + query = new TorznabQuery // duplicate category (1 torznab cat => 2 indexer cats) { Categories = new [] { TorznabCatType.ConsoleXBox.ID } }; @@ -219,13 +224,21 @@ namespace Jackett.Test.Common.Models Assert.AreEqual("44", trackerCats[0]); Assert.AreEqual("40", trackerCats[1]); - query = new TorznabQuery // custom cat + query = new TorznabQuery // custom cat "integer" { - Categories = new [] { 100001 } // Movies + Categories = new [] { 100044 } // Console/Xbox_c }; trackerCats = tcc.MapTorznabCapsToTrackers(query); Assert.AreEqual(1, trackerCats.Count); - Assert.AreEqual("1", trackerCats[0]); // Movies + Assert.AreEqual("44", trackerCats[0]); // Console/Xbox_c + + query = new TorznabQuery // custom cat "string" + { + Categories = new [] { 137107 } // Console/Wii_c + }; + trackerCats = tcc.MapTorznabCapsToTrackers(query); + Assert.AreEqual(1, trackerCats.Count); + Assert.AreEqual("con_wii", trackerCats[0]); // Console/Wii_c query = new TorznabQuery // unknown category { @@ -233,6 +246,13 @@ namespace Jackett.Test.Common.Models }; trackerCats = tcc.MapTorznabCapsToTrackers(query); Assert.AreEqual(0, trackerCats.Count); + + query = new TorznabQuery // unknown custom cat + { + Categories = new [] { 100001 } + }; + trackerCats = tcc.MapTorznabCapsToTrackers(query); + Assert.AreEqual(0, trackerCats.Count); } [Test] @@ -241,17 +261,16 @@ namespace Jackett.Test.Common.Models // MapTrackerCatToNewznab: maps Tracker cat ID => Torznab cats var tcc = CreateTestDataset(); - // TODO: this is wrong, custom cat 100001 doesn't exists (it's not defined by us) - var torznabCats = tcc.MapTrackerCatToNewznab("1").ToList(); - Assert.AreEqual(2, torznabCats.Count); + var torznabCats = tcc.MapTrackerCatToNewznab("1").ToList(); // "integer" id without custom cat + Assert.AreEqual(1, torznabCats.Count); Assert.AreEqual(2000, torznabCats[0]); - Assert.AreEqual(100001, torznabCats[1]); - torznabCats = tcc.MapTrackerCatToNewznab("mov_sd").ToList(); + torznabCats = tcc.MapTrackerCatToNewznab("mov_sd").ToList(); // "string" id without custom cat Assert.AreEqual(1, torznabCats.Count); Assert.AreEqual(2030, torznabCats[0]); - torznabCats = tcc.MapTrackerCatToNewznab("44").ToList(); // 44 and 45 maps to ConsoleXbox but different custom cat + // "integer" id with custom cats. 44 and 40 maps to ConsoleXbox but different custom cat + torznabCats = tcc.MapTrackerCatToNewznab("44").ToList(); Assert.AreEqual(2, torznabCats.Count); Assert.AreEqual(1040, torznabCats[0]); Assert.AreEqual(100044, torznabCats[1]); @@ -260,9 +279,17 @@ namespace Jackett.Test.Common.Models Assert.AreEqual(1040, torznabCats[0]); Assert.AreEqual(100040, torznabCats[1]); - // TODO: this is wrong, we are returning cat 109999 which doesn't exist - //torznabCats = tcc.MapTrackerCatToNewznab("9999").ToList(); // unknown cat - //Assert.AreEqual(0, torznabCats.Count); + // "string" id with custom cats + torznabCats = tcc.MapTrackerCatToNewznab("con_wii").ToList(); + Assert.AreEqual(2, torznabCats.Count); + Assert.AreEqual(1030, torznabCats[0]); + Assert.AreEqual(137107, torznabCats[1]); + + torznabCats = tcc.MapTrackerCatToNewznab("9999").ToList(); // unknown cat + Assert.AreEqual(0, torznabCats.Count); + + torznabCats = tcc.MapTrackerCatToNewznab("con_unknown").ToList(); // unknown custom cat + Assert.AreEqual(0, torznabCats.Count); torznabCats = tcc.MapTrackerCatToNewznab(null).ToList(); // null Assert.AreEqual(0, torznabCats.Count); @@ -274,21 +301,24 @@ namespace Jackett.Test.Common.Models // MapTrackerCatDescToNewznab: maps Tracker cat Description => Torznab cats var tcc = CreateTestDataset(); - var torznabCats = tcc.MapTrackerCatDescToNewznab("Console/Xbox_c").ToList(); // Console/Xbox_c and Console/Xbox_c2 maps to ConsoleXbox but different custom cat + // "integer" id with custom cats + // Console/Xbox_c and Console/Xbox_c2 maps to ConsoleXbox but different custom cat + var torznabCats = tcc.MapTrackerCatDescToNewznab("Console/Xbox_c").ToList(); Assert.AreEqual(2, torznabCats.Count); Assert.AreEqual(1040, torznabCats[0]); Assert.AreEqual(100044, torznabCats[1]); - torznabCats = tcc.MapTrackerCatDescToNewznab("Console/Xbox_c2").ToList(); Assert.AreEqual(2, torznabCats.Count); Assert.AreEqual(1040, torznabCats[0]); Assert.AreEqual(100040, torznabCats[1]); + // "string" id with custom cats torznabCats = tcc.MapTrackerCatDescToNewznab("Console/Wii_c").ToList(); - Assert.AreEqual(1, torznabCats.Count); + Assert.AreEqual(2, torznabCats.Count); Assert.AreEqual(1030, torznabCats[0]); + Assert.AreEqual(137107, torznabCats[1]); - torznabCats = tcc.MapTrackerCatDescToNewznab("9999").ToList(); // unknown cat + torznabCats = tcc.MapTrackerCatDescToNewznab("Unknown/Cat").ToList(); // unknown cat Assert.AreEqual(0, torznabCats.Count); torznabCats = tcc.MapTrackerCatDescToNewznab(null).ToList(); // null @@ -306,6 +336,7 @@ namespace Jackett.Test.Common.Models Assert.True(tcc.SupportsCategories(new []{ 100040 })); // custom cat Assert.False(tcc.SupportsCategories(new []{ TorznabCatType.Movies3D.ID })); // not supported child cat Assert.False(tcc.SupportsCategories(new []{ 9999 })); // unknown cat + Assert.False(tcc.SupportsCategories(new []{ 100001 })); // unknown custom cat Assert.False(tcc.SupportsCategories(new int[]{})); // empty list Assert.False(tcc.SupportsCategories(null)); // null } @@ -338,6 +369,7 @@ namespace Jackett.Test.Common.Models TorznabCatType.Books.CopyWithoutSubCategories(), TorznabCatType.Console.CopyWithoutSubCategories(), new TorznabCategory(100044, "Console/Xbox_c"), + new TorznabCategory(137107, "Console/Wii_c"), new TorznabCategory(100040, "Console/Xbox_c2") }; expected[0].SubCategories.Add(TorznabCatType.MoviesSD.CopyWithoutSubCategories()); diff --git a/src/Jackett.Test/Common/Models/TorznabCapabilitiesTests.cs b/src/Jackett.Test/Common/Models/TorznabCapabilitiesTests.cs index 815fdc05e..63e6a4c69 100644 --- a/src/Jackett.Test/Common/Models/TorznabCapabilitiesTests.cs +++ b/src/Jackett.Test/Common/Models/TorznabCapabilitiesTests.cs @@ -442,17 +442,19 @@ namespace Jackett.Test.Common.Models // test Torznab caps (XML) => more in Common.Model.TorznabCapabilitiesTests var xDocument = torznabCaps.GetXDocument(); var xDocumentCategories = xDocument.Root?.Element("categories")?.Elements("category").ToList(); - Assert.AreEqual(5, xDocumentCategories?.Count); + Assert.AreEqual(6, xDocumentCategories?.Count); Assert.AreEqual("1000", xDocumentCategories?[0].Attribute("id")?.Value); Assert.AreEqual(2, xDocumentCategories?[0]?.Elements("subcat").ToList().Count); Assert.AreEqual("2000", xDocumentCategories?[1].Attribute("id")?.Value); Assert.AreEqual(1, xDocumentCategories?[1]?.Elements("subcat").ToList().Count); Assert.AreEqual("7000", xDocumentCategories?[2].Attribute("id")?.Value); Assert.AreEqual(1, xDocumentCategories?[2]?.Elements("subcat").ToList().Count); - Assert.AreEqual("100044", xDocumentCategories?[3].Attribute("id")?.Value); + Assert.AreEqual("137107", xDocumentCategories?[3].Attribute("id")?.Value); Assert.AreEqual(0, xDocumentCategories?[3]?.Elements("subcat").ToList().Count); - Assert.AreEqual("100040", xDocumentCategories?[4].Attribute("id")?.Value); + Assert.AreEqual("100044", xDocumentCategories?[4].Attribute("id")?.Value); Assert.AreEqual(0, xDocumentCategories?[4]?.Elements("subcat").ToList().Count); + Assert.AreEqual("100040", xDocumentCategories?[5].Attribute("id")?.Value); + Assert.AreEqual(0, xDocumentCategories?[5]?.Elements("subcat").ToList().Count); } [Test] diff --git a/src/Jackett.Test/TestHelpers/TestCategories.cs b/src/Jackett.Test/TestHelpers/TestCategories.cs index c4e3267a6..7be225ea4 100644 --- a/src/Jackett.Test/TestHelpers/TestCategories.cs +++ b/src/Jackett.Test/TestHelpers/TestCategories.cs @@ -10,7 +10,7 @@ namespace Jackett.Test.TestHelpers { // these categories are chosen to test all kind of category types: // - with integer and string id - // - with and without description + // - with and without description (with description we generate custom cats) // - parent and child categories // - custom categories are not added automatically but they are created from other categories automatically // - categories and subcategories are unsorted to test the sort when required