Add initial support for multiple categories and 1:1 category mapping

This commit is contained in:
kaso17 2017-02-21 13:07:54 +01:00
parent e75590876a
commit 87d3fd9443
27 changed files with 139 additions and 80 deletions

View File

@ -336,31 +336,31 @@ namespace Jackett.Indexers
{
category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
if (category == "TV Series")
release.Category = TorznabCatType.TVAnime.ID;
release.Category = new List<int> { TorznabCatType.TVAnime.ID };
// Ignore these categories as they'll cause hell with the matcher
// TV Special, OVA, ONA, DVD Special, BD Special
if (category == "Movie")
release.Category = TorznabCatType.Movies.ID;
release.Category = new List<int> { TorznabCatType.Movies.ID };
if (category == "Manga" || category == "Oneshot" || category == "Anthology" || category == "Manhwa" || category == "Manhua" || category == "Light Novel")
release.Category = TorznabCatType.BooksComics.ID;
release.Category = new List<int> { TorznabCatType.BooksComics.ID };
if (category == "Novel" || category == "Artbook")
release.Category = TorznabCatType.BooksComics.ID;
release.Category = new List<int> { TorznabCatType.BooksComics.ID };
if (category == "Game" || category == "Visual Novel")
{
var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
if (description.Contains(" PSP "))
release.Category = TorznabCatType.ConsolePSP.ID;
release.Category = new List<int> { TorznabCatType.ConsolePSP.ID };
if (description.Contains("PSX"))
release.Category = TorznabCatType.ConsoleOther.ID;
release.Category = new List<int> { TorznabCatType.ConsoleOther.ID };
if (description.Contains(" NES "))
release.Category = TorznabCatType.ConsoleOther.ID;
release.Category = new List<int> { TorznabCatType.ConsoleOther.ID };
if (description.Contains(" PC "))
release.Category = TorznabCatType.PCGames.ID;
release.Category = new List<int> { TorznabCatType.PCGames.ID };
}
}
@ -371,11 +371,11 @@ namespace Jackett.Indexers
{
var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
if (description.Contains(" Lossless "))
release.Category = TorznabCatType.AudioLossless.ID;
release.Category = new List<int> { TorznabCatType.AudioLossless.ID };
else if (description.Contains("MP3"))
release.Category = TorznabCatType.AudioMP3.ID;
release.Category = new List<int> { TorznabCatType.AudioMP3.ID };
else
release.Category = TorznabCatType.AudioOther.ID;
release.Category = new List<int> { TorznabCatType.AudioOther.ID };
}
}
@ -450,7 +450,7 @@ namespace Jackett.Indexers
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
if (release.Category != 0)
if (release.Category != null)
releases.Add(release);
}
}

View File

