Exemple #1
0
        /// <summary>
        /// Execute our search query
        /// </summary>
        /// <param name="query">Query</param>
        /// <returns>Releases</returns>
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases   = new List <ReleaseInfo>();
            var searchTerm = query.GetEpisodeSearchString() + " " + query.SanitizedSearchTerm; // use episode search string first, see issue #1202

            searchTerm = searchTerm.Trim();
            searchTerm = searchTerm.ToLower();

            if (EnhancedAnime && query.HasSpecifiedCategories && (query.Categories.Contains(TorznabCatType.TVAnime.ID) || query.Categories.Contains(100032) || query.Categories.Contains(100101) || query.Categories.Contains(100110)))
            {
                var regex = new Regex(" ([0-9]+)");
                searchTerm = regex.Replace(searchTerm, " E$1");
            }

            // Check cache first so we don't query the server (if search term used or not in dev mode)
            if (!DevMode && !string.IsNullOrEmpty(searchTerm))
            {
                lock (cache)
                {
                    // Remove old cache items
                    CleanCache();

                    // Search in cache
                    var cachedResult = cache.FirstOrDefault(i => i.Query == searchTerm);
                    if (cachedResult != null)
                    {
                        return(cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray());
                    }
                }
            }

            // Build our query
            var request = BuildQuery(searchTerm, query, ApiEndpoint);

            // Getting results & Store content
            var results = await QueryExec(request);

            try
            {
                // Deserialize our Json Response
                var xthorResponse = JsonConvert.DeserializeObject <XthorResponse>(results);

                // Check Tracker's State
                CheckApiState(xthorResponse.error);

                // If contains torrents
                if (xthorResponse.torrents != null)
                {
                    // Adding each torrent row to releases
                    releases.AddRange(xthorResponse.torrents.Select(torrent =>
                    {
                        //issue #3847 replace multi keyword
                        if (!string.IsNullOrEmpty(ReplaceMulti))
                        {
                            var regex    = new Regex("(?i)([\\.\\- ])MULTI([\\.\\- ])");
                            torrent.name = regex.Replace(torrent.name, "$1" + ReplaceMulti + "$2");
                        }

                        // issue #8759 replace vostfr and subfrench with English
                        if (ConfigData.Vostfr.Value)
                        {
                            torrent.name = torrent.name.Replace("VOSTFR", "ENGLISH").Replace("SUBFRENCH", "ENGLISH");
                        }

                        var publishDate = DateTimeUtil.UnixTimestampToDateTime(torrent.added);
                        //TODO replace with download link?
                        var guid    = new Uri(TorrentDetailsUrl.Replace("{id}", torrent.id.ToString()));
                        var details = new Uri(TorrentDetailsUrl.Replace("{id}", torrent.id.ToString()));
                        var link    = new Uri(torrent.download_link);
                        var release = new ReleaseInfo
                        {
                            // Mapping data
                            Category             = MapTrackerCatToNewznab(torrent.category.ToString()),
                            Title                = torrent.name,
                            Seeders              = torrent.seeders,
                            Peers                = torrent.seeders + torrent.leechers,
                            MinimumRatio         = 1,
                            MinimumSeedTime      = 345600,
                            PublishDate          = publishDate,
                            Size                 = torrent.size,
                            Grabs                = torrent.times_completed,
                            Files                = torrent.numfiles,
                            UploadVolumeFactor   = 1,
                            DownloadVolumeFactor = (torrent.freeleech == 1 ? 0 : 1),
                            Guid                 = guid,
                            Details              = details,
                            Link                 = link,
                            TMDb                 = torrent.tmdb_id
                        };

                        //TODO make consistent with other trackers
                        if (DevMode)
                        {
                            Output(release.ToString());
                        }

                        return(release);
                    }));
                }
            }
            catch (Exception ex)
            {
                OnParseError("Unable to parse result \n" + ex.StackTrace, ex);
            }

            // Return found releases
            return(releases);
        }
