newpct: huge refactor. resolves #5618 resolves #7928 resolves #8193 (#8346)

This commit is contained in:
Diego Heras
2020-04-25 03:33:13 +02:00
committed by GitHub
parent 20471ba9d3
commit 22a35573ba

View File

@@ -57,20 +57,21 @@ namespace Jackett.Common.Indexers
public MatchEvaluator MatchEvaluator; public MatchEvaluator MatchEvaluator;
} }
private readonly char[] _wordSeparators = new char[] { ' ', '.', ',', ';', '(', ')', '[', ']', '-', '_' }; private readonly char[] _wordSeparators = { ' ', '.', ',', ';', '(', ')', '[', ']', '-', '_' };
private readonly int _wordNotFoundScore = 100000; private readonly int _wordNotFoundScore = 100000;
private readonly Regex _searchStringRegex = new Regex(@"(.+?)S0?(\d+)(E0?(\d+))?$", RegexOptions.IgnoreCase); private readonly Regex _searchStringRegex = new Regex(@"(.+?)S(\d{2})(E(\d{2}))?$", RegexOptions.IgnoreCase);
private readonly Regex _titleListRegex = new Regex(@"Serie( *Descargar)?(.+?)(Temporada(.+?)(\d+)(.+?))?Capitulos?(.+?)(\d+)((.+?)(\d+))?(.+?)-(.+?)Calidad(.*)", RegexOptions.IgnoreCase); // Defending Jacob Temporada 1 Capitulo 1
private readonly Regex _titleClassicRegex = new Regex(@"(\[[^\]]*\])?\[Cap\.(\d{1,2})(\d{2})([_-](\d{1,2})(\d{2}))?\]", RegexOptions.IgnoreCase); private readonly Regex _seriesChapterTitleRegex = new Regex(@"(.+)Temporada (\d+) Capitulo (\d+)", RegexOptions.IgnoreCase);
private readonly Regex _titleClassicTvQualityRegex = new Regex(@"\[([^\]]*HDTV[^\]]*)", RegexOptions.IgnoreCase); // Love 101 - Temporada 1 Capitulos 1 al 8
private readonly Regex _titleYearRegex = new Regex(@"[\[\(] *(\d{4}) *[\]\)]"); private readonly Regex _seriesChaptersTitleRegex = new Regex(@"(.+)Temporada (\d+) Capitulos (\d+) al (\d+)", RegexOptions.IgnoreCase);
private readonly DownloadMatcher[] _downloadMatchers = new DownloadMatcher[] private readonly Regex _titleYearRegex = new Regex(@" *[\[\(]? *((19|20)\d{2}) *[\]\)]? *$");
private readonly DownloadMatcher[] _downloadMatchers =
{ {
new DownloadMatcher() new DownloadMatcher
{ {
MatchRegex = new Regex("(/descargar-torrent/[^\"]+)\"") MatchRegex = new Regex("(/descargar-torrent/[^\"]+)\"")
}, },
new DownloadMatcher() new DownloadMatcher
{ {
MatchRegex = new Regex(@"nalt\s*=\s*'([^\/]*)"), MatchRegex = new Regex(@"nalt\s*=\s*'([^\/]*)"),
MatchEvaluator = m => string.Format("/download/{0}.torrent", m.Groups[1]) MatchEvaluator = m => string.Format("/download/{0}.torrent", m.Groups[1])
@@ -78,11 +79,9 @@ namespace Jackett.Common.Indexers
}; };
private readonly int _maxDailyPages = 4; private readonly int _maxDailyPages = 4;
private readonly int _maxMoviesPages = 10; private readonly int _maxMoviesPages = 6;
private readonly int[] _allTvCategories = (new TorznabCategory[] { TorznabCatType.TV }).Concat(TorznabCatType.TV.SubCategories).Select(c => c.ID).ToArray(); private readonly int[] _allTvCategories = (new [] {TorznabCatType.TV }).Concat(TorznabCatType.TV.SubCategories).Select(c => c.ID).ToArray();
private readonly int[] _allMoviesCategories = (new TorznabCategory[] { TorznabCatType.Movies }).Concat(TorznabCatType.Movies.SubCategories).Select(c => c.ID).ToArray(); private readonly int[] _allMoviesCategories = (new [] { TorznabCatType.Movies }).Concat(TorznabCatType.Movies.SubCategories).Select(c => c.ID).ToArray();
private readonly int _firstYearAllowed = 1885;
private readonly int _lastYearAllowedFromNow = 3;
private bool _includeVo; private bool _includeVo;
private bool _filterMovies; private bool _filterMovies;
@@ -116,47 +115,45 @@ namespace Jackett.Common.Indexers
public Newpct(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps) public Newpct(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
: base("Newpct", : base("Newpct",
description: "Newpct - Descargar peliculas, series y estrenos torrent gratis", description: "Newpct - Descargar peliculas, series y estrenos torrent gratis",
link: "https://descargas2020.org/", link: "https://descargas2020.org/",
caps: new TorznabCapabilities(TorznabCatType.TV, caps: new TorznabCapabilities(TorznabCatType.TV,
TorznabCatType.TVSD, TorznabCatType.TVSD,
TorznabCatType.TVHD, TorznabCatType.TVHD,
TorznabCatType.Movies), TorznabCatType.Movies),
configService: configService, configService: configService,
client: wc, client: wc,
logger: l, logger: l,
p: ps, p: ps,
configData: new ConfigurationData()) configData: new ConfigurationData())
{ {
Encoding = Encoding.GetEncoding("windows-1252"); Encoding = Encoding.GetEncoding("windows-1252");
Language = "es-es"; Language = "es-es";
Type = "public"; Type = "public";
var voItem = new BoolItem() { Name = "Include original versions in search results", Value = false }; var voItem = new BoolItem { Name = "Include original versions in search results", Value = false };
configData.AddDynamic("IncludeVo", voItem); configData.AddDynamic("IncludeVo", voItem);
var filterMoviesItem = new BoolItem() { Name = "Only full match movies", Value = true }; var filterMoviesItem = new BoolItem { Name = "Only full match movies", Value = true };
configData.AddDynamic("FilterMovies", filterMoviesItem); configData.AddDynamic("FilterMovies", filterMoviesItem);
var removeMovieAccentsItem = new BoolItem() { Name = "Remove accents in movie searches", Value = true }; var removeMovieAccentsItem = new BoolItem { Name = "Remove accents in movie searches", Value = true };
configData.AddDynamic("RemoveMovieAccents", removeMovieAccentsItem); configData.AddDynamic("RemoveMovieAccents", removeMovieAccentsItem);
var removeMovieYearItem = new BoolItem() { Name = "Remove year from movie results", Value = false }; var removeMovieYearItem = new BoolItem { Name = "Remove year from movie results", Value = false };
configData.AddDynamic("RemoveMovieYear", removeMovieYearItem); configData.AddDynamic("RemoveMovieYear", removeMovieYearItem);
} }
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson) public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{ {
configData.LoadValuesFromJson(configJson); LoadValuesFromJson(configJson);
// TODO: must be a simpler way to set the configured SiteLink var results = await PerformQuery(new TorznabQuery());
SiteLink = configData.SiteLink.Value; if (!results.Any())
throw new Exception("Found 0 releases!");
var releases = await PerformQuery(new TorznabQuery());
await ConfigureIfOK(string.Empty, releases.Any(), () =>
throw new Exception("Could not find releases from this URL"));
IsConfigured = true;
SaveConfig();
return IndexerConfigurationStatus.Completed; return IndexerConfigurationStatus.Completed;
} }
@@ -233,7 +230,6 @@ namespace Jackett.Common.Indexers
query.Categories.Any(c => _allMoviesCategories.Contains(c)); query.Categories.Any(c => _allMoviesCategories.Contains(c));
if (isMovieSearch) if (isMovieSearch)
releases.AddRange(await MovieSearch(query)); releases.AddRange(await MovieSearch(query));
} }
// Database lost on 2018/04/05, all previous torrents don't have download links // Database lost on 2018/04/05, all previous torrents don't have download links
@@ -299,7 +295,7 @@ namespace Jackett.Common.Indexers
}); });
} }
private async Task<IEnumerable<ReleaseInfo>> GetReleasesFromUri(Uri uri, string seriesName) private async Task<List<ReleaseInfo>> GetReleasesFromUri(Uri uri, string seriesName)
{ {
var releases = new List<ReleaseInfo>(); var releases = new List<ReleaseInfo>();
@@ -330,7 +326,7 @@ namespace Jackett.Common.Indexers
urlFormat => new Uri(SiteLink + string.Format(urlFormat, seriesLetter.ToLower()))); urlFormat => new Uri(SiteLink + string.Format(urlFormat, seriesLetter.ToLower())));
} }
private IEnumerable<NewpctRelease> ParseDailyContent(string content) private List<NewpctRelease> ParseDailyContent(string content)
{ {
var parser = new HtmlParser(); var parser = new HtmlParser();
var doc = parser.ParseDocument(content); var doc = parser.ParseDocument(content);
@@ -339,35 +335,31 @@ namespace Jackett.Common.Indexers
try try
{ {
var rows = doc.QuerySelectorAll(".content .info"); var rows = doc.QuerySelectorAll("ul.noticias-series > li");
foreach (var row in rows) foreach (var row in rows)
{ {
var anchor = row.QuerySelector("a"); var qDiv = row.QuerySelector("div.info");
var title = Regex.Replace(anchor.TextContent, @"\s+", " ").Trim(); var title = qDiv.QuerySelector("h2").TextContent.Trim();
var title2 = Regex.Replace(anchor.GetAttribute("title"), @"\s+", " ").Trim(); var detailsUrl = qDiv.QuerySelector("a").GetAttribute("href");
if (title2.Length >= title.Length)
title = title2;
var detailsUrl = anchor.GetAttribute("href"); // TODO: move this check to GetReleaseFromData to apply all releases
if (!_includeVo && _voUrls.Any(vo => detailsUrl.ToLower().Contains(vo.ToLower()))) if (!_includeVo && _voUrls.Any(vo => detailsUrl.ToLower().Contains(vo.ToLower())))
continue; continue;
var span = row.QuerySelector("span"); var span = qDiv.QuerySelector("span");
var quality = span.ChildNodes[0].TextContent.Trim(); var quality = span.ChildNodes[0].TextContent.Trim();
var releaseType = ReleaseTypeFromQuality(quality); var releaseType = ReleaseTypeFromQuality(quality);
var sizeText = span.ChildNodes[1].TextContent.Replace("Tama\u00F1o", "").Trim(); var sizeString = span.ChildNodes[1].TextContent.Replace("Tama\u00F1o", "").Trim();
var size = ReleaseInfo.GetBytes(sizeString);
var language = qDiv.QuerySelector("div > strong").TextContent.Trim();
var div = row.QuerySelector("div");
var language = div.ChildNodes[1].TextContent.Trim();
_dailyResultIdx++; _dailyResultIdx++;
var publishDate = _dailyNow - TimeSpan.FromMilliseconds(_dailyResultIdx);
var rSize = ReleaseInfo.GetBytes(sizeText); var banner = "https:" + row.QuerySelector("img").GetAttribute("src");
var rPublishDate = _dailyNow - TimeSpan.FromMilliseconds(_dailyResultIdx);
var rTitle = releaseType == ReleaseType.Tv
? $"Serie {title} - {language} Calidad [{quality}]"
: $"{title} [{quality}][{language}]";
var release = GetReleaseFromData(releaseType, rTitle, detailsUrl, quality, language, rSize, rPublishDate); var release = GetReleaseFromData(releaseType, title, detailsUrl, quality, language, size, publishDate, banner);
releases.Add(release); releases.Add(release);
} }
} }
@@ -381,28 +373,24 @@ namespace Jackett.Common.Indexers
private string ParseSeriesListContent(string content, string title) private string ParseSeriesListContent(string content, string title)
{ {
var titleLower = title.Trim().ToLower();
var parser = new HtmlParser(); var parser = new HtmlParser();
var doc = parser.ParseDocument(content); var doc = parser.ParseDocument(content);
try try
{ {
var rows = doc.QuerySelectorAll(".pelilist li a"); var rows = doc.QuerySelectorAll(".pelilist li a");
foreach (var anchor in rows) foreach (var row in rows)
{ if (titleLower.Equals(row.QuerySelector("h2").TextContent.Trim().ToLower()))
var h2 = anchor.QuerySelector("h2"); return row.GetAttribute("href");
if (h2.TextContent.Trim().ToLower() == title.Trim().ToLower())
return anchor.GetAttribute("href");
}
} }
catch (Exception ex) catch (Exception ex)
{ {
OnParseError(content, ex); OnParseError(content, ex);
} }
return null; return null;
} }
private IEnumerable<NewpctRelease> ParseEpisodesListContent(string content) private List<NewpctRelease> ParseEpisodesListContent(string content)
{ {
var parser = new HtmlParser(); var parser = new HtmlParser();
var doc = parser.ParseDocument(content); var doc = parser.ParseDocument(content);
@@ -411,20 +399,25 @@ namespace Jackett.Common.Indexers
try try
{ {
var rows = doc.QuerySelectorAll(".content .info"); var rows = doc.QuerySelectorAll("ul.buscar-list > li");
foreach (var row in rows) foreach (var row in rows)
{ {
var anchor = row.QuerySelector("a"); var qDiv = row.QuerySelector("div.info");
var title = anchor.TextContent.Replace("\t", "").Trim(); var qTitle = qDiv.QuerySelector("h2");
var detailsUrl = anchor.GetAttribute("href"); if (qTitle.Children.Length == 0)
continue; // we skip episodes with old title (those torrents can't be downloaded anyway)
var title = qTitle.Children[0].TextContent.Trim();
var language = qTitle.Children[1].TextContent.Trim();
var quality = qTitle.Children[2].TextContent.Replace("[", "").Replace("]", "").Trim();
var pubDateText = row.ChildNodes[3].TextContent.Trim(); var detailsUrl = qDiv.QuerySelector("a").GetAttribute("href");
var sizeText = row.ChildNodes[5].TextContent.Trim();
var size = ReleaseInfo.GetBytes(sizeText); var publishDate = DateTime.ParseExact(qDiv.ChildNodes[3].TextContent.Trim(), "dd-MM-yyyy", null);
var publishDate = DateTime.ParseExact(pubDateText, "dd-MM-yyyy", null); var size = ReleaseInfo.GetBytes(qDiv.ChildNodes[5].TextContent.Trim());
var release = GetReleaseFromData(ReleaseType.Tv, title, detailsUrl, null, null, size, publishDate); var banner = "https:" + row.QuerySelector("img").GetAttribute("src");
var release = GetReleaseFromData(ReleaseType.Tv, title, detailsUrl, quality, language, size, publishDate, banner);
releases.Add(release); releases.Add(release);
} }
} }
@@ -444,6 +437,16 @@ namespace Jackett.Common.Indexers
if (_removeMovieAccents) if (_removeMovieAccents)
searchStr = RemoveDiacritics(searchStr); searchStr = RemoveDiacritics(searchStr);
// we always remove the year in the search, even if _removeMovieYear is disabled
// and we save the year to add it in the title if required
var year = "";
var matchYear = _titleYearRegex.Match(searchStr);
if (matchYear.Success)
{
year = matchYear.Groups[1].Value;
searchStr = _titleYearRegex.Replace(searchStr, "");
}
var searchJsonUrl = SiteLink + _searchJsonUrl; var searchJsonUrl = SiteLink + _searchJsonUrl;
var pg = 1; var pg = 1;
@@ -451,15 +454,15 @@ namespace Jackett.Common.Indexers
{ {
var queryCollection = new Dictionary<string, string> var queryCollection = new Dictionary<string, string>
{ {
{"ordenar", "Lo+Ultimo"},
{"inon", "Descendente"},
{"s", searchStr}, {"s", searchStr},
{"pg", pg.ToString()} {"pg", pg.ToString()}
}; };
var results = await PostDataWithCookies(searchJsonUrl, queryCollection); var results = await PostDataWithCookies(searchJsonUrl, queryCollection);
if (results == null || string.IsNullOrEmpty(results.Content)) var items = ParseSearchJsonContent(results.Content, year);
break; if (!items.Any())
var items = ParseSearchJsonContent(results.Content);
if (items == null)
break; break;
releases.AddRange(items); releases.AddRange(items);
@@ -474,10 +477,11 @@ namespace Jackett.Common.Indexers
return releases; return releases;
} }
private IEnumerable<NewpctRelease> ParseSearchJsonContent(string content) private List<NewpctRelease> ParseSearchJsonContent(string content, string year)
{ {
var someFound = false;
var releases = new List<NewpctRelease>(); var releases = new List<NewpctRelease>();
if (string.IsNullOrWhiteSpace(content))
return releases;
try try
{ {
@@ -488,43 +492,54 @@ namespace Jackett.Common.Indexers
{ {
var item = jo["data"]["torrents"]["0"][i.ToString()]; var item = jo["data"]["torrents"]["0"][i.ToString()];
var url = item["guid"].ToString();
var title = item["torrentName"].ToString(); var title = item["torrentName"].ToString();
var pubDateText = item["torrentDateAdded"].ToString(); var detailsUrl = SiteLink + item["guid"];
var calidad = item["calidad"].ToString(); var quality = item["calidad"].ToString();
var sizeText = item["torrentSize"].ToString(); var size = ReleaseInfo.GetBytes(item["torrentSize"].ToString());
DateTime.TryParseExact(item["torrentDateAdded"].ToString(), "dd/MM/yyyy", null, DateTimeStyles.None, out var publishDate);
var banner = SiteLink + item["imagen"].ToString().TrimStart('/');
someFound = true; // we have another search for series
var titleLower = title.ToLower();
var isSeries = calidad != null && calidad.ToLower().Contains("hdtv"); var isSeries = quality != null && quality.ToLower().Contains("hdtv");
var isGame = title.ToLower().Contains("pcdvd"); var isGame = titleLower.Contains("pcdvd");
if (isSeries || isGame) if (isSeries || isGame)
continue; continue;
long size = 0; // at this point we assume that this is a movie release, we need to parse the title. examples:
try // Quien Es Harry Crumb (1989) [BluRay 720p X264 MKV][AC3 5.1 Castellano][www.descargas2020.ORG]
{ // Harry Potter y la orden del Fenix [4K UHDrip][2160p][HDR][AC3 5.1 Castellano DTS 5.1-Ingles+Subs][ES-EN]
size = ReleaseInfo.GetBytes(sizeText); // Harry Potter Y El Misterio Del Principe [DVDFULL][Spanish][2009]
} // Harry Potter 2 Y La Camara Secreta [DVD9 FULL][Spanish_English][Inc Subs.]
catch // The Avengers [DVDRIP][VOSE English_Subs. Español][2012]
{ // Harry Potter y las Reliquias de la Muerte Parte I.DVD5 [ DVDR] [AC3 5.1] [Multilenguaje] [2010]
} // Joker (2019) 720p [Web Screener 720p ][Castellano][www.descargas2020.ORG][www.pctnew.ORG]
DateTime.TryParseExact(pubDateText, "dd/MM/yyyy", null, DateTimeStyles.None, out var publishDate); title = title.Split('[')[0].Replace("720p", "").Trim();
var detailsUrl = SiteLink + url; // we have to guess the language
var language = "spanish";
if ((titleLower.Contains("castellano") && titleLower.Contains("ingles")) ||
(titleLower.Contains("spanish") && titleLower.Contains("english")) ||
titleLower.Contains("[es-en]"))
language += " dual";
else if (titleLower.Contains("multilenguaje"))
language += " multi";
else if (titleLower.Contains("vose"))
language = "english vose";
var release = GetReleaseFromData(ReleaseType.Movie, title, detailsUrl, calidad, null, size, publishDate); // we add the year if it's not in the title (could be removed later)
if (!string.IsNullOrWhiteSpace(year) && !_titleYearRegex.Match(title).Success)
title += " " + year;
var release = GetReleaseFromData(ReleaseType.Movie, title, detailsUrl, quality, language, size, publishDate, banner);
releases.Add(release); releases.Add(release);
} }
} }
catch (Exception) catch (Exception ex)
{ {
return null; OnParseError(content, ex);
} }
if (!someFound)
return null;
return releases; return releases;
} }
@@ -550,9 +565,7 @@ namespace Jackett.Common.Indexers
releaseWords[index] = null; releaseWords[index] = null;
} }
else else
{
release.Score += _wordNotFoundScore; release.Score += _wordNotFoundScore;
}
} }
} }
} }
@@ -563,7 +576,7 @@ namespace Jackett.Common.Indexers
: ReleaseType.Movie; : ReleaseType.Movie;
private NewpctRelease GetReleaseFromData(ReleaseType releaseType, string title, string detailsUrl, string quality, private NewpctRelease GetReleaseFromData(ReleaseType releaseType, string title, string detailsUrl, string quality,
string language, long size, DateTime publishDate) string language, long size, DateTime publishDate, string banner)
{ {
var result = new NewpctRelease var result = new NewpctRelease
{ {
@@ -571,44 +584,36 @@ namespace Jackett.Common.Indexers
}; };
//Sanitize //Sanitize
title = title.Replace("\t", "").Replace("\x2013", "-"); title = title.Replace("-", "").Replace("(", "").Replace(")", "");
title = Regex.Replace(title, @"\s+", " ");
var match = _titleListRegex.Match(title);
if (match.Success)
{
result.SeriesName = match.Groups[2].Value.Trim(' ', '-');
result.Season = int.Parse(match.Groups[5].Success ? match.Groups[5].Value.Trim() : "1");
result.Episode = int.Parse(match.Groups[8].Value.Trim().PadLeft(2, '0'));
result.EpisodeTo = match.Groups[11].Success ? (int?)int.Parse(match.Groups[11].Value.Trim()) : null;
var audioQuality = match.Groups[13].Value.Trim(' ', '[', ']');
if (string.IsNullOrEmpty(language))
language = audioQuality;
quality = match.Groups[14].Value.Trim(' ', '[', ']');
var seasonText = result.Season.ToString();
var episodeText = seasonText + result.Episode.ToString().PadLeft(2, '0');
var episodeToText = result.EpisodeTo.HasValue ? "_" + seasonText + result.EpisodeTo.ToString().PadLeft(2, '0') : "";
result.Title = string.Format("{0} - Temporada {1} [{2}][Cap.{3}{4}][{5}]",
result.SeriesName, seasonText, quality, episodeText, episodeToText, audioQuality);
}
else
{
var matchClassic = _titleClassicRegex.Match(title);
if (matchClassic.Success)
{
result.Season = matchClassic.Groups[2].Success ? (int?)int.Parse(matchClassic.Groups[2].Value) : null;
result.Episode = matchClassic.Groups[3].Success ? (int?)int.Parse(matchClassic.Groups[3].Value) : null;
result.EpisodeTo = matchClassic.Groups[6].Success ? (int?)int.Parse(matchClassic.Groups[6].Value) : null;
if (matchClassic.Groups[1].Success)
quality = matchClassic.Groups[1].Value;
}
result.Title = title;
}
if (releaseType == ReleaseType.Tv) if (releaseType == ReleaseType.Tv)
{ {
var match = _seriesChapterTitleRegex.Match(title);
if (match.Success)
{
result.SeriesName = match.Groups[1].Value.Trim();
result.Season = int.Parse(match.Groups[2].Value);
result.Episode = int.Parse(match.Groups[3].Value);
}
else
{
match = _seriesChaptersTitleRegex.Match(title);
if (match.Success)
{
result.SeriesName = match.Groups[1].Value.Trim();
result.Season = int.Parse(match.Groups[2].Value);
result.Episode = int.Parse(match.Groups[3].Value);
result.EpisodeTo = int.Parse(match.Groups[4].Value);
}
}
// tv series
var episodeText = "S" + result.Season.ToString().PadLeft(2, '0');
episodeText += "E" + result.Episode.ToString().PadLeft(2, '0');
episodeText += result.EpisodeTo.HasValue ? "-" + result.EpisodeTo.ToString().PadLeft(2, '0') : "";
result.Title = $"{result.SeriesName} {episodeText}";
if (!string.IsNullOrWhiteSpace(quality) && (quality.Contains("720") || quality.Contains("1080"))) if (!string.IsNullOrWhiteSpace(quality) && (quality.Contains("720") || quality.Contains("1080")))
result.Category = new List<int> { TorznabCatType.TVHD.ID }; result.Category = new List<int> { TorznabCatType.TVHD.ID };
else else
@@ -616,96 +621,60 @@ namespace Jackett.Common.Indexers
} }
else else
{ {
// movie
result.Title = title; result.Title = title;
result.Category = new List<int> { TorznabCatType.Movies.ID }; result.Category = new List<int> { TorznabCatType.Movies.ID };
} }
// TODO: add banner result.Title = FixedTitle(result, quality, language);
if (size > 0)
result.Size = size;
result.Link = new Uri(detailsUrl); result.Link = new Uri(detailsUrl);
result.Guid = result.Link; result.Guid = result.Link;
result.Comments = result.Link; result.Comments = result.Link;
result.PublishDate = publishDate; result.PublishDate = publishDate;
result.BannerUrl = new Uri(banner);
result.Seeders = 1; result.Seeders = 1;
result.Peers = 1; result.Peers = 2;
result.Size = size;
result.Title = FixedTitle(result, quality, language);
result.MinimumRatio = 1;
result.MinimumSeedTime = 172800; // 48 hours
result.DownloadVolumeFactor = 0; result.DownloadVolumeFactor = 0;
result.UploadVolumeFactor = 1; result.UploadVolumeFactor = 1;
result.MinimumRatio = 1;
result.MinimumSeedTime = 172800; // 48 hours
return result; return result;
} }
private string FixedTitle(NewpctRelease release, string quality, string language) private string FixedTitle(NewpctRelease release, string quality, string language)
{ {
if (string.IsNullOrEmpty(release.SeriesName))
{
release.SeriesName = release.Title;
if (release.NewpctReleaseType == ReleaseType.Tv && release.SeriesName.Contains("-"))
release.SeriesName = release.Title.Substring(0, release.SeriesName.IndexOf('-') - 1);
}
var titleParts = new List<string> var fixedTitle = release.Title;
{
release.SeriesName
};
if (release.NewpctReleaseType == ReleaseType.Tv) if (release.NewpctReleaseType == ReleaseType.Movie && _removeMovieYear)
{ fixedTitle = _titleYearRegex.Replace(fixedTitle, "");
if (string.IsNullOrEmpty(quality))
quality = "HDTV";
var seasonAndEpisode = "S" + release.Season.ToString().PadLeft(2, '0'); var fixedLanguage = language.ToLower()
seasonAndEpisode += "E" + release.Episode.ToString().PadLeft(2, '0'); .Replace("español", "spanish")
if (release.EpisodeTo != release.Episode && release.EpisodeTo != null && release.EpisodeTo != 0) .Replace("espanol", "spanish")
{ .Replace("castellano", "spanish")
seasonAndEpisode += "-" + release.EpisodeTo.ToString().PadLeft(2, '0'); .ToUpper();
}
titleParts.Add(seasonAndEpisode);
}
if (!string.IsNullOrEmpty(quality) && !release.SeriesName.Contains(quality)) var qualityLower = quality.ToLower();
{ var fixedQuality = quality.Replace("-", " ");
titleParts.Add(quality); if (qualityLower.Contains("full"))
} fixedQuality = qualityLower.Contains("4k") ? "BluRay 2160p COMPLETE" : "BluRay COMPLETE";
else if (qualityLower.Contains("remux"))
fixedQuality = qualityLower.Contains("4k") ? "BluRay 2160p REMUX" : "BluRay REMUX";
else if (qualityLower.Contains("4k")) // filter full and remux before 4k (there are 4k full and remux)
fixedQuality = "BluRay 2160p";
else if (qualityLower.Contains("microhd"))
fixedQuality = "BluRay 1080p";
else if (qualityLower.Contains("blurayrip"))
fixedQuality = "BluRay 720p";
else if (qualityLower.Contains("screener") || qualityLower.Contains("screeener")) // BluRay and DVD Screener are not supported in Radarr
fixedQuality = "TS Screener";
else if (qualityLower.Contains("htdv"))
fixedQuality = "HDTV";
if (!string.IsNullOrWhiteSpace(language) && !release.SeriesName.Contains(language)) return $"{fixedTitle} {fixedLanguage} {fixedQuality}";
{
titleParts.Add(language);
}
if (release.Title.ToLower().Contains("espa\u00F1ol") ||
release.Title.ToLower().Contains("espanol") ||
release.Title.ToLower().Contains("castellano") ||
release.Title.ToLower().EndsWith("espa"))
{
titleParts.Add("Spanish");
}
var result = string.Join(".", titleParts);
if (release.NewpctReleaseType == ReleaseType.Movie)
{
if (_removeMovieYear)
{
Match match = _titleYearRegex.Match(result);
if (match.Success)
{
int year = int.Parse(match.Groups[1].Value);
if (year >= _firstYearAllowed && year <= DateTime.Now.Year + _lastYearAllowedFromNow)
result = result.Replace(match.Groups[0].Value, "");
}
}
}
result = Regex.Replace(result, @"[\[\]]+", ".");
result = Regex.Replace(result, @"\.[ \.]*\.", ".");
return result;
} }
private string RemoveDiacritics(string text) private string RemoveDiacritics(string text)
@@ -723,9 +692,7 @@ namespace Jackett.Common.Indexers
{ {
var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c); var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
if (unicodeCategory != UnicodeCategory.NonSpacingMark) if (unicodeCategory != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c); stringBuilder.Append(c);
}
} }
return stringBuilder.ToString().Normalize(NormalizationForm.FormC); return stringBuilder.ToString().Normalize(NormalizationForm.FormC);