@ -219,7 +219,7 @@ namespace Jackett.Indexers
var SearchResultDocument = SearchResultParser.Parse(results.Content);
var Rows = SearchResultDocument.QuerySelectorAll(RowsSelector);
int GroupCategory = 0;
ICollection<int> GroupCategory = null;
string GroupTitle = null;
string GroupYearStr = null;
Nullable<DateTime> GroupPublishDate = null;
@ -230,7 +230,7 @@ namespace Jackett.Indexers
{
var qDetailsLink = Row.QuerySelector("a[href^=\"torrents.php?id=\"]");
string Title = qDetailsLink.TextContent;
int Category = 0;
ICollection<int> Category = null;
string YearStr = null;
Nullable<DateTime> YearPublishDate = null;

View File

@ -120,30 +120,55 @@ namespace Jackett.Indexers
return new Uri(downloadUrlBase + link.ToString(), UriKind.RelativeOrAbsolute);
}
protected int MapTrackerCatToNewznab(string input)
protected ICollection<int> MapTrackerCatToNewznab(string input)
{
var cats = new List<int>();
if (null != input)
{
var mapping = categoryMapping.Where(m => m.TrackerCategory != null && m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
if (mapping != null)
{
return mapping.NewzNabCategory;
cats.Add(mapping.NewzNabCategory);
}
// 1:1 category mapping
try
{
var trackerCategoryInt = int.Parse(input);
cats.Add(trackerCategoryInt + 100000);
}
catch (FormatException)
{
// input is not an integer, continue
}
}
return 0;
return cats;
}
protected int MapTrackerCatDescToNewznab(string input)
protected ICollection<int> MapTrackerCatDescToNewznab(string input)
{
var cats = new List<int>();
if (null != input)
{
var mapping = categoryMapping.Where(m => m.TrackerCategoryDesc != null && m.TrackerCategoryDesc.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
if (mapping != null)
{
return mapping.NewzNabCategory;
cats.Add(mapping.NewzNabCategory);
// 1:1 category mapping
try
{
var trackerCategoryInt = int.Parse(mapping.TrackerCategory);
cats.Add(trackerCategoryInt + 100000);
}
catch (FormatException)
{
// mapping.TrackerCategory is not an integer, continue
}
}
}
return 0;
return cats;
}
public static string GetIndexerID(Type type)
@ -525,7 +550,7 @@ namespace Jackett.Indexers
{
foreach (var result in results)
{
if (query.Categories.Length == 0 || query.Categories.Contains(result.Category) || result.Category == 0 || TorznabCatType.QueryContainsParentCategory(query.Categories, result.Category))
if (query.Categories.Length == 0 || result.Category == null || result.Category.Count() == 0 || query.Categories.Intersect(result.Category).Any() || TorznabCatType.QueryContainsParentCategory(query.Categories, result.Category))
{
yield return result;
}
@ -546,6 +571,22 @@ namespace Jackett.Indexers
if (TorznabCatType.Movies.Contains(newznabCategory))
TorznabCaps.MovieSearchAvailable = true;
}
// add 1:1 categories
if (trackerCategoryDesc != null && trackerCategory != null)
{
try
{
var trackerCategoryInt = int.Parse(trackerCategory);
var CustomCat = new TorznabCategory(trackerCategoryInt + 100000, trackerCategoryDesc);
if (!TorznabCaps.Categories.Contains(CustomCat))
TorznabCaps.Categories.Add(CustomCat);
}
catch (FormatException)
{
// trackerCategory is not an integer, continue
}
}
}
protected void AddCategoryMapping(int trackerCategory, TorznabCategory newznabCategory, string trackerCategoryDesc = null)
@ -566,6 +607,13 @@ namespace Jackett.Indexers
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)

View File

@ -106,7 +106,7 @@ namespace Jackett.Indexers
var item = new ReleaseInfo();
if (!string.IsNullOrEmpty(btnResult.SeriesBanner))
item.BannerUrl = new Uri(btnResult.SeriesBanner);
item.Category = TorznabCatType.TV.ID;
item.Category = new List<int> { TorznabCatType.TV.ID };
item.Comments = new Uri($"https://broadcasthe.net/torrents.php?id={btnResult.GroupID}&torrentid={btnResult.TorrentID}");
item.Description = btnResult.ReleaseName;
item.Guid = new Uri(btnResult.DownloadURL);

View File

@ -223,13 +223,13 @@ namespace Jackett.Indexers
? seriesCatsDanish
: seriesCatsDanish.Concat(seriesCatsIntl);
if (moviesCats.Contains(catNo))
release.Category = TorznabCatType.Movies.ID;
release.Category = new List<int> { TorznabCatType.Movies.ID };
else if (seriesCats.Contains(catNo))
release.Category = TorznabCatType.TV.ID;
release.Category = new List<int> { TorznabCatType.TV.ID };
else if (catNo == 12)
release.Category = TorznabCatType.BooksEbook.ID;
release.Category = new List<int> { TorznabCatType.BooksEbook.ID };
else if (catNo == 6)
release.Category = TorznabCatType.AudioAudiobook.ID;
release.Category = new List<int> { TorznabCatType.AudioAudiobook.ID };
else
continue;

View File

@ -131,14 +131,14 @@ namespace Jackett.Indexers
release.Title = qLink.Text().Trim();
release.Description = rowB.ChildElements.ElementAt(0).Cq().Text();
if (release.Category == TorznabCatType.Audio.ID)
if (release.Category != null && release.Category.Contains(TorznabCatType.Audio.ID))
{
if (release.Description.Contains("Lossless"))
release.Category = TorznabCatType.AudioLossless.ID;
release.Category = new List<int> { TorznabCatType.AudioLossless.ID };
else if (release.Description.Contains("MP3"))
release.Category = TorznabCatType.AudioMP3.ID;
release.Category = new List<int> { TorznabCatType.AudioMP3.ID };
else
release.Category = TorznabCatType.AudioOther.ID;
release.Category = new List<int> { TorznabCatType.AudioOther.ID };
}
release.Comments = new Uri(SiteLink + qLink.Attr("href"));

View File

@ -169,7 +169,7 @@ namespace Jackett.Indexers
release.UploadVolumeFactor = 1;
// Skip Romanian releases
if (release.Category == TorznabCatType.MoviesForeign.ID && !configData.IncludeRomanianReleases.Value)
if (release.Category.Contains(TorznabCatType.MoviesForeign.ID) && !configData.IncludeRomanianReleases.Value)
continue;
releases.Add(release);

View File

@ -114,7 +114,7 @@ namespace Jackett.Indexers
release.Guid = new Uri(SiteLink + qLink.Attr("href").TrimStart('/'));
release.Comments = release.Guid;
release.Link = new Uri(SiteLink + qRow.Find("td.table_links > a").First().Attr("href").TrimStart('/'));
release.Category = TvCategoryParser.ParseTvShowQuality(release.Title);
release.Category = new List<int> { TvCategoryParser.ParseTvShowQuality(release.Title) };
release.Seeders = ParseUtil.CoerceInt(qRow.Find("td.table_seeders").Text().Trim());
release.Peers = ParseUtil.CoerceInt(qRow.Find("td.table_leechers").Text().Trim()) + release.Seeders;

View File

@ -99,7 +99,7 @@ namespace Jackett.Indexers
release.MinimumRatio = 0.5;
release.MinimumSeedTime = 0;
release.Title = row.name;
release.Category = TorznabCatType.Audio.ID;
release.Category = new List<int> { TorznabCatType.Audio.ID };
release.Size = row.size;
release.Seeders = row.seeders;
release.Peers = row.leechers + release.Seeders;
@ -125,7 +125,7 @@ namespace Jackett.Indexers
if ((int)row.flac != 0)
{
tags.Add("FLAC");
release.Category = TorznabCatType.AudioLossless.ID;
release.Category = new List<int> { TorznabCatType.AudioLossless.ID };
}
if (tags.Count > 0)

View File

@ -71,7 +71,7 @@ namespace Jackett.Indexers
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var isTv = TorznabCatType.QueryContainsParentCategory(query.Categories, TorznabCatType.TV.ID);
var isTv = TorznabCatType.QueryContainsParentCategory(query.Categories, new List<int> { TorznabCatType.TV.ID });
var releases = new List<ReleaseInfo>();
var searchQuery = query.GetQueryString();
@ -229,7 +229,7 @@ namespace Jackett.Indexers
{
Title = title,
Description = title,
Category = category, // Who seasons movies right
Category = new List<int> { category }, // Who seasons movies right
Link = new Uri(DownloadUrl + torrentId),
PublishDate = publishDate,
Seeders = seeders,

View File

@ -138,7 +138,7 @@ namespace Jackett.Indexers
SearchUrl, HttpUtility.UrlEncode((string)torrent["Id"]), HttpUtility.UrlEncode(AuthKey), HttpUtility.UrlEncode(configData.Passkey.Value)));
release.MinimumRatio = 1;
release.MinimumSeedTime = 345600;
release.Category = 2000;
release.Category = new List<int> { 2000 };
bool golden, scene, check;
bool.TryParse((string)torrent["GoldenPopcorn"], out golden);