Exemple #2
0
        /// <summary>
        /// Execute our search query
        /// </summary>
        /// <param name="query">Query</param>
        /// <returns>Releases</returns>
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases   = new List <ReleaseInfo>();
            var searchTerm = query.SanitizedSearchTerm + " " + query.GetEpisodeSearchString();

            searchTerm = searchTerm.Trim();
            searchTerm = searchTerm.ToLower();
            searchTerm = searchTerm.Replace(" ", ".");

            if (EnhancedAnimeSearch && query.HasSpecifiedCategories && (query.Categories.Contains(TorznabCatType.TVAnime.ID) || query.Categories.Contains(100032) || query.Categories.Contains(100101) || query.Categories.Contains(100110)))
            {
                var regex = new Regex(" ([0-9]+)");
                searchTerm = regex.Replace(searchTerm, " E$1");
            }

            // Multiple page support
            var nextPage = 1; var followingPages = true;

            do
            {
                // Build our query
                var request = BuildQuery(searchTerm, query, ApiEndpoint, nextPage);

                // Getting results
                logger.Info("\nXthor - Querying API page " + nextPage);
                var results = await QueryTrackerAsync(request);

                // Torrents Result Count
                var torrentsCount = 0;

                try
                {
                    // Deserialize our Json Response
                    var xthorResponse = JsonConvert.DeserializeObject <XthorResponse>(results);

                    // Check Tracker's State
                    CheckApiState(xthorResponse.Error);

                    // If contains torrents
                    if (xthorResponse.Torrents != null)
                    {
                        // Store torrents rows count result
                        torrentsCount = xthorResponse.Torrents.Count();
                        logger.Info("\nXthor - Found " + torrentsCount + " torrents on current page.");

                        // Adding each torrent row to releases
                        // Exclude hidden torrents (category 106, example => search 'yoda' in the API) #10407
                        releases.AddRange(xthorResponse.Torrents
                                          .Where(torrent => torrent.Category != 106).Select(torrent =>
                        {
                            //issue #3847 replace multi keyword
                            if (!string.IsNullOrEmpty(MultiReplacement))
                            {
                                var regex    = new Regex("(?i)([\\.\\- ])MULTI([\\.\\- ])");
                                torrent.Name = regex.Replace(torrent.Name, "$1" + MultiReplacement + "$2");
                            }

                            // issue #8759 replace vostfr and subfrench with English
                            if (SubReplacement)
                            {
                                torrent.Name = torrent.Name.Replace("VOSTFR", "ENGLISH").Replace("SUBFRENCH", "ENGLISH");
                            }

                            var publishDate = DateTimeUtil.UnixTimestampToDateTime(torrent.Added);
                            //TODO replace with download link?
                            var guid    = new Uri(TorrentDetailsUrl.Replace("{id}", torrent.Id.ToString()));
                            var details = new Uri(TorrentDetailsUrl.Replace("{id}", torrent.Id.ToString()));
                            var link    = new Uri(torrent.Download_link);
                            var release = new ReleaseInfo
                            {
                                // Mapping data
                                Category             = MapTrackerCatToNewznab(torrent.Category.ToString()),
                                Title                = torrent.Name,
                                Seeders              = torrent.Seeders,
                                Peers                = torrent.Seeders + torrent.Leechers,
                                MinimumRatio         = 1,
                                MinimumSeedTime      = 345600,
                                PublishDate          = publishDate,
                                Size                 = torrent.Size,
                                Grabs                = torrent.Times_completed,
                                Files                = torrent.Numfiles,
                                UploadVolumeFactor   = 1,
                                DownloadVolumeFactor = (torrent.Freeleech == 1 ? 0 : 1),
                                Guid                 = guid,
                                Details              = details,
                                Link                 = link,
                                TMDb                 = torrent.Tmdb_id
                            };

                            return(release);
                        }));
                        nextPage++;
                    }
                    else
                    {
                        logger.Info("\nXthor - No results found on page  " + nextPage + ", stopping follow of next page.");
                        //  No results or no more results available
                        followingPages = false;
                        break;
                    }
                }
                catch (Exception ex)
                {
                    OnParseError("Unable to parse result \n" + ex.StackTrace, ex);
                }

                // Stop ?
                if (query.IsTmdbQuery && MaxPagesBypassForTMDB)
                {
                    if (nextPage > MaxPagesHardLimit)
                    {
                        logger.Info("\nXthor - Stopping follow of next page " + nextPage + " due to page hard limit reached.");
                        break;
                    }
                    logger.Info("\nXthor - Continue to next page " + nextPage + " due to TMDB request and activated max page bypass for this type of query. Max page hard limit: 4.");
                    continue;
                }
                else
                {
                    if (torrentsCount < 32)
                    {
                        logger.Info("\nXthor - Stopping follow of next page " + nextPage + " due max available results reached.");
                        break;
                    }
                    else if (nextPage > MaxPages)
                    {
                        logger.Info("\nXthor - Stopping follow of next page " + nextPage + " due to page limit reached.");
                        break;
                    }
                    else if (query.IsTest)
                    {
                        logger.Info("\nXthor - Stopping follow of next page " + nextPage + " due to index test query.");
                        break;
                    }
                }
            } while (followingPages);

            // Check if there is duplicate and return unique rows - Xthor API can be very buggy !
            var uniqReleases    = releases.GroupBy(x => x.Guid).Select(x => x.First()).ToList();
            var errorPercentage = 1 - ((double)uniqReleases.Count() / releases.Count());

            if (errorPercentage >= 0.25)
            {
                logger.Warn("\nXthor - High percentage error detected: " + string.Format("{0:0.0%}", errorPercentage) + "\nWe strongly recommend that you lower max page to 1, as there is no benefit to grab additionnals.\nTracker API sent us duplicated pages with same results, even if we deduplicate returned rows, please consider to lower as it's unnecessary and increase time used for query for the same result.");
            }
            // Return found releases
            return(uniqReleases);
        }
