Exemplo n.º 1
0
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();

            searchBlock Search = Definition.Search;

            // init template context
            var variables = getTemplateVariablesFromConfigData();

            variables[".Query.Type"]       = query.QueryType;
            variables[".Query.Q"]          = query.SearchTerm;
            variables[".Query.Series"]     = null;
            variables[".Query.Ep"]         = query.Episode;
            variables[".Query.Season"]     = query.Season;
            variables[".Query.Movie"]      = null;
            variables[".Query.Year"]       = null;
            variables[".Query.Limit"]      = query.Limit;
            variables[".Query.Offset"]     = query.Offset;
            variables[".Query.Extended"]   = query.Extended;
            variables[".Query.Categories"] = query.Categories;
            variables[".Query.APIKey"]     = query.ApiKey;
            variables[".Query.TVDBID"]     = null;
            variables[".Query.TVRageID"]   = query.RageID;
            variables[".Query.IMDBID"]     = query.ImdbID;
            variables[".Query.TVMazeID"]   = null;
            variables[".Query.TraktID"]    = null;

            variables[".Query.Episode"] = query.GetEpisodeSearchString();
            variables[".Categories"]    = MapTorznabCapsToTrackers(query);

            var KeywordTokens    = new List <string>();
            var KeywordTokenKeys = new List <string> {
                "Q", "Series", "Movie", "Year"
            };

            foreach (var key in KeywordTokenKeys)
            {
                var Value = (string)variables[".Query." + key];
                if (!string.IsNullOrWhiteSpace(Value))
                {
                    KeywordTokens.Add(Value);
                }
            }

            if (!string.IsNullOrWhiteSpace((string)variables[".Query.Episode"]))
            {
                KeywordTokens.Add((string)variables[".Query.Episode"]);
            }
            variables[".Query.Keywords"] = string.Join(" ", KeywordTokens);
            variables[".Keywords"]       = variables[".Query.Keywords"];

            // build search URL
            var searchUrl       = SiteLink + applyGoTemplateText(Search.Path, variables) + "?";
            var queryCollection = new NameValueCollection();

            if (Search.Inputs != null)
            {
                foreach (var Input in Search.Inputs)
                {
                    var value = applyGoTemplateText(Input.Value, variables);
                    if (Input.Key == "$raw")
                    {
                        searchUrl += value;
                    }
                    else
                    {
                        queryCollection.Add(Input.Key, value);
                    }
                }
            }
            searchUrl += "&" + queryCollection.GetQueryString();

            // send HTTP request
            var response = await RequestBytesWithCookies(searchUrl);

            var results = Encoding.GetEncoding("iso-8859-1").GetString(response.Content);

            try
            {
                var SearchResultParser   = new HtmlParser();
                var SearchResultDocument = SearchResultParser.Parse(results);

                var             RowsDom = SearchResultDocument.QuerySelectorAll(Search.Rows.Selector);
                List <IElement> Rows    = new List <IElement>();
                foreach (var RowDom in RowsDom)
                {
                    Rows.Add(RowDom);
                }

                // merge following rows for After selector
                var After = Definition.Search.Rows.After;
                if (After > 0)
                {
                    for (int i = 0; i < Rows.Count; i += 1)
                    {
                        var CurrentRow = Rows[i];
                        for (int j = 0; j < After; j += 1)
                        {
                            var          MergeRowIndex = i + j + 1;
                            var          MergeRow      = Rows[MergeRowIndex];
                            List <INode> MergeNodes    = new List <INode>();
                            foreach (var node in MergeRow.QuerySelectorAll("td"))
                            {
                                MergeNodes.Add(node);
                            }
                            CurrentRow.Append(MergeNodes.ToArray());
                        }
                        Rows.RemoveRange(i + 1, After);
                    }
                }

                foreach (var Row in Rows)
                {
                    try
                    {
                        var release = new ReleaseInfo();
                        release.MinimumRatio    = 1;
                        release.MinimumSeedTime = 48 * 60 * 60;

                        // Parse fields
                        foreach (var Field in Search.Fields)
                        {
                            string value = handleSelector(Field.Value, Row);
                            value = ParseUtil.NormalizeSpace(value);
                            try
                            {
                                switch (Field.Key)
                                {
                                case "download":
                                    if (value.StartsWith("magnet:"))
                                    {
                                        release.MagnetUri = new Uri(value);
                                        release.Link      = release.MagnetUri;
                                    }
                                    else
                                    {
                                        release.Link = resolvePath(value);
                                    }
                                    break;

                                case "details":
                                    var url = resolvePath(value);
                                    release.Guid = url;
                                    if (release.Comments == null)
                                    {
                                        release.Comments = url;
                                    }
                                    break;

                                case "comments":
                                    var CommentsUrl = resolvePath(value);
                                    release.Comments = CommentsUrl;
                                    if (release.Guid == null)
                                    {
                                        release.Guid = CommentsUrl;
                                    }
                                    break;

                                case "title":
                                    release.Title = value;
                                    break;

                                case "description":
                                    release.Description = value;
                                    break;

                                case "category":
                                    release.Category = MapTrackerCatToNewznab(value);
                                    break;

                                case "size":
                                    release.Size = ReleaseInfo.GetBytes(value);
                                    break;

                                case "leechers":
                                    if (release.Peers == null)
                                    {
                                        release.Peers = ParseUtil.CoerceInt(value);
                                    }
                                    else
                                    {
                                        release.Peers += ParseUtil.CoerceInt(value);
                                    }
                                    break;

                                case "seeders":
                                    release.Seeders = ParseUtil.CoerceInt(value);
                                    if (release.Peers == null)
                                    {
                                        release.Peers = release.Seeders;
                                    }
                                    else
                                    {
                                        release.Peers += release.Seeders;
                                    }
                                    break;

                                case "date":
                                    release.PublishDate = DateTimeUtil.FromUnknown(value);
                                    break;

                                case "files":
                                    release.Files = ParseUtil.CoerceLong(value);
                                    break;

                                case "grabs":
                                    release.Grabs = ParseUtil.CoerceLong(value);
                                    break;

                                case "downloadvolumefactor":
                                    release.DownloadVolumeFactor = ParseUtil.CoerceDouble(value);
                                    break;

                                case "uploadvolumefactor":
                                    release.UploadVolumeFactor = ParseUtil.CoerceDouble(value);
                                    break;

                                default:
                                    break;
                                }
                            }
                            catch (Exception ex)
                            {
                                throw new Exception(string.Format("Error while parsing field={0}, selector={1}, value={2}: {3}", Field.Key, Field.Value.Selector, value, ex.Message));
                            }
                        }

                        // if DateHeaders is set go through the previous rows and look for the header selector
                        var DateHeaders = Definition.Search.Rows.Dateheaders;
                        if (DateHeaders != null)
                        {
                            var    PrevRow = Row.PreviousElementSibling;
                            string value   = null;
                            while (PrevRow != null)
                            {
                                try
                                {
                                    value = handleSelector(DateHeaders, PrevRow);
                                    break;
                                }
                                catch (Exception ex)
                                {
                                    // do nothing
                                }
                                PrevRow = PrevRow.PreviousElementSibling;
                            }

                            if (value == null)
                            {
                                throw new Exception(string.Format("No date header row found for {0}", release.ToString()));
                            }

                            release.PublishDate = DateTimeUtil.FromUnknown(value);
                        }

                        releases.Add(release);
                    }
                    catch (Exception ex)
                    {
                        logger.Error(string.Format("CardigannIndexer ({0}): Error while parsing row '{1}': {2}", ID, Row.OuterHtml, ex));
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(results, ex);
            }

            return(releases);
        }
Exemplo n.º 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.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");
                        }

                        var publishDate = DateTimeUtil.UnixTimestampToDateTime(torrent.added);
                        //TODO replace with download link?
                        var guid     = new Uri(TorrentDescriptionUrl.Replace("{id}", torrent.id.ToString()));
                        var comments = new Uri(TorrentCommentUrl.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,
                            Comments             = comments,
                            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);
        }
Exemplo n.º 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.GetQueryString();

            searchTerm = searchTerm.ToLower();

            // 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 =>
                    {
                        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          = DateTimeUtil.UnixTimestampToDateTime(torrent.added),
                            Size                 = torrent.size,
                            Grabs                = torrent.times_completed,
                            Files                = torrent.numfiles,
                            UploadVolumeFactor   = 1,
                            DownloadVolumeFactor = (torrent.freeleech == 1 ? 0 : 1),
                            Guid                 = new Uri(TorrentDescriptionUrl.Replace("{id}", torrent.id.ToString())),
                            Comments             = new Uri(TorrentCommentUrl.Replace("{id}", torrent.id.ToString())),
                            Link                 = new Uri(torrent.download_link),
                            TMDb                 = torrent.tmdb_id
                        };

                        if (DevMode)
                        {
                            Output(release.ToString());
                        }

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

            // Return found releases
            return(releases);
        }