View File

@ -181,7 +181,7 @@ namespace Jackett.Indexers
var Leechers = Row.QuerySelector("td:nth-child(8)");
release.Title = GroupTitle + " " + title.TextContent;
release.Category = TorznabCatType.MoviesHD.ID;
release.Category = new List<int> { TorznabCatType.MoviesHD.ID };
release.Link = new Uri(SiteLink + link.GetAttribute("href"));
release.Comments = new Uri(SiteLink + title.GetAttribute("href"));
release.Guid = release.Link;

View File

@ -312,7 +312,7 @@ namespace Jackett.Indexers
release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(10).InnerText) + release.Seeders;
var cat = row.ChildElements.ElementAt(0).ChildElements.ElementAt(0).GetAttribute("href").Replace("browse.php?", string.Empty);
release.Category = MapTrackerResultCatToNewznab(cat);
release.Category = MapTrackerCatToNewznab(cat);
var files = qRow.Find("td:nth-child(4)").Text();
release.Files = ParseUtil.CoerceInt(files);
@ -332,19 +332,5 @@ namespace Jackett.Indexers
}
return releases;
}
protected int MapTrackerResultCatToNewznab(string input)
{
if (null != input)
{
input = input.ToLowerInvariant();
var mapping = resultMapping.Where(m => m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
if (mapping != null)
{
return mapping.NewzNabCategory;
}
}
return 0;
}
}
}