Exemple #3
0
        /// <summary>
        /// Execute our search query
        /// </summary>
        /// <param name="query">Query</param>
        /// <returns>Releases</returns>
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases   = new List <ReleaseInfo>();
            var searchTerm = query.SanitizedSearchTerm + " " + query.GetEpisodeSearchString();

            if (EnhancedAnimeSearch && query.HasSpecifiedCategories && (query.Categories.Contains(TorznabCatType.TVAnime.ID) || query.Categories.Contains(100032) || query.Categories.Contains(100101) || query.Categories.Contains(100110)))
            {
                var regex = new Regex(" ([0-9]+)");
                searchTerm = regex.Replace(searchTerm, " E$1");
            }

            searchTerm = searchTerm.Trim();
            searchTerm = searchTerm.ToLower();
            searchTerm = searchTerm.Replace(" ", ".");

            // Multiple page support
            var nextPage       = 1;
            var followingPages = true;

            do
            {
                // Build our query
                var request = BuildQuery(searchTerm, query, SearchUrl, nextPage);

                // Getting results
                logger.Info("\nAbnormal - Querying API page " + nextPage);
                var dom     = new HtmlParser().ParseDocument(await QueryExecAsync(request));
                var results = dom.QuerySelectorAll(".table-rows > tbody > tr:not(.mvc-grid-empty-row)");

                // Torrents Result Count
                var torrentsCount = results.Length;

                try
                {
                    // If contains torrents
                    if (torrentsCount > 0)
                    {
                        logger.Info("\nAbnormal - Found " + torrentsCount + " torrents on current page.");

                        // Adding each torrent row to releases
                        releases.AddRange(results.Select(torrent =>
                        {
                            // Selectors
                            var id         = torrent.QuerySelector("td.grid-release-column > a").GetAttribute("href");  // ID
                            var name       = torrent.QuerySelector("td.grid-release-column > a").TextContent;           // Release Name
                            var categoryId = torrent.QuerySelector("td.grid-cat-column > a").GetAttribute("href");      // Category
                            var completed  = torrent.QuerySelector("td:nth-of-type(3)").TextContent;                    // Completed
                            var seeders    = torrent.QuerySelector("td.text-green").TextContent;                        // Seeders
                            var leechers   = torrent.QuerySelector("td.text-red").TextContent;                          // Leechers
                            var size       = torrent.QuerySelector("td:nth-of-type(5)").TextContent;                    // Size

                            var release = new ReleaseInfo
                            {
                                // Mapping data
                                Category             = MapTrackerCatToNewznab(Regex.Match(categoryId, @"\d+").Value),
                                Title                = name,
                                Seeders              = int.Parse(Regex.Match(seeders, @"\d+").Value),
                                Peers                = int.Parse(Regex.Match(seeders, @"\d+").Value) + int.Parse(Regex.Match(leechers, @"\d+").Value),
                                Grabs                = int.Parse(Regex.Match(completed, @"\d+").Value) + int.Parse(Regex.Match(leechers, @"\d+").Value),
                                MinimumRatio         = 1,
                                MinimumSeedTime      = 172800,
                                Size                 = ReleaseInfo.GetBytes(size.Replace("Go", "gb").Replace("Mo", "mb").Replace("Ko", "kb")),
                                UploadVolumeFactor   = 1,
                                DownloadVolumeFactor = 1,
                                PublishDate          = DateTime.Now,
                                Guid                 = new Uri(TorrentDetailsUrl.Replace("{id}", Regex.Match(id, @"\d+").Value)),
                                Details              = new Uri(TorrentDetailsUrl.Replace("{id}", Regex.Match(id, @"\d+").Value)),
                                Link                 = new Uri(TorrentDownloadUrl.Replace("{id}", Regex.Match(id, @"\d+").Value))
                            };

                            // Multi Replacement
                            if (!string.IsNullOrEmpty(MultiReplacement))
                            {
                                var regex     = new Regex("(?i)([\\.\\- ])MULTI([\\.\\- ])");
                                release.Title = regex.Replace(release.Title, "$1" + MultiReplacement + "$2");
                            }

                            // Sub Replacement
                            if (SubReplacement)
                            {
                                release.Title = release.Title.Replace("VOSTFR", "ENGLISH").Replace("SUBFRENCH", "ENGLISH");
                            }

                            // Freeleech
                            if (torrent.QuerySelector("img[alt=\"Freeleech\"]") != null)
                            {
                                release.DownloadVolumeFactor = 0;
                            }

                            return(release);
                        }));
                        if (torrentsCount == 50)
                        {
                            // Is there more pages to follow ?
                            var morePages = dom.QuerySelectorAll("div.mvc-grid-pager > button").Last().GetAttribute("tabindex");
                            if (morePages == "-1")
                            {
                                followingPages = false;
                            }
                        }
                        nextPage++;
                    }
                    else
                    {
                        logger.Info("\nAbnormal - No results found on page  " + nextPage + ", stopping follow of next page.");
                        //  No results or no more results available
                        followingPages = false;
                        break;
                    }
                }
                catch (Exception ex)
                {
                    OnParseError("Unable to parse result \n" + ex.StackTrace, ex);
                }

                // Stop ?
                if (torrentsCount < int.Parse(dom.QuerySelector(".mvc-grid-pager-rows").GetAttribute("value")))
                {
                    logger.Info("\nAbnormal - Stopping follow of next page " + nextPage + " due max available results reached.");
                    break;
                }
                else if (nextPage > MaxPages)
                {
                    logger.Info("\nAbnormal - Stopping follow of next page " + nextPage + " due to page limit reached.");
                    break;
                }
                else if (query.IsTest)
                {
                    logger.Info("\nAbnormal - Stopping follow of next page " + nextPage + " due to index test query.");
                    break;
                }
            } while (followingPages);

            // Return found releases
            return(releases);
        }
