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
This commit is contained in:
Diego Heras
2020-11-02 01:42:00 +01:00
committed by GitHub
parent d2a7b59a8a
commit 1d7ea48505
9 changed files with 152 additions and 143 deletions

View File

@@ -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<int>();
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 ||

View File

@@ -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<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)

View File

@@ -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> _categoryMapping = new List<CategoryMapping>();
private readonly List<TorznabCategory> _torznabCategoryTree = new List<TorznabCategory>();
public List<string> GetTrackerCategories() => _categoryMapping.Select(x => x.TrackerCategory).ToList();
public List<string> GetTrackerCategories() => _categoryMapping
.Where(m => m.NewzNabCategory < 100000)
.Select(m => m.TrackerCategory).Distinct().ToList();
public List<TorznabCategory> 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<string> MapTorznabCapsToTrackers(TorznabQuery query, bool mapChildrenCatsToParent = false)
{
var result = new List<string>();
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<int> { 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<int> MapTrackerCatToNewznab(string input)
public ICollection<int> MapTrackerCatToNewznab(string trackerCategory)
{
if (input == null)
if (string.IsNullOrWhiteSpace(trackerCategory))
return new List<int>();
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<int> MapTrackerCatDescToNewznab(string input)
public ICollection<int> MapTrackerCatDescToNewznab(string trackerCategoryDesc)
{
var cats = new List<int>();
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<int>();
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);
}
/// <summary>
/// If there are parent categories in TorznabQuery.Categories the children categories are added
/// </summary>
/// <param name="query">Search query</param>
/// <param name="mapChildrenCatsToParent">If enabled, children categories will add the parent category to the list</param>
/// <returns></returns>
public List<int> ExpandTorznabQueryCategories(TorznabQuery query, bool mapChildrenCatsToParent = false)
{
var expandedQueryCats = new List<int>();
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

View File

@@ -45,6 +45,7 @@ namespace Jackett.Test.Common.Indexers
public void TestFilterResults()
{
var indexer = new TestWebIndexer();
indexer.AddTestCategories();
var results = new List<ReleaseInfo>
{
new ReleaseInfo
@@ -59,12 +60,16 @@ namespace Jackett.Test.Common.Indexers
{
Category = new List<int> { TorznabCatType.BooksEBook.ID, 100004 } // torznab (mandatory) + custom cat
},
new ReleaseInfo
{
Category = new List<int> { 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]);
}
}
}

View File

@@ -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());

View File

@@ -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);

View File

@@ -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());

View File

@@ -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]

View File

@@ -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