View File

@ -285,8 +285,8 @@ namespace Jackett.Indexers
};
// if unknown category, set to "other"
if (release.Category == 0)
release.Category = 7000;
if (release.Category.Count() == 0)
release.Category.Add(7000);
release.Peers += release.Seeders;
releases.Add(release);

View File

@ -209,11 +209,11 @@ namespace Jackett.Indexers
{
if (release.Title.Contains("1080p") || release.Title.Contains("720p"))
{
release.Category = TorznabCatType.TVHD.ID;
release.Category = new List<int> { TorznabCatType.TVHD.ID };
}
else
{
release.Category = TorznabCatType.TVSD.ID;
release.Category = new List<int> { TorznabCatType.TVSD.ID };
}
}

View File

@ -190,8 +190,8 @@ namespace Jackett.Indexers
};
// If its not apps or audio we can only mark as general TV
if (release.Category == 0)
release.Category = 5030;
if (release.Category.Count() == 0)
release.Category.Add(5030);
release.Peers += release.Seeders;
releases.Add(release);
@ -256,8 +256,8 @@ namespace Jackett.Indexers
release.Category = MapTrackerCatToNewznab(cat);
// If its not apps or audio we can only mark as general TV
if (release.Category == 0)
release.Category = 5030;
if (release.Category.Count() == 0)
release.Category.Add(5030);
var grabs = qRow.Find("td:nth-child(6)").Text();
release.Grabs = ParseUtil.CoerceInt(grabs);

View File

@ -121,7 +121,7 @@ namespace Jackett.Indexers
release.Description = DescStr.TextContent.Trim();
release.Title = qDetailsLink.TextContent + " " + release.Description;
release.PublishDate = DateTimeUtil.FromTimeAgo(Added.TextContent);
release.Category = TvCategoryParser.ParseTvShowQuality(release.Description);
release.Category = new List<int> { TvCategoryParser.ParseTvShowQuality(release.Description) };
release.Link = new Uri(SiteLink + DLLink);
release.Comments = new Uri(SiteLink + qDetailsLink.GetAttribute("href"));

View File