Exemple #4
0
        /// <summary>
        /// Execute our search query
        /// </summary>
        /// <param name="query">Query</param>
        /// <returns>Releases</returns>
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases   = new List <ReleaseInfo>();
            var searchTerm = query.SanitizedSearchTerm + " " + query.GetEpisodeSearchString();

            searchTerm = searchTerm.Trim();
            searchTerm = searchTerm.ToLower();
            searchTerm = searchTerm.Replace(" ", ".");

            if (EnhancedAnime && query.HasSpecifiedCategories && (query.Categories.Contains(TorznabCatType.TVAnime.ID) || query.Categories.Contains(100032) || query.Categories.Contains(100101) || query.Categories.Contains(100110)))
            {
                var regex = new Regex(" ([0-9]+)");
                searchTerm = regex.Replace(searchTerm, " E$1");
            }

            logger.Info("\nXthor - Search requested for \"" + searchTerm + "\"");

            // Multiple page support
            var nextPage = 1; var followingPages = true;

            do
            {
                // Build our query
                var request = BuildQuery(searchTerm, query, ApiEndpoint, nextPage);

                // Getting results
                logger.Info("\nXthor - Querying API page " + nextPage);
                var results = await QueryTrackerAsync(request);

                // Torrents Result Count
                var torrentsCount = 0;

                try
                {
                    // Deserialize our Json Response
                    var xthorResponse = JsonConvert.DeserializeObject <XthorResponse>(results);

                    // Check Tracker's State
                    CheckApiState(xthorResponse.Error);

                    // If contains torrents
                    if (xthorResponse.Torrents != null)
                    {
                        // Store torrents rows count result
                        torrentsCount = xthorResponse.Torrents.Count();
                        logger.Info("\nXthor - Found " + torrentsCount + " torrents on current page.");

                        // Adding each torrent row to releases
                        // Exclude hidden torrents (category 106, example => search 'yoda' in the API) #10407
                        releases.AddRange(xthorResponse.Torrents
                                          .Where(torrent => torrent.Category != 106).Select(torrent =>
                        {
                            //issue #3847 replace multi keyword
                            if (!string.IsNullOrEmpty(ReplaceMulti))
                            {
                                var regex    = new Regex("(?i)([\\.\\- ])MULTI([\\.\\- ])");
                                torrent.Name = regex.Replace(torrent.Name, "$1" + ReplaceMulti + "$2");
                            }

                            // issue #8759 replace vostfr and subfrench with English
                            if (ConfigData.Vostfr.Value)
                            {
                                torrent.Name = torrent.Name.Replace("VOSTFR", "ENGLISH").Replace("SUBFRENCH", "ENGLISH");
                            }

                            var publishDate = DateTimeUtil.UnixTimestampToDateTime(torrent.Added);
                            //TODO replace with download link?
                            var guid    = new Uri(TorrentDetailsUrl.Replace("{id}", torrent.Id.ToString()));
                            var details = new Uri(TorrentDetailsUrl.Replace("{id}", torrent.Id.ToString()));
                            var link    = new Uri(torrent.Download_link);
                            var release = new ReleaseInfo
                            {
                                // Mapping data
                                Category             = MapTrackerCatToNewznab(torrent.Category.ToString()),
                                Title                = torrent.Name,
                                Seeders              = torrent.Seeders,
                                Peers                = torrent.Seeders + torrent.Leechers,
                                MinimumRatio         = 1,
                                MinimumSeedTime      = 345600,
                                PublishDate          = publishDate,
                                Size                 = torrent.Size,
                                Grabs                = torrent.Times_completed,
                                Files                = torrent.Numfiles,
                                UploadVolumeFactor   = 1,
                                DownloadVolumeFactor = (torrent.Freeleech == 1 ? 0 : 1),
                                Guid                 = guid,
                                Details              = details,
                                Link                 = link,
                                TMDb                 = torrent.Tmdb_id
                            };

                            return(release);
                        }));
                        nextPage++;
                    }
                    else
                    {
                        logger.Info("\nXthor - No results found on page  " + (nextPage - 1) + ", stopping follow of next page.");
                        //  No results or no more results available
                        followingPages = false;
                    }
                }
                catch (Exception ex)
                {
                    OnParseError("Unable to parse result \n" + ex.StackTrace, ex);
                }

                // Stop ?
                if (nextPage > MaxPageLoads | torrentsCount < 32 | string.IsNullOrWhiteSpace(searchTerm))
                {
                    logger.Info("\nXthor - Stopping follow of next page " + nextPage + " due to page limit or max available results reached or indexer test.");
                    followingPages = false;
                }
            } while (followingPages);

            // Check if there is duplicate and return unique rows - Xthor API can be very buggy !
            var uniqReleases = releases.GroupBy(x => x.Guid).Select(x => x.First()).ToList();

            // Return found releases
            return(uniqReleases);
        }