private string FixedTitle(NewpctRelease release, string quality) { if (String.IsNullOrEmpty(release.SerieName)) { release.SerieName = release.Title; if (release.Title.Contains("-")) { release.SerieName = release.Title.Substring(0, release.Title.IndexOf('-') - 1); } } if (String.IsNullOrEmpty(quality)) { quality = "HDTV"; } var seasonAndEpisode = "S" + release.Season.ToString().PadLeft(2, '0'); seasonAndEpisode += "E" + release.Episode.ToString().PadLeft(2, '0'); if (release.EpisodeTo != release.Episode && release.EpisodeTo != null && release.EpisodeTo != 0) { seasonAndEpisode += "-" + release.EpisodeTo.ToString().PadLeft(2, '0'); } var titleParts = new List <string>(); titleParts.Add(release.SerieName); titleParts.Add(seasonAndEpisode); titleParts.Add(quality.Replace("[", "").Replace("]", "")); if (release.Title.ToLower().Contains("esp") || release.Title.ToLower().Contains("cast")) { titleParts.Add("Spanish"); } return(String.Join(".", titleParts)); }
private IEnumerable <NewpctRelease> ParseEpisodesListContent(string content) { var SearchResultParser = new HtmlParser(); var doc = SearchResultParser.Parse(content); List <NewpctRelease> releases = new List <NewpctRelease>(); try { var rows = doc.QuerySelectorAll(".content .info"); foreach (var row in rows) { var anchor = row.QuerySelector("a"); var title = anchor.TextContent.Replace("\t", "").Trim(); var detailsUrl = anchor.GetAttribute("href"); var span = row.QuerySelector("span"); var pubDateText = row.ChildNodes[3].TextContent.Trim(); var sizeText = row.ChildNodes[5].TextContent.Trim(); long size = ReleaseInfo.GetBytes(sizeText); DateTime publishDate = DateTime.ParseExact(pubDateText, "dd-MM-yyyy", null); NewpctRelease newpctRelease = GetReleaseFromData(ReleaseType.TV, title, detailsUrl, null, null, size, publishDate); releases.Add(newpctRelease); } } catch (Exception ex) { OnParseError(content, ex); } return(releases); }
private async Task <IEnumerable <ReleaseInfo> > PerformQuery(Uri siteLink, TorznabQuery query, int attempts) { var releases = new List <ReleaseInfo>(); _includeVo = ((BoolItem)configData.GetDynamic("IncludeVo")).Value; _filterMovies = ((BoolItem)configData.GetDynamic("FilterMovies")).Value; _dailyNow = DateTime.Now; _dailyResultIdx = 0; bool rssMode = string.IsNullOrEmpty(query.SanitizedSearchTerm); if (rssMode) { int pg = 1; while (pg <= _maxDailyPages) { Uri url = new Uri(siteLink, string.Format(_dailyUrl, pg)); var results = await RequestStringWithCookies(url.AbsoluteUri); var items = ParseDailyContent(results.Content); if (items == null || !items.Any()) { break; } releases.AddRange(items); //Check if we need to go to next page bool recentFound = _mostRecentRelease != null && items.Any(r => r.Title == _mostRecentRelease.Title && r.Link.AbsoluteUri == _mostRecentRelease.Link.AbsoluteUri); if (pg == 1) { _mostRecentRelease = (NewpctRelease)items.First().Clone(); } if (recentFound) { break; } pg++; } } else { bool isTvSearch = query.Categories == null || query.Categories.Length == 0 || query.Categories.Any(c => _allTvCategories.Contains(c)); if (isTvSearch) { releases.AddRange(await TvSearch(siteLink, query)); } bool isMovieSearch = query.Categories == null || query.Categories.Length == 0 || query.Categories.Any(c => _allMoviesCategories.Contains(c)); if (isMovieSearch) { releases.AddRange(await MovieSearch(siteLink, query)); } } return(releases); }
private string FixedTitle(NewpctRelease release, string quality, string language) { var fixedLanguage = language.ToLower() .Replace("español", "spanish") .Replace("espanol", "spanish") .Replace("castellano", "spanish") .ToUpper(); var qualityLower = quality.ToLower(); var fixedQuality = quality.Replace("-", " "); if (qualityLower.Contains("full")) { fixedQuality = qualityLower.Contains("4k") ? "BluRay 2160p COMPLETE x265" : "BluRay COMPLETE"; } else if (qualityLower.Contains("remux")) { fixedQuality = qualityLower.Contains("4k") ? "BluRay 2160p REMUX x265" : "BluRay REMUX"; } else if (qualityLower.Contains("4k")) // filter full and remux before 4k (there are 4k full and remux) { fixedQuality = "BluRay 2160p x265"; } else if (qualityLower.Contains("microhd")) { fixedQuality = qualityLower.Contains("720") ? "BluRay 720p MicroHD" : "BluRay 1080p MicroHD"; } else if (qualityLower.Contains("blurayrip")) { fixedQuality = "BluRay 720p"; } else if (qualityLower.Contains("dvdrip")) { fixedQuality = "DVDRip"; } else if (qualityLower.Contains("htdv")) { fixedQuality = "HDTV"; } // BluRay and DVD Screener are not supported in Radarr else if (qualityLower.Contains("screener") || qualityLower.Contains("screeener")) { if (qualityLower.Contains("720p") || qualityLower.Contains("dvd")) { fixedQuality = "Screener 720p"; } else if (qualityLower.Contains("bluray")) // there are bluray with 720p (condition after 720p) { fixedQuality = "Screener 1080p"; } else { fixedQuality = "TS Screener"; } } return($"{release.Title} {fixedLanguage} {fixedQuality}"); }
public NewpctRelease(NewpctRelease copyFrom) : base(copyFrom) { NewpctReleaseType = copyFrom.NewpctReleaseType; SeriesName = copyFrom.SeriesName; Season = copyFrom.Season; Episode = copyFrom.Episode; EpisodeTo = copyFrom.EpisodeTo; }
private async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query, int attempts) { var releases = new List <ReleaseInfo>(); lock (cache) { CleanCache(); } _dailyNow = DateTime.Now; _dailyResultIdx = 0; bool rssMode = string.IsNullOrEmpty(query.SanitizedSearchTerm); if (rssMode) { int pg = 1; while (pg <= _maxDailyPages) { Uri url = new Uri(SiteLinkUri, string.Format(_dailyUrl, pg)); var results = await RequestStringWithCookies(url.AbsoluteUri); var items = ParseDailyContent(results.Content); if (items == null || !items.Any()) { break; } releases.AddRange(items); //Check if we need to go to next page bool recentFound = _mostRecentRelease != null && items.Any(r => r.Title == _mostRecentRelease.Title && r.Link.AbsoluteUri == _mostRecentRelease.Link.AbsoluteUri); if (pg == 1) { _mostRecentRelease = (NewpctRelease)items.First().Clone(); } if (recentFound) { break; } pg++; } } else { //Only tv search supported. (newpct web search is useless) bool isTvSearch = query.Categories == null || query.Categories.Length == 0 || query.Categories.Any(c => _allTvCategories.Contains(c)); if (isTvSearch) { return(await TvSearch(query)); } } return(releases); }
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>(); titleParts.Add(release.SeriesName); if (release.NewpctReleaseType == ReleaseType.TV) { if (String.IsNullOrEmpty(quality)) { quality = "HDTV"; } var seasonAndEpisode = "S" + release.Season.ToString().PadLeft(2, '0'); seasonAndEpisode += "E" + release.Episode.ToString().PadLeft(2, '0'); if (release.EpisodeTo != release.Episode && release.EpisodeTo != null && release.EpisodeTo != 0) { seasonAndEpisode += "-" + release.EpisodeTo.ToString().PadLeft(2, '0'); } titleParts.Add(seasonAndEpisode); } if (!string.IsNullOrEmpty(quality) && !release.SeriesName.Contains(quality)) { titleParts.Add(quality); } if (!string.IsNullOrWhiteSpace(language) && !release.SeriesName.Contains(language)) { 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"); } string result = String.Join(".", titleParts); result = Regex.Replace(result, @"[\[\]]+", "."); result = Regex.Replace(result, @"\.[ \.]*\.", "."); return(result); }
private string FixedTitle(NewpctRelease release, string quality, string language) { var fixedTitle = release.Title; if (release.NewpctReleaseType == ReleaseType.Movie && _removeMovieYear) { fixedTitle = _titleYearRegex.Replace(fixedTitle, ""); } var fixedLanguage = language.ToLower() .Replace("español", "spanish") .Replace("espanol", "spanish") .Replace("castellano", "spanish") .ToUpper(); var qualityLower = quality.ToLower(); var fixedQuality = quality.Replace("-", " "); 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"; } return($"{fixedTitle} {fixedLanguage} {fixedQuality}"); }
NewpctRelease GetReleaseFromData(ReleaseType releaseType, string title, string detailsUrl, string quality, string language, long size, DateTime publishDate) { NewpctRelease result = new NewpctRelease(); result.NewpctReleaseType = releaseType; //Sanitize title = title.Replace("\t", "").Replace("\x2013", "-"); Match 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; string audioQuality = match.Groups[13].Value.Trim(' ', '[', ']'); if (string.IsNullOrEmpty(language)) { language = audioQuality; } quality = match.Groups[14].Value.Trim(' ', '[', ']'); string seasonText = result.Season.ToString(); string episodeText = seasonText + result.Episode.ToString().PadLeft(2, '0'); string 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 { Match 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 (!string.IsNullOrWhiteSpace(quality) && (quality.Contains("720") || quality.Contains("1080"))) { result.Category = new List <int> { TorznabCatType.TVHD.ID } } ; else { result.Category = new List <int> { TorznabCatType.TV.ID } }; } else { result.Title = title; result.Category = new List <int> { TorznabCatType.Movies.ID }; } result.Size = size; result.Link = new Uri(detailsUrl); result.Guid = result.Link; result.PublishDate = publishDate; result.Seeders = 1; result.Peers = 1; result.Title = FixedTitle(result, quality, language); return(result); }
private async Task <IEnumerable <ReleaseInfo> > TvSearch(TorznabQuery query) { List <ReleaseInfo> newpctReleases = null; string seriesName = query.SanitizedSearchTerm; int? season = query.Season > 0 ? (int?)query.Season : null; int? episode = null; if (!string.IsNullOrWhiteSpace(query.Episode) && int.TryParse(query.Episode, out int episodeTemp)) { episode = episodeTemp; } //If query has no season/episode info, try to parse title if (season == null && episode == null) { Match searchMatch = _searchStringRegex.Match(query.SanitizedSearchTerm); if (searchMatch.Success) { seriesName = searchMatch.Groups[1].Value.Trim(); season = int.Parse(searchMatch.Groups[2].Value); episode = searchMatch.Groups[4].Success ? (int?)int.Parse(searchMatch.Groups[4].Value) : null; } } //Try to reuse cache lock (cache) { var cachedResult = cache.FirstOrDefault(i => i.Query == seriesName.ToLower()); if (cachedResult != null) { newpctReleases = cachedResult.Results.Select(r => (ReleaseInfo)r.Clone()).ToList(); } } if (newpctReleases == null) { newpctReleases = new List <ReleaseInfo>(); //Search series url foreach (Uri seriesListUrl in SeriesListUris(seriesName)) { newpctReleases.AddRange(await GetReleasesFromUri(seriesListUrl, seriesName)); } //Sonarr removes "the" from shows. If there is nothing try prepending "the" if (newpctReleases.Count == 0 && !(seriesName.ToLower().StartsWith("the"))) { seriesName = "The " + seriesName; foreach (Uri seriesListUrl in SeriesListUris(seriesName)) { newpctReleases.AddRange(await GetReleasesFromUri(seriesListUrl, seriesName)); } } //Cache ALL episodes lock (cache) { cache.Add(new CachedQueryResult(seriesName.ToLower(), newpctReleases)); } } //Filter only episodes needed return(newpctReleases.Where(r => { NewpctRelease nr = r as NewpctRelease; return ( nr.Season.HasValue != season.HasValue || //Can't determine if same season nr.Season.HasValue && season.Value == nr.Season.Value && //Same season and ... ( nr.Episode.HasValue != episode.HasValue || //Can't determine if same episode nr.Episode.HasValue && ( nr.Episode.Value == episode.Value || //Same episode nr.EpisodeTo.HasValue && episode.Value >= nr.Episode.Value && episode.Value <= nr.EpisodeTo.Value //Episode in interval ) ) ); })); }
private NewpctRelease GetReleaseFromData(ReleaseType releaseType, string title, string detailsUrl, string quality, string language, long size, DateTime publishDate, string banner) { var result = new NewpctRelease { NewpctReleaseType = releaseType }; //Sanitize title = title.Replace("-", "").Replace("(", "").Replace(")", ""); title = Regex.Replace(title, @"\s+", " "); 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"))) { result.Category = new List <int> { TorznabCatType.TVHD.ID } } ; else { result.Category = new List <int> { TorznabCatType.TV.ID } }; } else { // movie result.Title = title; result.Category = new List <int> { TorznabCatType.Movies.ID }; } result.Title = FixedTitle(result, quality, language); result.Link = new Uri(detailsUrl); result.Guid = result.Link; result.Comments = result.Link; result.PublishDate = publishDate; result.BannerUrl = new Uri(banner); result.Seeders = 1; result.Peers = 2; result.Size = size; result.DownloadVolumeFactor = 0; result.UploadVolumeFactor = 1; result.MinimumRatio = 1; result.MinimumSeedTime = 172800; // 48 hours return(result); }
private async Task <IEnumerable <ReleaseInfo> > PerformQuery(Uri siteLink, TorznabQuery query, int attempts) { var releases = new List <ReleaseInfo>(); _includeVo = ((BoolItem)configData.GetDynamic("IncludeVo")).Value; _filterMovies = ((BoolItem)configData.GetDynamic("FilterMovies")).Value; _removeMovieAccents = ((BoolItem)configData.GetDynamic("RemoveMovieAccents")).Value; _dailyNow = DateTime.Now; _dailyResultIdx = 0; var rssMode = string.IsNullOrEmpty(query.SanitizedSearchTerm); if (rssMode) { var pg = 1; Uri validUri = null; while (pg <= _maxDailyPages) { IEnumerable <NewpctRelease> items = null; WebClientStringResult results = null; if (validUri != null) { var uri = new Uri(validUri, string.Format(_dailyUrl, pg)); results = await RequestStringWithCookiesAndRetry(uri.AbsoluteUri); if (results == null || string.IsNullOrEmpty(results.Content)) { break; } await FollowIfRedirect(results); items = ParseDailyContent(results.Content); } else { foreach (var uri in GetLinkUris(new Uri(siteLink, string.Format(_dailyUrl, pg)))) { results = await RequestStringWithCookiesAndRetry(uri.AbsoluteUri); if (results != null && !string.IsNullOrEmpty(results.Content)) { await FollowIfRedirect(results); items = ParseDailyContent(results.Content); if (items != null && items.Any()) { validUri = uri; break; } } } } if (items == null || !items.Any()) { break; } releases.AddRange(items); //Check if we need to go to next page var recentFound = _mostRecentRelease != null && items.Any(r => r.Title == _mostRecentRelease.Title && r.Link.AbsoluteUri == _mostRecentRelease.Link.AbsoluteUri); if (pg == 1) { _mostRecentRelease = (NewpctRelease)items.First().Clone(); } if (recentFound) { break; } pg++; } } else { var isTvSearch = query.Categories == null || query.Categories.Length == 0 || query.Categories.Any(c => _allTvCategories.Contains(c)); if (isTvSearch) { releases.AddRange(await TvSearch(siteLink, query)); } var isMovieSearch = query.Categories == null || query.Categories.Length == 0 || query.Categories.Any(c => _allMoviesCategories.Contains(c)); if (isMovieSearch) { releases.AddRange(await MovieSearch(siteLink, query)); } } // Database lost on 2018/04/05, all previous torrents don't have download links var failureDay = new DateTime(2018, 04, 05); releases = releases.Where(r => r.PublishDate > failureDay).ToList(); return(releases); }
private async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query, int attempts) { var releases = new List <ReleaseInfo>(); bool rssMode = string.IsNullOrEmpty(query.SanitizedSearchTerm); Uri siteLinkUri = new Uri(configData.SiteLink.Value); if (rssMode) { int pg = 1; while (pg <= _maxDailyPages) { Uri url = new Uri(siteLinkUri, string.Format(_dailyUrl, pg)); var results = await RequestStringWithCookies(url.AbsoluteUri); var items = ParseDailyContent(results.Content); if (items == null || !items.Any()) { break; } releases.AddRange(items); //Check if we need to go to next page bool recentFound = _mostRecentRelease != null && items.Any(r => r.Title == _mostRecentRelease.Title && r.Link.AbsoluteUri == _mostRecentRelease.Link.AbsoluteUri); if (pg == 1) { _mostRecentRelease = (ReleaseInfo)items.First().Clone(); } if (recentFound) { break; } pg++; } } else { //Only tv search supported. (newpct web search is useless) bool isTvSearch = query.Categories == null || query.Categories.Length == 0 || query.Categories.Any(c => _allTvCategories.Contains(c)); if (isTvSearch) { var newpctReleases = new List <ReleaseInfo>(); string seriesName = query.SanitizedSearchTerm; int? season = query.Season > 0 ? (int?)query.Season : null; int? episode = null; if (!string.IsNullOrWhiteSpace(query.Episode) && int.TryParse(query.Episode, out int episodeTemp)) { episode = episodeTemp; } //If query has no season/episode info, try to parse title if (season == null && episode == null) { Match searchMatch = _searchStringRegex.Match(query.SanitizedSearchTerm); if (searchMatch.Success) { seriesName = searchMatch.Groups[1].Value.Trim(); season = int.Parse(searchMatch.Groups[2].Value); episode = searchMatch.Groups[4].Success ? (int?)int.Parse(searchMatch.Groups[4].Value) : null; } } //Try to reuse cache bool cacheFound = false; lock (cache) { CleanCache(); var cachedResult = cache.FirstOrDefault(i => i.Query == seriesName.ToLower()); if (cachedResult != null && cachedResult.Results != null) { cacheFound = true; newpctReleases = cachedResult.Results.Where(r => (r as NewpctRelease) != null).ToList(); if (!newpctReleases.Any() && cachedResult.Results.Any()) { cacheFound = false; } } } if (!cacheFound) { IEnumerable <string> lettersUrl; if (!((BoolItem)configData.GetDynamic("IncludeVo")).Value) { lettersUrl = _seriesLetterUrls; } else { lettersUrl = _seriesLetterUrls.Concat(_seriesVOLetterUrls); } string seriesLetter = !char.IsDigit(seriesName[0]) ? seriesName[0].ToString() : "0-9"; //Search series url foreach (string urlFormat in lettersUrl) { Uri seriesListUrl = new Uri(siteLinkUri, string.Format(urlFormat, seriesLetter.ToLower())); var results = await RequestStringWithCookies(seriesListUrl.AbsoluteUri); //Episodes list string seriesEpisodesUrl = ParseSeriesListContent(results.Content, seriesName); if (!string.IsNullOrEmpty(seriesEpisodesUrl)) { int pg = 1; while (pg < _maxEpisodesListPages) { Uri episodesListUrl = new Uri(string.Format(_seriesUrl, seriesEpisodesUrl, pg)); results = await RequestStringWithCookies(episodesListUrl.AbsoluteUri); var items = ParseEpisodesListContent(results.Content); if (items == null || !items.Any()) { break; } newpctReleases.AddRange(items); pg++; } } } //Cache ALL episodes lock (cache) { cache.Add(new CachedQueryResult(seriesName.ToLower(), newpctReleases)); } } //Filter only episodes needed releases.AddRange(newpctReleases.Where(r => { NewpctRelease nr = r as NewpctRelease; return(nr.Season.HasValue != season.HasValue || //Can't determine if same season nr.Season.HasValue && season.Value == nr.Season.Value && //Same season and ... ( nr.Episode.HasValue != episode.HasValue || //Can't determine if same episode nr.Episode.HasValue && ( nr.Episode.Value == episode.Value || //Same episode nr.EpisodeTo.HasValue && episode.Value >= nr.Episode.Value && episode.Value <= nr.EpisodeTo.Value //Episode in interval ) )); })); } } return(releases); }
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>(); titleParts.Add(release.SeriesName); if (release.NewpctReleaseType == ReleaseType.TV) { if (string.IsNullOrEmpty(quality)) { quality = "HDTV"; } var seasonAndEpisode = "S" + release.Season.ToString().PadLeft(2, '0'); seasonAndEpisode += "E" + release.Episode.ToString().PadLeft(2, '0'); if (release.EpisodeTo != release.Episode && release.EpisodeTo != null && release.EpisodeTo != 0) { seasonAndEpisode += "-" + release.EpisodeTo.ToString().PadLeft(2, '0'); } titleParts.Add(seasonAndEpisode); } if (!string.IsNullOrEmpty(quality) && !release.SeriesName.Contains(quality)) { titleParts.Add(quality); } if (!string.IsNullOrWhiteSpace(language) && !release.SeriesName.Contains(language)) { 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); }