@ -197,7 +197,7 @@ namespace Jackett.Indexers
release.Peers = peers;
release.MinimumRatio = 1;
release.MinimumSeedTime = 345600;
release.Category = 2000;
release.Category = new List<int> { 2000 };
release.Comments = movieReleasesLink;
if (imdb_id > 0) {
release.Imdb = imdb_id;

View File

@ -169,13 +169,13 @@ namespace Jackett.Indexers
release.Description = release.Description.Replace("\n", "<br>");
if (format.Contains("MP3"))
release.Category = TorznabCatType.AudioMP3.ID;
release.Category = new List<int> { TorznabCatType.AudioMP3.ID };
else if (format.Contains("AAC"))
release.Category = TorznabCatType.AudioOther.ID;
release.Category = new List<int> { TorznabCatType.AudioOther.ID };
else if (format.Contains("Lossless"))
release.Category = TorznabCatType.AudioLossless.ID;
release.Category = new List<int> { TorznabCatType.AudioLossless.ID };
else
release.Category = TorznabCatType.AudioOther.ID;
release.Category = new List<int> { TorznabCatType.AudioOther.ID };
var lastAction = Row.QuerySelector("td:nth-child(9) > span").FirstChild.NodeValue;
release.PublishDate = DateTimeUtil.FromUnknown(lastAction, "UK");

View File

@ -133,7 +133,7 @@ namespace Jackett.Indexers
release.Guid = new Uri(SiteLink + row.QuerySelector("a[data-src]").GetAttribute("href"));
release.Comments = release.Guid;
release.Link = new Uri(SiteLink + row.QuerySelector("a[href*='action=download']").GetAttribute("href"));
release.Category = TvCategoryParser.ParseTvShowQuality(release.Title);
release.Category = new List<int> { TvCategoryParser.ParseTvShowQuality(release.Title) };
var timeAnchor = row.QuerySelector("span[class='time']");
release.PublishDate = DateTime.ParseExact(timeAnchor.GetAttribute("title"), "MMM dd yyyy, HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);

View File

@ -290,8 +290,8 @@ namespace Jackett.Indexers
release.Category = MapTrackerCatToNewznab(cat);
// If its not apps or audio we can only mark as general TV
if (release.Category == 0)
release.Category = 5030;
if (release.Category != null)
release.Category = new List<int> { 5030 };
var grabs = qRow.Find("td:nth-child(6)").Text();
release.Grabs = ParseUtil.CoerceInt(grabs);

View File

@ -104,7 +104,15 @@ namespace Jackett
Mapper.CreateMap<ReleaseInfo, TrackerCacheResult>().AfterMap((r, t) =>
{
t.CategoryDesc = TorznabCatType.GetCatDesc(r.Category);
if (r.Category != null)
{
var CategoryDesc = string.Join(", ", r.Category.Select(x => TorznabCatType.GetCatDesc(x)).Where(x => !string.IsNullOrEmpty(x)));
t.CategoryDesc = CategoryDesc;
}
else
{
t.CategoryDesc = "";
}
});
}
}

View File

@ -17,7 +17,7 @@ namespace Jackett.Models
public Uri Link { get; set; }
public Uri Comments { get; set; }
public DateTime PublishDate { get; set; }
public int Category { get; set; }
public ICollection<int> Category { get; set; }
public long? Size { get; set; }
public long? Files { get; set; }
public long? Grabs { get; set; }

View File

@ -74,7 +74,7 @@ namespace Jackett.Models
r.Grabs == null ? null : new XElement("grabs", r.Grabs),
new XElement("description", r.Description),
new XElement("link", r.Link ?? r.MagnetUri),
r.Category == 0 ? null : new XElement("category", r.Category),
r.Category == null ? null : from c in r.Category select new XElement("category", c),
new XElement(
"enclosure",
new XAttribute("url", r.Link ?? r.MagnetUri),

View File

@ -69,7 +69,7 @@ namespace Jackett.Models
public JArray CapsToJson()
{
var jArray = new JArray();
foreach (var cat in Categories.GroupBy(p => p.ID).Select(g => g.First()).OrderBy(c=>c.ID))
foreach (var cat in Categories.GroupBy(p => p.ID).Select(g => g.First()).OrderBy(c=> c.ID < 100000 ? "z"+c.ID.ToString() : c.Name))
{
jArray.Add(cat.ToJson());
}
@ -96,7 +96,7 @@ namespace Jackett.Models
)
),
new XElement("categories",
from c in Categories
from c in Categories.OrderBy(x => x.ID < 100000 ? "z" + x.ID.ToString() : x.Name)
select new XElement("category",
new XAttribute("id", c.ID),
new XAttribute("name", c.Name),

View File

@ -1,16 +1,20 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
namespace Jackett.Models
{
public static partial class TorznabCatType
{
public static bool QueryContainsParentCategory(int[] queryCats, int releaseCat)
public static bool QueryContainsParentCategory(int[] queryCats, ICollection<int> releaseCats)
{
var cat = AllCats.FirstOrDefault(c => c.ID == releaseCat);
if (cat != null && queryCats != null)
foreach (var releaseCat in releaseCats)
{
return cat.SubCategories.Any(c => queryCats.Contains(c.ID));
var cat = AllCats.FirstOrDefault(c => c.ID == releaseCat);
if (cat != null && queryCats != null)
{
return cat.SubCategories.Any(c => queryCats.Contains(c.ID));
}
}
return false;

View File

@ -43,6 +43,19 @@ namespace Jackett.Models
t["ID"] = ID;
t["Name"] = Name;
return t;
}
public override bool Equals(Object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
return ID == ((TorznabCategory)obj).ID;
}
public override int GetHashCode()
{
return ID;
}
}
}