示例#1
0
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases        = new List <ReleaseInfo>();
            var searchString    = query.GetQueryString();
            var searchUrl       = SearchUrl;
            var queryCollection = new NameValueCollection();

            queryCollection.Add("total", "146"); // Not sure what this is about but its required!

            var cat       = "0";
            var queryCats = MapTorznabCapsToTrackers(query);

            if (queryCats.Count == 1)
            {
                cat = queryCats.First().ToString();
            }

            queryCollection.Add("cat", cat);
            queryCollection.Add("searchin", "filename");
            queryCollection.Add("search", searchString);
            queryCollection.Add("page", "1");
            searchUrl += "?" + queryCollection.GetQueryString();

            var extraHeaders = new Dictionary <string, string>()
            {
                { "X-Requested-With", "XMLHttpRequest" }
            };

            var response = await RequestStringWithCookiesAndRetry(searchUrl, null, SearchUrlReferer, extraHeaders);

            var results = response.Content;

            try
            {
                CQ dom = results;

                var rows = dom["tr"];
                foreach (var row in rows.Skip(1))
                {
                    var release    = new ReleaseInfo();
                    var qRow       = row.Cq();
                    var qTitleLink = qRow.Find("td:eq(1) a:eq(0)").First();
                    release.Title = qTitleLink.Find("strong").Text().Trim();

                    // If we search an get no results, we still get a table just with no info.
                    if (string.IsNullOrWhiteSpace(release.Title))
                    {
                        break;
                    }

                    release.Description = release.Title;
                    release.Guid        = new Uri(qTitleLink.Attr("href"));
                    release.Comments    = release.Guid;

                    var dateString = qRow.Find("td:eq(4)").Text();
                    release.PublishDate = DateTime.ParseExact(dateString, "dd MMM yy", CultureInfo.InvariantCulture);

                    var qLink = qRow.Find("td:eq(2) a");
                    release.Link = new Uri(qLink.Attr("href"));

                    var sizeStr = qRow.Find("td:eq(5)").Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    var connections = qRow.Find("td:eq(7)").Text().Trim().Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                    release.Seeders = ParseUtil.CoerceInt(connections[0].Trim());
                    release.Peers   = ParseUtil.CoerceInt(connections[1].Trim()) + release.Seeders;

                    var rCat    = row.Cq().Find("td:eq(0) a").First().Attr("href");
                    var rCatIdx = rCat.IndexOf("cat=");
                    if (rCatIdx > -1)
                    {
                        rCat = rCat.Substring(rCatIdx + 4);
                    }

                    release.Category = MapTrackerCatToNewznab(rCat);

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results, ex);
            }

            return(releases);
        }
示例#2
0
        public static TorznabQuery ToTorznabQuery(TorznabRequest request)
        {
            var query = new TorznabQuery()
            {
                QueryType  = "search",
                SearchTerm = request.q,
                ImdbID     = request.imdbid,
                Episode    = request.ep,
            };

            if (request.t != null)
            {
                query.QueryType = request.t;
            }
            if (!string.IsNullOrWhiteSpace(request.extended))
            {
                query.Extended = ParseUtil.CoerceInt(request.extended);
            }
            if (!string.IsNullOrWhiteSpace(request.limit))
            {
                query.Limit = ParseUtil.CoerceInt(request.limit);
            }
            if (!string.IsNullOrWhiteSpace(request.offset))
            {
                query.Offset = ParseUtil.CoerceInt(request.offset);
            }

            bool _cache;

            if (bool.TryParse(request.cache, out _cache))
            {
                query.Cache = _cache;
            }

            if (request.cat != null)
            {
                query.Categories = request.cat.Split(',').Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => int.Parse(s)).ToArray();
            }
            else
            {
                if (query.QueryType == "movie" && !string.IsNullOrWhiteSpace(request.imdbid))
                {
                    query.Categories = new int[] { TorznabCatType.Movies.ID }
                }
                ;
                else
                {
                    query.Categories = new int[0];
                }
            }

            if (!string.IsNullOrWhiteSpace(request.rid))
            {
                query.RageID = int.Parse(request.rid);
            }
            if (!string.IsNullOrWhiteSpace(request.tvdbid))
            {
                query.TvdbID = int.Parse(request.tvdbid);
            }
            if (!string.IsNullOrWhiteSpace(request.season))
            {
                query.Season = int.Parse(request.season);
            }

            if (!string.IsNullOrWhiteSpace(request.tmdbid))
            {
                query.TmdbID = int.Parse(request.tmdbid);
            }

            if (!string.IsNullOrWhiteSpace(request.album))
            {
                query.Album = request.album;
            }
            if (!string.IsNullOrWhiteSpace(request.artist))
            {
                query.Artist = request.artist;
            }
            if (!string.IsNullOrWhiteSpace(request.label))
            {
                query.Label = request.label;
            }
            if (!string.IsNullOrWhiteSpace(request.track))
            {
                query.Track = request.track;
            }
            if (!string.IsNullOrWhiteSpace(request.year))
            {
                query.Year = int.Parse(request.year);
            }
            if (!string.IsNullOrWhiteSpace(request.genre))
            {
                query.Genre = request.genre.Split(',');
            }

            if (!string.IsNullOrWhiteSpace(request.title))
            {
                query.Title = request.title;
            }
            if (!string.IsNullOrWhiteSpace(request.author))
            {
                query.Author = request.author;
            }

            return(query);
        }
示例#3
0
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 3, 5, DayOfWeek.Sunday);
            TimeZoneInfo.TransitionTime endTransition   = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 4, 0, 0), 10, 5, DayOfWeek.Sunday);
            TimeSpan delta = new TimeSpan(1, 0, 0);

            TimeZoneInfo.AdjustmentRule   adjustment  = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1), DateTime.MaxValue.Date, delta, startTransition, endTransition);
            TimeZoneInfo.AdjustmentRule[] adjustments = { adjustment };
            TimeZoneInfo germanyTz = TimeZoneInfo.CreateCustomTimeZone("W. Europe Standard Time", new TimeSpan(1, 0, 0), "(GMT+01:00) W. Europe Standard Time", "W. Europe Standard Time", "W. Europe DST Time", adjustments);

            var releases = new List <ReleaseInfo>();

            var searchString    = query.GetQueryString();
            var searchUrl       = IndexUrl;
            var queryCollection = new NameValueCollection();

            queryCollection.Add("strWebValue", "torrent");
            queryCollection.Add("strWebAction", "search");
            queryCollection.Add("sort", "torrent_added");
            queryCollection.Add("by", "d");
            queryCollection.Add("type", "0");
            queryCollection.Add("do_search", "suchen");
            queryCollection.Add("time", "0");
            queryCollection.Add("details", "title");

            if (!string.IsNullOrWhiteSpace(searchString))
            {
                queryCollection.Add("searchstring", searchString);
            }

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add("dirs" + cat, "1");
            }
            searchUrl += "?" + queryCollection.GetQueryString();
            logger.Error(searchUrl);
            logger.Error(CookieHeader);
            var response = await RequestBytesWithCookies(searchUrl);

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

            try
            {
                CQ  dom  = results;
                var rows = dom["table.torrenttable > tbody > tr"];

                foreach (var row in rows.Skip(1))
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio    = 0.8;
                    release.MinimumSeedTime = 0;
                    var qRow = row.Cq();

                    var qDetailsLink = qRow.Find("a[href^=index.php?strWebValue=torrent&strWebAction=details]").First();
                    release.Title = qDetailsLink.Text();

                    var qCatLink  = qRow.Find("a[href^=index.php?strWebValue=torrent&strWebAction=search&dir=]").First();
                    var qDLLink   = qRow.Find("a[href^=index.php?strWebValue=torrent&strWebAction=download&id=]").First();
                    var qSeeders  = qRow.Find("td.column1:eq(3)");
                    var qLeechers = qRow.Find("td.column2:eq(3)");
                    var qDateStr  = qRow.Find("font:has(a)").First();
                    var qSize     = qRow.Find("td.column2[align=center]").First();

                    var catStr = qCatLink.Attr("href").Split('=')[3].Split('#')[0];
                    release.Category = MapTrackerCatToNewznab(catStr);

                    release.Link     = new Uri(SiteLink + qDLLink.Attr("href"));
                    release.Comments = new Uri(SiteLink + qDetailsLink.Attr("href"));
                    release.Guid     = release.Link;

                    var sizeStr = qSize.Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(qSeeders.Text());
                    release.Peers   = ParseUtil.CoerceInt(qLeechers.Text()) + release.Seeders;

                    var      dateStr      = qDateStr.Text().Trim();
                    var      dateStrParts = dateStr.Split();
                    DateTime dateGerman;
                    if (dateStrParts[0] == "Heute")
                    {
                        dateGerman = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + TimeSpan.Parse(dateStrParts[1]);
                    }
                    else if (dateStrParts[0] == "Gestern")
                    {
                        dateGerman = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + TimeSpan.Parse(dateStrParts[1]) - TimeSpan.FromDays(1);
                    }
                    else
                    {
                        dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStrParts[0] + dateStrParts[1], "dd.MM.yyyyHH:mm", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
                    }

                    DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
                    release.PublishDate = pubDateUtc.ToLocalTime();

                    var grabs = qRow.Find("td:nth-child(7)").Text();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    if (qRow.Find("img[src=\"themes/images/freeleech.png\"]").Length >= 1)
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else if (qRow.Find("img[src=\"themes/images/DL50.png\"]").Length >= 1)
                    {
                        release.DownloadVolumeFactor = 0.5;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    release.UploadVolumeFactor = 1;

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results, ex);
            }

            return(releases);
        }
示例#4
0
        private async Task <List <ReleaseInfo> > ParseUserSearchAsync(TorznabQuery query)
        {
            var releases        = new List <ReleaseInfo>();
            var searchUrl       = BrowseUrl;
            var isSearchAnime   = query.Categories.Any(s => s == TorznabCatType.TVAnime.ID);
            var searchTerm      = FixSearchTerm(query);
            var queryCollection = new NameValueCollection
            {
                { "searchstr", StripSearchString(searchTerm, isSearchAnime) },
                { "order_by", "time" },
                { "order_way", "desc" },
                { "group_results", "1" },
                { "action", "basic" },
                { "searchsubmit", "1" }
            };

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add("filter_cat[" + cat + "]", "1");
            }
            searchUrl += "?" + queryCollection.GetQueryString();
            var results = await RequestStringWithCookies(searchUrl);

            if (results.IsRedirect)
            {
                // re-login
                await ApplyConfiguration(null);

                results = await RequestStringWithCookies(searchUrl);
            }

            try
            {
                const string      rowsSelector         = "table.torrent_table > tbody > tr:not(tr.colhead)";
                var               searchResultParser   = new HtmlParser();
                var               searchResultDocument = searchResultParser.ParseDocument(results.Content);
                var               rows          = searchResultDocument.QuerySelectorAll(rowsSelector);
                ICollection <int> groupCategory = null;
                string            groupTitle    = null;
                string            groupYearStr  = null;
                var               categoryStr   = "";
                foreach (var row in rows)
                {
                    try
                    {
                        // ignore sub groups info row, it's just an row with an info about the next section, something like "Dual Áudio" or "Legendado"
                        if (row.QuerySelector(".edition_info") != null)
                        {
                            continue;
                        }
                        var qDetailsLink           = row.QuerySelector("a[href^=\"torrents.php?id=\"]");
                        var title                  = StripSearchString(qDetailsLink.TextContent, false);
                        var seasonEp               = _EpisodeRegex.Match(qDetailsLink.TextContent).Value;
                        ICollection <int> category = null;
                        string            yearStr  = null;
                        if (row.ClassList.Contains("group") || row.ClassList.Contains("torrent")) // group/ungrouped headers
                        {
                            var qCatLink = row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
                            categoryStr = qCatLink.GetAttribute("href").Split('=')[1].Split('&')[0];
                            category    = MapTrackerCatToNewznab(categoryStr);
                            yearStr     = qDetailsLink.NextSibling.TextContent.Trim().TrimStart('[').TrimEnd(']');
                            if (row.ClassList.Contains("group")) // group headers
                            {
                                groupCategory = category;
                                groupTitle    = title;
                                groupYearStr  = yearStr;
                                continue;
                            }
                        }

                        var release = new ReleaseInfo
                        {
                            MinimumRatio    = 1,
                            MinimumSeedTime = 0
                        };
                        var qDlLink    = row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
                        var qSize      = row.QuerySelector("td:nth-last-child(4)");
                        var qGrabs     = row.QuerySelector("td:nth-last-child(3)");
                        var qSeeders   = row.QuerySelector("td:nth-last-child(2)");
                        var qLeechers  = row.QuerySelector("td:nth-last-child(1)");
                        var qFreeLeech = row.QuerySelector("strong[title=\"Free\"]");
                        if (row.ClassList.Contains("group_torrent")) // torrents belonging to a group
                        {
                            release.Description = Regex.Match(qDetailsLink.TextContent, @"\[.*?\]").Value;
                            release.Title       = ParseTitle(groupTitle, seasonEp, groupYearStr, categoryStr);
                            release.Category    = groupCategory;
                        }
                        else if (row.ClassList.Contains("torrent")) // standalone/un grouped torrents
                        {
                            release.Description = row.QuerySelector("div.torrent_info").TextContent;
                            release.Title       = ParseTitle(title, seasonEp, yearStr, categoryStr);
                            release.Category    = category;
                        }

                        release.Description = release.Description.Replace(" / Free", ""); // Remove Free Tag
                        release.Description = release.Description.Replace("Full HD", "1080p");
                        // Handles HDR conflict
                        release.Description = release.Description.Replace("/ HD /", "/ 720p /");
                        release.Description = release.Description.Replace("/ HD]", "/ 720p]");
                        release.Description = release.Description.Replace("4K", "2160p");
                        release.Description = release.Description.Replace("SD", "480p");
                        release.Description = release.Description.Replace("Dual Áudio", "Dual");
                        // If it ain't nacional there will be the type of the audio / original audio
                        if (!release.Description.Contains("Nacional"))
                        {
                            release.Description = Regex.Replace(
                                release.Description, @"(Dual|Legendado|Dublado) \/ (.*?) \/", "$1 /");
                        }

                        // Adjust the description in order to can be read by Radarr and Sonarr
                        var      cleanDescription = release.Description.Trim().TrimStart('[').TrimEnd(']');
                        string[] titleElements;

                        //Formats the title so it can be parsed later
                        var stringSeparators = new[]
                        {
                            " / "
                        };
                        titleElements = cleanDescription.Split(stringSeparators, StringSplitOptions.None);
                        // release.Title += string.Join(" ", titleElements);
                        release.Title = release.Title.Trim();
                        if (titleElements.Length < 6)
                        {
                            // Usually non movies / series could have less than 6 elements, eg: Books.
                            release.Title += " " + string.Join(" ", titleElements);
                        }
                        else
                        {
                            release.Title += " " + titleElements[5] + " " + titleElements[3] + " " + titleElements[1] + " " +
                                             titleElements[2] + " " + titleElements[4] + " " + string.Join(
                                " ", titleElements.Skip(6));
                        }

                        // This tracker does not provide an publish date to search terms (only on last 24h page)
                        release.PublishDate = DateTime.Today;

                        // check for previously stripped search terms
                        if (!query.IsImdbQuery && !query.MatchQueryStringAND(release.Title, null, searchTerm))
                        {
                            continue;
                        }
                        var size = qSize.TextContent;
                        release.Size                 = ReleaseInfo.GetBytes(size);
                        release.Link                 = new Uri(SiteLink + qDlLink.GetAttribute("href"));
                        release.Comments             = new Uri(SiteLink + qDetailsLink.GetAttribute("href"));
                        release.Guid                 = release.Link;
                        release.Grabs                = ParseUtil.CoerceLong(qGrabs.TextContent);
                        release.Seeders              = ParseUtil.CoerceInt(qSeeders.TextContent);
                        release.Peers                = ParseUtil.CoerceInt(qLeechers.TextContent) + release.Seeders;
                        release.DownloadVolumeFactor = qFreeLeech != null ? 0 : 1;
                        release.UploadVolumeFactor   = 1;
                        releases.Add(release);
                    }
                    catch (Exception ex)
                    {
                        logger.Error($"{ID}: Error while parsing row '{row.OuterHtml}': {ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

            return(releases);
        }
示例#5
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 Rows = SearchResultDocument.QuerySelectorAll(Search.Rows.Selector);
                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":
                                    release.Link = resolvePath(value);
                                    break;

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

                                case "comments":
                                    release.Comments = resolvePath(value);
                                    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));
                            }
                        }

                        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);
        }
示例#6
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();

            // the order of the params is important!
            var qc = new List <string>();

            var catList = MapTorznabCapsToTrackers(query);

            foreach (var cat in catList)
            {
                qc.Add(cat);
            }

            if (query.IsImdbQuery)
            {
                qc.Add("deep");
                qc.Add("q");
                qc.Add(query.ImdbID);
            }
            else
            {
                qc.Add("q");
                qc.Add(WebUtilityHelpers.UrlEncode(query.GetQueryString(), Encoding));
            }

            var searchUrl = SearchUrl + string.Join("/", qc);
            var response  = await RequestWithCookiesAndRetryAsync(searchUrl);

            if (!response.ContentString.Contains("/logout.php")) // re-login
            {
                await DoLogin();

                response = await RequestWithCookiesAndRetryAsync(searchUrl);
            }

            try
            {
                var parser = new HtmlParser();
                var dom    = parser.ParseDocument(response.ContentString);
                var rows   = dom.QuerySelectorAll("div.boxContent > table > tbody > tr");

                foreach (var row in rows)
                {
                    var cells = row.QuerySelectorAll("td");

                    var title    = row.QuerySelector("td[class='lft'] > div > a").TextContent.Trim();
                    var link     = new Uri(SiteLink + row.QuerySelector("img[title='Download']").ParentElement.GetAttribute("href").TrimStart('/'));
                    var comments = new Uri(SiteLink + row.QuerySelector("td[class='lft'] > div > a").GetAttribute("href").TrimStart('/'));
                    var size     = ReleaseInfo.GetBytes(cells[5].TextContent);
                    var grabs    = ParseUtil.CoerceInt(cells[6].TextContent);
                    var seeders  = ParseUtil.CoerceInt(cells[7].TextContent);
                    var leechers = ParseUtil.CoerceInt(cells[8].TextContent);

                    var pubDateStr  = row.QuerySelector("span[class^='elapsedDate']").GetAttribute("title").Replace(" at", "");
                    var publishDate = DateTime.ParseExact(pubDateStr, "dddd, MMMM d, yyyy h:mmtt", CultureInfo.InvariantCulture);

                    var cat = row.QuerySelector("a").GetAttribute("href").Split('/').Last();
                    var downloadVolumeFactor = row.QuerySelector("span:contains(\"[Freeleech]\")") != null ? 0 : 1;

                    var release = new ReleaseInfo
                    {
                        Title                = title,
                        Link                 = link,
                        Guid                 = link,
                        Comments             = comments,
                        PublishDate          = publishDate,
                        Category             = MapTrackerCatToNewznab(cat),
                        Size                 = size,
                        Grabs                = grabs,
                        Seeders              = seeders,
                        Peers                = seeders + leechers,
                        MinimumRatio         = 1,
                        MinimumSeedTime      = 172800, // 48 hours
                        DownloadVolumeFactor = downloadVolumeFactor,
                        UploadVolumeFactor   = 1
                    };

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(response.ContentString, ex);
            }
            return(releases);
        }
示例#7
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();

            var searchString = query.GetQueryString();

            // if the search string is empty use the "last 24h torrents" view
            if (string.IsNullOrWhiteSpace(searchString))
            {
                var results = await RequestStringWithCookies(TodayUrl);

                try
                {
                    string RowsSelector = "table.torrent_table > tbody > tr:not(tr.colhead)";

                    var SearchResultParser   = new HtmlParser();
                    var SearchResultDocument = SearchResultParser.Parse(results.Content);
                    var Rows = SearchResultDocument.QuerySelectorAll(RowsSelector);
                    foreach (var Row in Rows)
                    {
                        try
                        {
                            var release = new ReleaseInfo();

                            release.MinimumRatio    = 1;
                            release.MinimumSeedTime = 0;

                            var qDetailsLink = Row.QuerySelector("a.BJinfoBox");
                            var qTitle       = qDetailsLink.QuerySelector("font");
                            release.Title = qTitle.TextContent;

                            var qBJinfoBox = qDetailsLink.QuerySelector("span");
                            var qCatLink   = Row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
                            var qDLLink    = Row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
                            var qSeeders   = Row.QuerySelector("td:nth-child(4)");
                            var qLeechers  = Row.QuerySelector("td:nth-child(5)");
                            var qFreeLeech = Row.QuerySelector("font[color=\"green\"]:contains(Free)");

                            release.Description = "";
                            foreach (var Child in qBJinfoBox.ChildNodes)
                            {
                                var type = Child.NodeType;
                                if (type != NodeType.Text)
                                {
                                    continue;
                                }

                                var line = Child.TextContent;
                                if (line.StartsWith("Tamanho:"))
                                {
                                    string Size = line.Substring("Tamanho: ".Length);;
                                    release.Size = ReleaseInfo.GetBytes(Size);
                                }
                                else if (line.StartsWith("Lançado em: "))
                                {
                                    string PublishDateStr = line.Substring("Lançado em: ".Length).Replace("às ", "");
                                    PublishDateStr += " +0";
                                    var PublishDate = DateTime.SpecifyKind(DateTime.ParseExact(PublishDateStr, "dd/MM/yyyy HH:mm z", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
                                    release.PublishDate = PublishDate.ToLocalTime();
                                }
                                else
                                {
                                    release.Description += line + "\n";
                                }
                            }

                            var catStr = qCatLink.GetAttribute("href").Split('=')[1];
                            release.Category = MapTrackerCatToNewznab(catStr);

                            release.Link     = new Uri(SiteLink + qDLLink.GetAttribute("href"));
                            release.Comments = new Uri(SiteLink + qDetailsLink.GetAttribute("href"));
                            release.Guid     = release.Link;

                            release.Seeders = ParseUtil.CoerceInt(qSeeders.TextContent);
                            release.Peers   = ParseUtil.CoerceInt(qLeechers.TextContent) + release.Seeders;

                            if (qFreeLeech != null)
                            {
                                release.DownloadVolumeFactor = 0;
                            }
                            else
                            {
                                release.DownloadVolumeFactor = 1;
                            }

                            release.UploadVolumeFactor = 1;

                            releases.Add(release);
                        }
                        catch (Exception ex)
                        {
                            logger.Error(string.Format("{0}: Error while parsing row '{1}': {2}", ID, Row.OuterHtml, ex.Message));
                        }
                    }
                }
                catch (Exception ex)
                {
                    OnParseError(results.Content, ex);
                }
            }
            else // use search
            {
                var searchUrl = BrowseUrl;

                var queryCollection = new NameValueCollection();
                queryCollection.Add("searchstr", StripSearchString(searchString));
                queryCollection.Add("order_by", "time");
                queryCollection.Add("order_way", "desc");
                queryCollection.Add("group_results", "1");
                queryCollection.Add("action", "basic");
                queryCollection.Add("searchsubmit", "1");

                foreach (var cat in MapTorznabCapsToTrackers(query))
                {
                    queryCollection.Add("filter_cat[" + cat + "]", "1");
                }

                searchUrl += "?" + queryCollection.GetQueryString();

                var results = await RequestStringWithCookies(searchUrl);

                try
                {
                    string RowsSelector = "table.torrent_table > tbody > tr:not(tr.colhead)";

                    var SearchResultParser   = new HtmlParser();
                    var SearchResultDocument = SearchResultParser.Parse(results.Content);
                    var Rows = SearchResultDocument.QuerySelectorAll(RowsSelector);

                    ICollection <int>   GroupCategory    = null;
                    string              GroupTitle       = null;
                    string              GroupYearStr     = null;
                    Nullable <DateTime> GroupPublishDate = null;

                    foreach (var Row in Rows)
                    {
                        try
                        {
                            var                 qDetailsLink    = Row.QuerySelector("a[href^=\"torrents.php?id=\"]");
                            string              Title           = qDetailsLink.TextContent;
                            ICollection <int>   Category        = null;
                            string              YearStr         = null;
                            Nullable <DateTime> YearPublishDate = null;

                            if (Row.ClassList.Contains("group") || Row.ClassList.Contains("torrent")) // group/ungrouped headers
                            {
                                var    qCatLink    = Row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
                                string CategoryStr = qCatLink.GetAttribute("href").Split('=')[1].Split('&')[0];
                                Category        = MapTrackerCatToNewznab(CategoryStr);
                                YearStr         = qDetailsLink.NextSibling.TextContent.Trim().TrimStart('[').TrimEnd(']');
                                YearPublishDate = DateTime.SpecifyKind(DateTime.ParseExact(YearStr, "yyyy", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);

                                if (Row.ClassList.Contains("group")) // group headers
                                {
                                    GroupCategory    = Category;
                                    GroupTitle       = Title;
                                    GroupYearStr     = YearStr;
                                    GroupPublishDate = YearPublishDate;
                                    continue;
                                }
                            }

                            var release = new ReleaseInfo();

                            release.MinimumRatio    = 1;
                            release.MinimumSeedTime = 0;

                            var qDLLink    = Row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
                            var qSize      = Row.QuerySelector("td:nth-last-child(4)");
                            var qSeeders   = Row.QuerySelector("td:nth-last-child(3)");
                            var qLeechers  = Row.QuerySelector("td:nth-last-child(2)");
                            var qFreeLeech = Row.QuerySelector("strong[title=\"Free\"]");

                            if (Row.ClassList.Contains("group_torrent")) // torrents belonging to a group
                            {
                                release.Description = qDetailsLink.TextContent;
                                release.Title       = GroupTitle + " " + GroupYearStr;
                                release.PublishDate = GroupPublishDate.Value;
                                release.Category    = GroupCategory;
                            }
                            else if (Row.ClassList.Contains("torrent")) // standalone/un grouped torrents
                            {
                                var qDescription = Row.QuerySelector("div.torrent_info");
                                release.Description = qDescription.TextContent;
                                release.Title       = Title + " " + YearStr;
                                release.PublishDate = YearPublishDate.Value;
                                release.Category    = Category;
                            }

                            release.Description = release.Description.Replace(" / Free", ""); // Remove Free Tag

                            release.Description = release.Description.Replace("Full HD", "1080p");
                            release.Description = release.Description.Replace("/ HD / ", "/ 720p /");
                            release.Description = release.Description.Replace(" / HD]", " / 720p]");
                            release.Description = release.Description.Replace("4K", "2160p");

                            int nBarra = release.Title.IndexOf("[");
                            if (nBarra != -1)
                            {
                                release.Title = release.Title.Substring(nBarra + 1);
                                release.Title = release.Title.Replace("]", "");
                            }

                            release.Title += " " + release.Description; // add year and Description to the release Title to add some meaning to it

                            // check for previously stripped search terms
                            if (!query.MatchQueryStringAND(release.Title))
                            {
                                continue;
                            }

                            var Size = qSize.TextContent;
                            release.Size = ReleaseInfo.GetBytes(Size);

                            release.Link     = new Uri(SiteLink + qDLLink.GetAttribute("href"));
                            release.Comments = new Uri(SiteLink + qDetailsLink.GetAttribute("href"));
                            release.Guid     = release.Link;

                            release.Seeders = ParseUtil.CoerceInt(qSeeders.TextContent);
                            release.Peers   = ParseUtil.CoerceInt(qLeechers.TextContent) + release.Seeders;

                            if (qFreeLeech != null)
                            {
                                release.DownloadVolumeFactor = 0;
                            }
                            else
                            {
                                release.DownloadVolumeFactor = 1;
                            }

                            release.UploadVolumeFactor = 1;

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

            return(releases);
        }
示例#8
0
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 3, 5, DayOfWeek.Sunday);
            TimeZoneInfo.TransitionTime endTransition   = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 4, 0, 0), 10, 5, DayOfWeek.Sunday);
            TimeSpan delta = new TimeSpan(1, 0, 0);

            TimeZoneInfo.AdjustmentRule   adjustment  = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1), DateTime.MaxValue.Date, delta, startTransition, endTransition);
            TimeZoneInfo.AdjustmentRule[] adjustments = { adjustment };
            TimeZoneInfo romaniaTz = TimeZoneInfo.CreateCustomTimeZone("Romania Time", new TimeSpan(2, 0, 0), "(GMT+02:00) Romania Time", "Romania Time", "Romania Daylight Time", adjustments);

            var    releases = new List <ReleaseInfo>();
            string episodeSearchUrl;

            if (string.IsNullOrEmpty(query.GetQueryString()))
            {
                episodeSearchUrl = SearchUrl;
            }
            else
            {
                episodeSearchUrl = $"{SearchUrl}?search={HttpUtility.UrlEncode(query.GetQueryString())}&cat=0";
            }

            var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl);

            try
            {
                CQ dom = results.Content;

                var rows = dom["#highlight > tbody > tr"];

                foreach (var row in rows.Skip(1))
                {
                    var release = new ReleaseInfo();

                    var qRow  = row.Cq();
                    var qLink = qRow.Find("a.torrent_name_link").First();

                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 172800;
                    release.Title           = qLink.Attr("title");
                    if (!query.MatchQueryStringAND(release.Title))
                    {
                        continue;
                    }

                    release.Description = release.Title;
                    release.Guid        = new Uri(SiteLink + qLink.Attr("href").TrimStart('/'));
                    release.Comments    = release.Guid;
                    release.Link        = new Uri(SiteLink + qRow.Find("td.table_links > a").First().Attr("href").TrimStart('/'));
                    release.Category    = TvCategoryParser.ParseTvShowQuality(release.Title);

                    release.Seeders = ParseUtil.CoerceInt(qRow.Find("td.table_seeders").Text().Trim());
                    release.Peers   = ParseUtil.CoerceInt(qRow.Find("td.table_leechers").Text().Trim()) + release.Seeders;

                    var sizeStr = qRow.Find("td.table_size")[0].Cq().Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    DateTime pubDateRomania;
                    var      dateString = qRow.Find("td.table_added").Text().Trim();
                    if (dateString.StartsWith("Today "))
                    {
                        pubDateRomania = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + TimeSpan.Parse(dateString.Split(' ')[1]);
                    }
                    else if (dateString.StartsWith("Yesterday "))
                    {
                        pubDateRomania = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + TimeSpan.Parse(dateString.Split(' ')[1]) - TimeSpan.FromDays(1);
                    }
                    else
                    {
                        pubDateRomania = DateTime.SpecifyKind(DateTime.ParseExact(dateString, "d-MMM-yyyy HH:mm:ss", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
                    }

                    DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(pubDateRomania, romaniaTz);
                    release.PublishDate = pubDateUtc.ToLocalTime();

                    var grabs = row.Cq().Find("td.table_snatch").Get(0).FirstChild.ToString();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    if (row.Cq().Find("img[alt=\"100% Free\"]").Any())
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else if (row.Cq().Find("img[alt=\"50% Free\"]").Any())
                    {
                        release.DownloadVolumeFactor = 0.5;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    release.UploadVolumeFactor = 1;

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

            return(releases);
        }
示例#9
0
文件: BB.cs 项目: waknaudt/Jackett
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            List <ReleaseInfo> releases      = new List <ReleaseInfo>();
            List <string>      searchStrings = new List <string>(new string[] { query.GetQueryString() });

            if (string.IsNullOrEmpty(query.Episode) && (query.Season > 0))
            {
                // Tracker naming rules: If query is for a whole season, "Season #" instead of "S##".
                searchStrings.Add((query.SanitizedSearchTerm + " " + string.Format("\"Season {0}\"", query.Season)).Trim());
            }

            List <string> categories   = MapTorznabCapsToTrackers(query);
            List <string> request_urls = new List <string>();

            foreach (var searchString in searchStrings)
            {
                var queryCollection = new NameValueCollection();
                queryCollection.Add("action", "basic");

                if (!string.IsNullOrWhiteSpace(searchString))
                {
                    queryCollection.Add("searchstr", searchString);
                }

                foreach (var cat in categories)
                {
                    queryCollection.Add("filter_cat[" + cat + "]", "1");
                }

                request_urls.Add(SearchUrl + queryCollection.GetQueryString());
            }
            IEnumerable <Task <WebClientStringResult> > downloadTasksQuery =
                from url in request_urls select RequestStringWithCookiesAndRetry(url);

            WebClientStringResult[] responses = await Task.WhenAll(downloadTasksQuery.ToArray());

            for (int i = 0; i < searchStrings.Count(); i++)
            {
                var results = responses[i];
                // Occasionally the cookies become invalid, login again if that happens
                if (results.IsRedirect)
                {
                    await ApplyConfiguration(null);

                    results = await RequestStringWithCookiesAndRetry(request_urls[i]);
                }
                try
                {
                    CQ  dom  = results.Content;
                    var rows = dom["#torrent_table > tbody > tr.torrent"];
                    foreach (var row in rows)
                    {
                        CQ  qRow    = row.Cq();
                        var release = new ReleaseInfo();

                        release.MinimumRatio    = 1;
                        release.MinimumSeedTime = 172800;

                        var catStr = row.ChildElements.ElementAt(0).FirstElementChild.GetAttribute("href").Split(new char[] { '[', ']' })[1];
                        release.Category = MapTrackerCatToNewznab(catStr);

                        var qLink   = row.ChildElements.ElementAt(1).Cq().Children("a")[0].Cq();
                        var linkStr = qLink.Attr("href");
                        release.Comments = new Uri(BaseUrl + "/" + linkStr);
                        release.Guid     = release.Comments;

                        var qDownload = row.ChildElements.ElementAt(1).Cq().Find("a[title='Download']")[0].Cq();
                        release.Link = new Uri(BaseUrl + "/" + qDownload.Attr("href"));

                        var dateStr = row.ChildElements.ElementAt(3).Cq().Text().Trim().Replace(" and", "");
                        release.PublishDate = DateTimeUtil.FromTimeAgo(dateStr);

                        var sizeStr = row.ChildElements.ElementAt(4).Cq().Text();
                        release.Size = ReleaseInfo.GetBytes(sizeStr);

                        release.Files   = ParseUtil.CoerceInt(row.ChildElements.ElementAt(2).Cq().Text().Trim());
                        release.Grabs   = ParseUtil.CoerceInt(row.ChildElements.ElementAt(6).Cq().Text().Trim());
                        release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(7).Cq().Text().Trim());
                        release.Peers   = ParseUtil.CoerceInt(row.ChildElements.ElementAt(8).Cq().Text().Trim()) + release.Seeders;

                        var grabs = qRow.Find("td:nth-child(6)").Text();
                        release.Grabs = ParseUtil.CoerceInt(grabs);

                        if (qRow.Find("strong:contains(\"Freeleech!\")").Length >= 1)
                        {
                            release.DownloadVolumeFactor = 0;
                        }
                        else
                        {
                            release.DownloadVolumeFactor = 1;
                        }

                        release.UploadVolumeFactor = 1;

                        var title = qRow.Find("td:nth-child(2)");
                        title.Find("span, strong, div, br").Remove();

                        release.Title = ParseUtil.NormalizeMultiSpaces(title.Text().Replace(" - ]", "]"));

                        if (catStr == "10") //change "Season #" to "S##" for TV shows
                        {
                            release.Title = Regex.Replace(release.Title, @"Season (\d+)",
                                                          m => string.Format("S{0:00}", Int32.Parse(m.Groups[1].Value)));
                        }

                        releases.Add(release);
                    }
                }
                catch (Exception ex)
                {
                    OnParseError(results.Content, ex);
                }
            }
            return(releases);
        }
示例#10
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();

            var qc = new NameValueCollection
            {
                { "incldead", "1" }
            };

            if (query.IsImdbQuery)
            {
                qc.Add("search", query.ImdbID);
                qc.Add("sc", "2"); // search in description
            }
            else
            {
                qc.Add("search", query.GetQueryString());
                qc.Add("sc", "1"); // search in title
            }

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                qc.Add("c" + cat, "1");
            }

            var searchUrl = SearchUrl + "?" + qc.GetQueryString();
            var response  = await RequestWithCookiesAndRetryAsync(searchUrl, referer : SearchUrl);

            if (response.IsRedirect) // re-login
            {
                await ApplyConfiguration(null);

                response = await RequestWithCookiesAndRetryAsync(searchUrl, referer : SearchUrl);
            }

            try
            {
                var parser = new HtmlParser();
                var dom    = parser.ParseDocument(response.ContentString);
                var rows   = dom.QuerySelectorAll("table > tbody:has(tr > td.colhead) > tr:not(:has(td.colhead))");
                foreach (var row in rows)
                {
                    var release = new ReleaseInfo();
                    var link    = row.QuerySelector("td:nth-of-type(2) a:nth-of-type(2)");
                    release.Guid     = new Uri(SiteLink + link.GetAttribute("href"));
                    release.Comments = release.Guid;
                    release.Title    = link.GetAttribute("title");

                    // There isn't a title attribute if the release name isn't truncated.
                    if (string.IsNullOrWhiteSpace(release.Title))
                    {
                        release.Title = link.FirstChild.TextContent.Trim();
                    }
                    release.Description = release.Title;

                    // If we search an get no results, we still get a table just with no info.
                    if (string.IsNullOrWhiteSpace(release.Title))
                    {
                        break;
                    }

                    // Check if the release has been assigned a category
                    var qCat = row.QuerySelector("td:nth-of-type(1) a");
                    if (qCat != null)
                    {
                        var cat = qCat.GetAttribute("href").Substring(15);
                        release.Category = MapTrackerCatToNewznab(cat);
                    }

                    var qLink = row.QuerySelector("td:nth-of-type(2) a");
                    release.Link = new Uri(SiteLink + qLink.GetAttribute("href"));
                    var added = row.QuerySelector("td:nth-of-type(5)").TextContent.Trim();
                    release.PublishDate = DateTime.ParseExact(added, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);
                    var sizeStr = row.QuerySelector("td:nth-of-type(7)").TextContent.Trim();
                    release.Size    = ReleaseInfo.GetBytes(sizeStr);
                    release.Seeders = ParseUtil.CoerceInt(row.QuerySelector("td:nth-of-type(9)").TextContent.Trim());
                    release.Peers   = ParseUtil.CoerceInt(row.QuerySelector("td:nth-of-type(10)").TextContent.Trim()) +
                                      release.Seeders;
                    var files = row.QuerySelector("td:nth-child(3)").TextContent;
                    release.Files = ParseUtil.CoerceInt(files);
                    var grabs = row.QuerySelector("td:nth-child(8)").TextContent;
                    if (grabs != "----")
                    {
                        release.Grabs = ParseUtil.CoerceInt(grabs);
                    }
                    release.DownloadVolumeFactor =
                        row.QuerySelector("font[color=\"green\"]:contains(\"F\"):contains(\"L\")") != null ? 0 : 1;
                    release.UploadVolumeFactor = 1;
                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(response.ContentString, ex);
            }

            return(releases);
        }
示例#11
0
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases        = new List <ReleaseInfo>();
            var queryUrl        = SearchUrl;
            var queryCollection = new NameValueCollection();
            var cats            = MapTorznabCapsToTrackers(query);
            var tags            = string.Empty;
            var catGroups       = new List <string>();

            foreach (var cat in cats)
            {
                //"cat[]=7&tags=x264"
                var cSplit = cat.Split('&');
                if (cSplit.Length > 0)
                {
                    var gsplit = cSplit[0].Split('=');
                    if (gsplit.Length > 1)
                    {
                        catGroups.Add(gsplit[1]);
                    }
                }

                if (cSplit.Length > 1)
                {
                    var gsplit = cSplit[1].Split('=');
                    if (gsplit.Length > 1)
                    {
                        if (tags != string.Empty)
                        {
                            tags += ",";
                        }
                        tags += gsplit[1];
                    }
                }
            }

            if (catGroups.Distinct().Count() == 1)
            {
                queryCollection.Add("cat[]", catGroups.First());
            }

            if (!string.IsNullOrWhiteSpace(query.GetQueryString()))
            {
                queryCollection.Add("st", "1");
                queryCollection.Add("search", query.GetQueryString());
            }

            // Do not include too many tags as it'll mess with their servers.
            if (tags.Split(',').Length < 7)
            {
                queryCollection.Add("tags", tags);
                if (!string.IsNullOrWhiteSpace(tags))
                {
                    // if tags are specified match any
                    queryCollection.Add("tf", "any");
                }
                else
                {
                    // if no tags are specified match all, with any we get random results
                    queryCollection.Add("tf", "all");
                }
            }

            if (queryCollection.Count > 0)
            {
                queryUrl += "?" + queryCollection.GetQueryString();
            }

            var response = await RequestStringWithCookiesAndRetry(queryUrl);

            if (response.IsRedirect)
            {
                await ApplyConfiguration(null);

                response = await RequestStringWithCookiesAndRetry(queryUrl);
            }

            try
            {
                CQ  dom  = response.Content;
                var rows = dom["table > tbody > tr.browse"];
                foreach (var row in rows)
                {
                    CQ  qRow    = row.Cq();
                    var release = new ReleaseInfo();

                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 172800;

                    var qLink = row.ChildElements.ElementAt(1).Cq().Find("a").First();
                    release.Title = qLink.Text().Trim();
                    if (qLink.Find("span").Count() == 1 && release.Title.StartsWith("NEW! |"))
                    {
                        release.Title = release.Title.Substring(6).Trim();
                    }

                    release.Comments = new Uri(SiteLink + qLink.Attr("href"));
                    release.Guid     = release.Comments;

                    var qDownload = row.ChildElements.ElementAt(2).Cq().Find("a").First();
                    release.Link = new Uri(SiteLink + qDownload.Attr("href"));

                    var dateStr = row.ChildElements.ElementAt(5).InnerHTML.Replace("<br>", " ");
                    release.PublishDate = DateTimeUtil.FromTimeAgo(dateStr);

                    var sizeStr = row.ChildElements.ElementAt(7).Cq().Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(9).InnerText);
                    release.Peers   = ParseUtil.CoerceInt(row.ChildElements.ElementAt(10).InnerText) + release.Seeders;

                    var cat = row.ChildElements.ElementAt(0).ChildElements.ElementAt(0).GetAttribute("href").Replace("browse.php?", string.Empty);
                    release.Category = MapTrackerCatToNewznab(cat);

                    var files = qRow.Find("td:nth-child(4)").Text();
                    release.Files = ParseUtil.CoerceInt(files);

                    var grabs = qRow.Find("td:nth-child(9)").Text();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    release.DownloadVolumeFactor = 0; // ratioless
                    release.UploadVolumeFactor   = 1;

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(response.Content, ex);
            }
            return(releases);
        }
示例#12
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 RequestStringWithCookies(searchUrl);

            var results = response.Content;

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

                // check if we need to login again
                var loginNeeded = CheckIfLoginIsNeeded(response, SearchResultDocument);
                if (loginNeeded)
                {
                    logger.Info(string.Format("CardigannIndexer ({0}): Relogin required", ID));
                    await DoLogin();
                    await TestLogin();

                    response = await RequestStringWithCookies(searchUrl);

                    results = results = response.Content;
                    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 = null;
                            try
                            {
                                value = handleSelector(Field.Value, Row);
                                value = ParseUtil.NormalizeSpace(value);
                                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;
                                    release.Comments = url;
                                    if (release.Guid == null)
                                    {
                                        release.Guid = url;
                                    }
                                    break;

                                case "comments":
                                    var CommentsUrl = resolvePath(value);
                                    if (release.Comments == null)
                                    {
                                        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;

                                case "imdb":
                                    Regex IMDBRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
                                    var   IMDBMatch = IMDBRegEx.Match(value);
                                    var   IMDBId    = IMDBMatch.Groups[1].Value;
                                    release.Imdb = ParseUtil.CoerceLong(IMDBId);
                                    break;

                                default:
                                    break;
                                }
                            }
                            catch (Exception ex)
                            {
                                if (OptionalFileds.Contains(Field.Key))
                                {
                                    continue;
                                }
                                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 (release.PublishDate == null && DateHeaders != null)
                        {
                            var    PrevRow = Row.PreviousElementSibling;
                            string value   = null;
                            while (PrevRow != null)
                            {
                                try
                                {
                                    value = handleSelector(DateHeaders, PrevRow);
                                    break;
                                }
                                catch (Exception)
                                {
                                    // 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);
        }
示例#13
0
文件: T411.cs 项目: mordae/Jackett
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();
            // API doesn't support getting the latest torrents, searching for the empty string will cause an error and all torrents returned
            var searchUrl = SearchUrl + HttpUtility.UrlEncode(query.SanitizedSearchTerm).Replace("+", "%20");

            searchUrl += "?offset=0&limit=200&cat=" + GetCategoryFromSubCat(query.Categories.FirstOrDefault()).Key;

            // handle special term search for tvsearch
            var queryStringOverride = query.SanitizedSearchTerm;

            switch (query.QueryType)
            {
            case "tvsearch":
                // T411 make the difference beetween Animation Movies and TV Animation Series, while Torznab does not.
                // So here we take LastOrDefault from the category ids, so if the query specify an animation tv serie, we select the correct id.
                searchUrl += "&subcat=" + GetCategoryFromSubCat(query.Categories.FirstOrDefault()).Value.LastOrDefault();
                if (query.Season >= 1 && query.Season <= 30)
                {
                    var seasonTermValue = 967 + query.Season;
                    searchUrl           += "&term[45][]=" + seasonTermValue;
                    queryStringOverride += " " + query.Season;
                }

                if (query.Episode != null)
                {
                    int episodeInt;
                    int episodeCategoryOffset = 936;
                    ParseUtil.TryCoerceInt(query.Episode, out episodeInt);
                    if (episodeInt >= 1 && episodeInt <= 8)
                    {
                        episodeCategoryOffset = 936;
                    }
                    else if (episodeInt >= 9 && episodeInt <= 30)
                    {
                        episodeCategoryOffset = 937;
                    }
                    else if (episodeInt >= 31)
                    {
                        episodeCategoryOffset = 1057;
                    }
                    searchUrl           += "&term[46][]=" + (episodeCategoryOffset + episodeInt);
                    queryStringOverride += " " + query.Episode;
                }
                break;

            case "movie":
                // T411 make the difference beetween Animation Movies and TV Animation Series, while Torznab does not.
                // So here we take FirstOrDefault from the category ids, so if the query specify an animation movie, we select the correct id.
                searchUrl += "&subcat=" + GetCategoryFromSubCat(query.Categories.FirstOrDefault()).Value.FirstOrDefault();
                break;
            }

            var headers = new Dictionary <string, string>();

            headers.Add("Authorization", await GetAuthToken());

            var response = await RequestStringWithCookies(searchUrl, null, null, headers);

            var results = response.Content;

            var jsonStart  = results.IndexOf('{');
            var jsonLength = results.Length - jsonStart;
            var jsonResult = JObject.Parse(results.Substring(jsonStart));

            try
            {
                var items = (JArray)jsonResult["torrents"];
                foreach (var item in items)
                {
                    if (item.GetType() == typeof(JValue))
                    {
                        logger.Debug(string.Format("{0}: skipping torrent ID {1} (pending release without details)", ID, item.ToString()));
                        continue;
                    }
                    var release = new ReleaseInfo();

                    release.MinimumRatio         = 1;
                    release.MinimumSeedTime      = 172800;
                    release.DownloadVolumeFactor = 0;
                    release.DownloadVolumeFactor = 1;
                    var torrentId = (string)item["id"];
                    release.Link  = new Uri(DownloadUrl + torrentId);
                    release.Title = (string)item["name"];

                    if ((query.ImdbID == null || !TorznabCaps.SupportsImdbSearch) && !query.MatchQueryStringAND(release.Title, null, queryStringOverride))
                    {
                        continue;
                    }

                    if ((string)item["isVerified"] == "1")
                    {
                        release.Description = "Verified";
                    }
                    release.Comments = new Uri(CommentsUrl + (string)item["rewritename"]);
                    release.Guid     = release.Comments;

                    var dateUtc = DateTime.ParseExact((string)item["added"], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
                    release.PublishDate = DateTime.SpecifyKind(dateUtc, DateTimeKind.Utc).ToLocalTime();

                    release.Seeders  = ParseUtil.CoerceInt((string)item["seeders"]);
                    release.Peers    = ParseUtil.CoerceInt((string)item["leechers"]) + release.Seeders;
                    release.Size     = ParseUtil.CoerceLong((string)item["size"]);
                    release.Category = MapTrackerCatToNewznab((string)item["category"]);
                    release.Grabs    = ParseUtil.CoerceLong((string)item["times_completed"]);

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results, ex);
            }
            return(releases);
        }
示例#14
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();
            var qc       = new NameValueCollection
            {
                { "cat", MapTorznabCapsToTrackers(query, true).FirstIfSingleOrDefault("0") }
            };
            var results = new List <WebResult>();
            var search  = new UriBuilder(SearchUrl);

            if (query.IsImdbQuery)
            {
                qc.Add("search", query.ImdbID);
                qc.Add("options", "4"); //Search URL field for IMDB link
                search.Query = qc.GetQueryString();
                results.Add(await RequestWithCookiesAndRetryAsync(search.ToString()));
                qc["Options"] = "1"; //Search Title and Description
                search.Query  = qc.GetQueryString();
                results.Add(await RequestWithCookiesAndRetryAsync(search.ToString()));
            }
            else
            {
                //Site handles empty string on search param. No need to check for IsNullOrEmpty()
                qc.Add("search", query.GetQueryString());
                qc.Add("options", "0"); //Search Title Only
                search.Query = qc.GetQueryString();
                results.Add(await RequestWithCookiesAndRetryAsync(search.ToString()));
            }

            var parser = new HtmlParser();

            foreach (var result in results)
            {
                try
                {
                    var dom = parser.ParseDocument(result.ContentString);
                    foreach (var child in dom.QuerySelectorAll("#needseed"))
                    {
                        child.Remove();
                    }
                    var table = dom.QuerySelector("table[align=center] + br + table > tbody");
                    if (table == null) // No results, so skip this search
                    {
                        continue;
                    }
                    foreach (var row in table.Children.Skip(1))
                    {
                        var release = new ReleaseInfo();
                        var qLink   = row.Children[2].QuerySelector("a");
                        release.MinimumRatio    = 1;
                        release.MinimumSeedTime = 172800; // 48 hours
                        release.Title           = qLink.GetAttribute("title");
                        var detailsLink = new Uri(qLink.GetAttribute("href"));
                        //Skip irrelevant and duplicate entries
                        if (!query.MatchQueryStringAND(release.Title) || releases.Any(r => r.Guid == detailsLink))
                        {
                            continue;
                        }
                        release.Files    = ParseUtil.CoerceLong(row.Children[3].TextContent);
                        release.Grabs    = ParseUtil.CoerceLong(row.Children[7].TextContent);
                        release.Guid     = detailsLink;
                        release.Comments = release.Guid;
                        release.Link     = new Uri(SiteLink + row.QuerySelector("a[href^=\"download.php\"]").GetAttribute("href"));
                        var catUrl   = new Uri(SiteLink + row.Children[1].FirstElementChild.GetAttribute("href"));
                        var catQuery = HttpUtility.ParseQueryString(catUrl.Query);
                        var catNum   = catQuery["cat"];
                        release.Category = MapTrackerCatToNewznab(catNum);

                        var dateString = row.Children[5].TextContent.Trim();
                        var pubDate    = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);
                        release.PublishDate = DateTime.SpecifyKind(pubDate, DateTimeKind.Local);
                        var sizeStr = row.Children[6].TextContent;
                        release.Size    = ReleaseInfo.GetBytes(sizeStr);
                        release.Seeders = ParseUtil.CoerceInt(row.Children[8].TextContent.Trim());
                        release.Peers   = ParseUtil.CoerceInt(row.Children[9].TextContent.Trim()) + release.Seeders;
                        switch (row.GetAttribute("bgcolor"))
                        {
                        case "#DDDDDD":
                            release.DownloadVolumeFactor = 1;
                            release.UploadVolumeFactor   = 2;
                            break;

                        case "#FFFF99":
                            release.DownloadVolumeFactor = 0;
                            release.UploadVolumeFactor   = 1;
                            break;

                        case "#CCFF99":
                            release.DownloadVolumeFactor = 0;
                            release.UploadVolumeFactor   = 2;
                            break;

                        default:
                            release.DownloadVolumeFactor = 1;
                            release.UploadVolumeFactor   = 1;
                            break;
                        }

                        releases.Add(release);
                    }
                }
                catch (Exception ex)
                {
                    OnParseError(result.ContentString, ex);
                }
            }

            return(releases);
        }
示例#15
0
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases     = new List <ReleaseInfo>();
            var searchString = query.GetQueryString();

            // search in normal + gems view
            foreach (var view in new string[] { "0", "1" })
            {
                var queryCollection = new NameValueCollection();

                queryCollection.Add("view", view);
                queryCollection.Add("searchtype", "1");
                queryCollection.Add("incldead", "1");
                if (!string.IsNullOrWhiteSpace(searchString))
                {
                    queryCollection.Add("search", searchString);
                }

                foreach (var cat in MapTorznabCapsToTrackers(query))
                {
                    queryCollection.Add(string.Format("c{0}", cat), "1");
                }

                var searchUrl = SearchUrl + "?" + queryCollection.GetQueryString();

                var results = await RequestStringWithCookiesAndRetry(searchUrl);

                if (results.IsRedirect)
                {
                    // re-login
                    await ApplyConfiguration(null);

                    results = await RequestStringWithCookiesAndRetry(searchUrl);
                }

                try
                {
                    CQ  dom  = results.Content;
                    var rows = dom["#torrentBrowse > table > tbody > tr"];
                    foreach (var row in rows.Skip(1))
                    {
                        var release = new ReleaseInfo();
                        CQ  qRow    = row.Cq();

                        release.MinimumRatio    = 0;
                        release.MinimumSeedTime = 2 * 24 * 60 * 60;

                        var qLink = qRow.Find("a[title][href^=\"details.php?id=\"]");
                        release.Title    = qLink.Attr("title");
                        release.Guid     = new Uri(SiteLink + qLink.Attr("href").TrimStart('/'));
                        release.Comments = release.Guid;

                        qLink        = qRow.Children().ElementAt(3).Cq().Children("a").First();
                        release.Link = new Uri(string.Format("{0}{1}", SiteLink, qLink.Attr("href")));

                        var catUrl = qRow.Children().ElementAt(0).FirstElementChild.Cq().Attr("href");
                        var catNum = catUrl.Split(new char[] { '=', '&' })[2].Replace("c", "");
                        release.Category = MapTrackerCatToNewznab(catNum);

                        var dateString = qRow.Children().ElementAt(6).Cq().Text().Trim();
                        if (dateString.Contains("ago"))
                        {
                            release.PublishDate = DateTimeUtil.FromTimeAgo(dateString);
                        }
                        else
                        {
                            release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);
                        }

                        var sizeStr = qRow.Children().ElementAt(7).Cq().Text().Split(new char[] { '/' })[0];
                        release.Size = ReleaseInfo.GetBytes(sizeStr);

                        release.Seeders = ParseUtil.CoerceInt(qRow.Children().ElementAt(8).Cq().Text().Split(new char[] { '/' })[0].Trim());
                        release.Peers   = ParseUtil.CoerceInt(qRow.Children().ElementAt(8).Cq().Text().Split(new char[] { '/' })[1].Trim()) + release.Seeders;
                        release.Files   = ParseUtil.CoerceLong(qRow.Find("td:nth-child(5)").Text());
                        release.Grabs   = ParseUtil.CoerceLong(qRow.Find("a[href^=\"snatches.php?id=\"]").Text().Split(' ')[0]);

                        release.DownloadVolumeFactor = 0;
                        release.UploadVolumeFactor   = 1;

                        var desc = qRow.Find("td:nth-child(2)");
                        desc.Find("a").Remove();
                        desc.Find("small").Remove(); // Remove release name (if enabled in the user cp)
                        release.Description = desc.Text().Trim(new char[] { '-', ' ' });

                        releases.Add(release);
                    }
                }
                catch (Exception ex)
                {
                    OnParseError(results.Content, ex);
                }
            }

            return(releases);
        }
示例#16
0
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases        = new List <ReleaseInfo>();
            var searchString    = query.GetQueryString();
            var searchUrl       = BrowseUrl;
            var queryCollection = new NameValueCollection();

            if (!string.IsNullOrWhiteSpace(searchString))
            {
                queryCollection.Add("q", searchString);
            }

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add(cat, string.Empty);
            }

            if (queryCollection.Count > 0)
            {
                searchUrl += "?" + queryCollection.GetQueryString();
            }

            var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);

            var results = response.Content;

            try
            {
                CQ dom = results;

                var rows = dom["table.torrents > tbody > tr"];
                foreach (var row in rows.Skip(1))
                {
                    var release    = new ReleaseInfo();
                    var qRow       = row.Cq();
                    var qTitleLink = qRow.Find("a.t_title").First();
                    release.Title = qTitleLink.Text().Trim();

                    // If we search an get no results, we still get a table just with no info.
                    if (string.IsNullOrWhiteSpace(release.Title))
                    {
                        break;
                    }

                    release.Description = release.Title;
                    release.Guid        = new Uri(UseLink + qTitleLink.Attr("href").Substring(1));
                    release.Comments    = release.Guid;

                    var descString = qRow.Find(".t_ctime").Text();
                    var dateString = descString.Split('|').Last().Trim();
                    dateString          = dateString.Split(new string[] { " by " }, StringSplitOptions.None)[0];
                    release.PublishDate = DateTimeUtil.FromTimeAgo(dateString);

                    var qLink = row.ChildElements.ElementAt(3).Cq().Children("a");
                    release.Link = new Uri(UseLink + HttpUtility.UrlEncode(qLink.Attr("href").TrimStart('/')));

                    var sizeStr = row.ChildElements.ElementAt(5).Cq().Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(qRow.Find(".t_seeders").Text().Trim());
                    release.Peers   = ParseUtil.CoerceInt(qRow.Find(".t_leechers").Text().Trim()) + release.Seeders;

                    var cat = row.Cq().Find("td:eq(0) a").First().Attr("href").Substring(1);
                    release.Category = MapTrackerCatToNewznab(cat);

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results, ex);
            }

            return(releases);
        }
示例#17
0
        private async Task <IEnumerable <ReleaseInfo> > GetResults(SearchType searchType, string searchTerm)
        {
            var cleanSearchTerm = HttpUtility.UrlEncode(searchTerm);

            // The result list
            var releases = new List <ReleaseInfo>();

            var queryUrl = searchType == SearchType.Video ? SearchUrl : MusicSearchUrl;

            // Only include the query bit if its required as hopefully the site caches the non query page
            if (!string.IsNullOrWhiteSpace(searchTerm))
            {
                queryUrl += string.Format("searchstr={0}&action=advanced&search_type=title&year=&year2=&tags=&tags_type=0&sort=time_added&way=desc&hentai=2&releasegroup=&epcount=&epcount2=&artbooktitle=", cleanSearchTerm);
            }

            // Check cache first so we don't query the server for each episode when searching for each episode in a series.
            lock (cache)
            {
                // Remove old cache items
                CleanCache();

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

            // Get the content from the tracker
            var response = await RequestStringWithCookiesAndRetry(queryUrl);

            CQ dom = response.Content;

            // Parse
            try
            {
                var releaseInfo = "S01";
                var root        = dom.Find(".group_cont");
                // We may have got redirected to the series page if we have none of these
                if (root.Count() == 0)
                {
                    root = dom.Find(".torrent_table");
                }

                foreach (var series in root)
                {
                    var seriesCq = series.Cq();

                    var    synonyms = new List <string>();
                    string mainTitle;
                    if (searchType == SearchType.Video)
                    {
                        mainTitle = seriesCq.Find(".group_title strong a").First().Text().Trim();
                    }
                    else
                    {
                        mainTitle = seriesCq.Find(".group_title strong").Text().Trim();
                    }

                    var yearStr   = seriesCq.Find(".group_title strong").First().Text().Trim().Replace("]", "").Trim();
                    int yearIndex = yearStr.LastIndexOf("[");
                    if (yearIndex > -1)
                    {
                        yearStr = yearStr.Substring(yearIndex + 1);
                    }

                    int year = 0;
                    if (!int.TryParse(yearStr, out year))
                    {
                        year = DateTime.Now.Year;
                    }

                    synonyms.Add(mainTitle);

                    // If the title contains a comma then we can't use the synonyms as they are comma seperated
                    if (!mainTitle.Contains(","))
                    {
                        var symnomnNames = string.Empty;
                        foreach (var e in seriesCq.Find(".group_statbox li"))
                        {
                            if (e.FirstChild.InnerText == "Synonyms:")
                            {
                                symnomnNames = e.InnerText;
                            }
                        }

                        if (!string.IsNullOrWhiteSpace(symnomnNames))
                        {
                            foreach (var name in symnomnNames.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
                            {
                                var theName = name.Trim();
                                if (!theName.Contains("&#") && !string.IsNullOrWhiteSpace(theName))
                                {
                                    synonyms.Add(theName);
                                }
                            }
                        }
                    }

                    foreach (var title in synonyms)
                    {
                        var releaseRows = seriesCq.Find(".torrent_group tr");

                        // Skip the first two info rows
                        for (int r = 1; r < releaseRows.Count(); r++)
                        {
                            var row   = releaseRows.Get(r);
                            var rowCq = row.Cq();
                            if (rowCq.HasClass("edition_info"))
                            {
                                releaseInfo = rowCq.Find("td").Text();

                                if (string.IsNullOrWhiteSpace(releaseInfo))
                                {
                                    // Single episodes alpha - Reported that this info is missing.
                                    // It should self correct when availible
                                    break;
                                }

                                releaseInfo = releaseInfo.Replace("Episode ", "");
                                releaseInfo = releaseInfo.Replace("Season ", "S");
                                releaseInfo = releaseInfo.Trim();
                                int test = 0;
                                if (InsertSeason && int.TryParse(releaseInfo, out test) && releaseInfo.Length == 1)
                                {
                                    releaseInfo = "S01E0" + releaseInfo;
                                }
                            }
                            else if (rowCq.HasClass("torrent"))
                            {
                                var links = rowCq.Find("a");
                                // Protect against format changes
                                if (links.Count() != 2)
                                {
                                    continue;
                                }

                                var release = new ReleaseInfo();
                                release.MinimumRatio    = 1;
                                release.MinimumSeedTime = 259200;
                                var downloadLink = links.Get(0);

                                // We dont know this so try to fake based on the release year
                                release.PublishDate = new DateTime(year, 1, 1);
                                release.PublishDate = release.PublishDate.AddDays(Math.Min(DateTime.Now.DayOfYear, 365) - 1);

                                var infoLink = links.Get(1);
                                release.Comments = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href"));
                                release.Guid     = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href") + "&nh=" + StringUtil.Hash(title)); // Sonarr should dedupe on this url - allow a url per name.
                                release.Link     = new Uri(downloadLink.Attributes.GetAttribute("href"), UriKind.Relative);

                                string category = null;
                                if (searchType == SearchType.Video)
                                {
                                    category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
                                    if (category == "TV Series")
                                    {
                                        release.Category = TorznabCatType.TVAnime.ID;
                                    }

                                    // Ignore these categories as they'll cause hell with the matcher
                                    // TV Special, OVA, ONA, DVD Special, BD Special

                                    if (category == "Movie")
                                    {
                                        release.Category = TorznabCatType.Movies.ID;
                                    }

                                    if (category == "Manga" || category == "Oneshot" || category == "Anthology" || category == "Manhwa" || category == "Manhua" || category == "Light Novel")
                                    {
                                        release.Category = TorznabCatType.BooksComics.ID;
                                    }

                                    if (category == "Novel" || category == "Artbook")
                                    {
                                        release.Category = TorznabCatType.BooksComics.ID;
                                    }

                                    if (category == "Game" || category == "Visual Novel")
                                    {
                                        var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
                                        if (description.Contains(" PSP "))
                                        {
                                            release.Category = TorznabCatType.ConsolePSP.ID;
                                        }
                                        if (description.Contains("PSX"))
                                        {
                                            release.Category = TorznabCatType.ConsoleOther.ID;
                                        }
                                        if (description.Contains(" NES "))
                                        {
                                            release.Category = TorznabCatType.ConsoleOther.ID;
                                        }
                                        if (description.Contains(" PC "))
                                        {
                                            release.Category = TorznabCatType.PCGames.ID;
                                        }
                                    }
                                }

                                if (searchType == SearchType.Audio)
                                {
                                    category = seriesCq.Find(".group_img .cat a").Text();
                                    if (category == "Single" || category == "Album" || category == "Compilation" || category == "Soundtrack" || category == "Remix CD")
                                    {
                                        var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
                                        if (description.Contains(" Lossless "))
                                        {
                                            release.Category = TorznabCatType.AudioLossless.ID;
                                        }
                                        else if (description.Contains("MP3"))
                                        {
                                            release.Category = TorznabCatType.AudioMP3.ID;
                                        }
                                        else
                                        {
                                            release.Category = TorznabCatType.AudioOther.ID;
                                        }
                                    }
                                }



                                // We dont actually have a release name >.> so try to create one
                                var releaseTags = infoLink.InnerText.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
                                for (int i = releaseTags.Count - 1; i >= 0; i--)
                                {
                                    releaseTags[i] = releaseTags[i].Trim();
                                    if (string.IsNullOrWhiteSpace(releaseTags[i]))
                                    {
                                        releaseTags.RemoveAt(i);
                                    }
                                }

                                var group = releaseTags.Last();
                                if (group.Contains("(") && group.Contains(")"))
                                {
                                    // Skip raws if set
                                    if (group.ToLowerInvariant().StartsWith("raw") && !AllowRaws)
                                    {
                                        continue;
                                    }

                                    var start = group.IndexOf("(");
                                    group = "[" + group.Substring(start + 1, (group.IndexOf(")") - 1) - start) + "] ";
                                }
                                else
                                {
                                    group = string.Empty;
                                }

                                var infoString = "";

                                for (int i = 0; i + 1 < releaseTags.Count(); i++)
                                {
                                    if (releaseTags[i] == "Raw" && !AllowRaws)
                                    {
                                        continue;
                                    }
                                    infoString += "[" + releaseTags[i] + "]";
                                }

                                if (category == "Movie")
                                {
                                    release.Title = string.Format("{0} {1} {2}{3}", title, year, group, infoString);
                                }
                                else
                                {
                                    release.Title = string.Format("{0}{1} {2} {3}", group, title, releaseInfo, infoString);
                                }
                                release.Description = title;

                                var size = rowCq.Find(".torrent_size");
                                if (size.Count() > 0)
                                {
                                    release.Size = ReleaseInfo.GetBytes(size.First().Text());
                                }

                                //  Additional 5 hours per GB
                                release.MinimumSeedTime += (release.Size / 1000000000) * 18000;

                                // Peer info
                                release.Seeders = ParseUtil.CoerceInt(rowCq.Find(".torrent_seeders").Text());
                                release.Peers   = release.Seeders + ParseUtil.CoerceInt(rowCq.Find(".torrent_leechers").Text());

                                // grabs
                                var grabs = rowCq.Find("td.torrent_snatched").Text();
                                release.Grabs = ParseUtil.CoerceInt(grabs);

                                // freeleech
                                if (rowCq.Find("img[alt=\"Freeleech!\"]").Length >= 1)
                                {
                                    release.DownloadVolumeFactor = 0;
                                }
                                else
                                {
                                    release.DownloadVolumeFactor = 1;
                                }
                                release.UploadVolumeFactor = 1;

                                if (release.Category != 0)
                                {
                                    releases.Add(release);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(response.Content, ex);
            }

            // Add to the cache
            lock (cache)
            {
                cache.Add(new CachedQueryResult(queryUrl, releases));
            }

            return(releases.Select(s => (ReleaseInfo)s.Clone()));
        }
示例#18
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases     = new List <ReleaseInfo>();
            var searchString = query.GetQueryString();
            var prevCook     = CookieHeader + "";

            var searchParams = new Dictionary <string, string> {
                { "do", "search" },
                { "category", "0" },
                { "include_dead_torrents", "no" }
            };

            if (query.IsImdbQuery)
            {
                searchParams.Add("keywords", query.ImdbID);
                searchParams.Add("search_type", "t_both");
            }
            else
            {
                searchParams.Add("keywords", searchString);
                searchParams.Add("search_type", "t_name");
            }

            var searchPage = await RequestWithCookiesAndRetryAsync(
                SearchUrl, CookieHeader, RequestType.POST, null, searchParams);

            // Occasionally the cookies become invalid, login again if that happens
            if (searchPage.IsRedirect)
            {
                await ApplyConfiguration(null);

                searchPage = await RequestWithCookiesAndRetryAsync(
                    SearchUrl, CookieHeader, RequestType.POST, null, searchParams);
            }

            try
            {
                var parser = new HtmlParser();
                var dom    = parser.ParseDocument(searchPage.ContentString);
                var rows   = dom.QuerySelectorAll("table#sortabletable > tbody > tr:has(div > a[href*=\"details.php?id=\"])");
                foreach (var row in rows)
                {
                    var release = new ReleaseInfo();

                    var qDetails = row.QuerySelector("div > a[href*=\"details.php?id=\"]");
                    var qTitle   = qDetails; // #7975

                    release.Title = qTitle.TextContent;

                    release.Guid     = new Uri(row.QuerySelector("td:nth-of-type(3) a").GetAttribute("href"));
                    release.Link     = release.Guid;
                    release.Comments = new Uri(qDetails.GetAttribute("href"));
                    //08-08-2015 12:51
                    release.PublishDate = DateTime.ParseExact(
                        row.QuerySelectorAll("td:nth-of-type(2) div").Last().TextContent.Trim(), "dd-MM-yyyy H:mm",
                        CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
                    release.Seeders = ParseUtil.CoerceInt(row.QuerySelector("td:nth-of-type(7)").TextContent);
                    release.Peers   = release.Seeders + ParseUtil.CoerceInt(row.QuerySelector("td:nth-of-type(8)").TextContent.Trim());
                    release.Size    = ReleaseInfo.GetBytes(row.QuerySelector("td:nth-of-type(5)").TextContent.Trim());

                    var qBanner = row.QuerySelector("td:nth-of-type(2) .tooltip-content img");
                    if (qBanner != null)
                    {
                        release.BannerUrl = new Uri(qBanner.GetAttribute("src"));
                    }

                    var cat      = row.QuerySelector("td:nth-of-type(1) a").GetAttribute("href");
                    var catSplit = cat.LastIndexOf('=');
                    if (catSplit > -1)
                    {
                        cat = cat.Substring(catSplit + 1);
                    }
                    release.Category = MapTrackerCatToNewznab(cat);

                    var grabs = row.QuerySelector("td:nth-child(6)").TextContent;
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    if (row.QuerySelector("img[alt^=\"Free Torrent\"]") != null)
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else if (row.QuerySelector("img[alt^=\"Silver Torrent\"]") != null)
                    {
                        release.DownloadVolumeFactor = 0.5;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    if (row.QuerySelector("img[alt^=\"x2 Torrent\"]") != null)
                    {
                        release.UploadVolumeFactor = 2;
                    }
                    else
                    {
                        release.UploadVolumeFactor = 1;
                    }

                    release.MinimumRatio = 0.8;

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(searchPage.ContentString, ex);
            }

            if (!CookieHeader.Trim().Equals(prevCook.Trim()))
            {
                SaveConfig();
            }

            return(releases);
        }
示例#19
0
        protected async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query, String seasonep)
        {
            var releases     = new List <ReleaseInfo>();
            var searchString = query.GetQueryString();
            var pairs        = new List <KeyValuePair <string, string> >();

            if (seasonep != null)
            {
                searchString = query.SanitizedSearchTerm;
            }

            pairs.Add(new KeyValuePair <string, string>("nyit_sorozat_resz", "true"));
            pairs.Add(new KeyValuePair <string, string>("miben", "name"));
            pairs.Add(new KeyValuePair <string, string>("tipus", "kivalasztottak_kozott"));
            pairs.Add(new KeyValuePair <string, string>("submit.x", "1"));
            pairs.Add(new KeyValuePair <string, string>("submit.y", "1"));
            pairs.Add(new KeyValuePair <string, string>("submit", "Ok"));
            pairs.Add(new KeyValuePair <string, string>("mire", searchString));

            var cats = MapTorznabCapsToTrackers(query);

            if (cats.Count == 0)
            {
                cats = GetAllTrackerCategories();
            }

            foreach (var lcat in LanguageCats)
            {
                if (!configData.Hungarian.Value)
                {
                    cats.Remove(lcat + "_hun");
                }
                if (!configData.English.Value)
                {
                    cats.Remove(lcat);
                }
            }

            foreach (var cat in cats)
            {
                pairs.Add(new KeyValuePair <string, string>("kivalasztott_tipus[]", cat));
            }

            var results = await PostDataWithCookiesAndRetry(SearchUrl, pairs);

            try
            {
                CQ dom = results.Content;

                ReleaseInfo release;
                var         rows = dom[".box_torrent_all"].Find(".box_torrent");

                foreach (var row in rows)
                {
                    CQ qRow = row.Cq();

                    var key = dom["link[rel=alternate]"].First().Attr("href").Split('=').Last();

                    release = new ReleaseInfo();
                    var torrentTxt = qRow.Find(".torrent_txt, .torrent_txt2").Find("a").Get(0);
                    //if (torrentTxt == null) continue;
                    release.Title                = torrentTxt.GetAttribute("title");
                    release.Description          = qRow.Find("div.siterank").Text();
                    release.MinimumRatio         = 1;
                    release.MinimumSeedTime      = 172800;
                    release.DownloadVolumeFactor = 0;
                    release.UploadVolumeFactor   = 1;

                    string downloadLink = SiteLink + torrentTxt.GetAttribute("href");
                    string downloadId   = downloadLink.Substring(downloadLink.IndexOf("&id=") + 4);

                    release.Link     = new Uri(SiteLink.ToString() + "torrents.php?action=download&id=" + downloadId + "&key=" + key);
                    release.Comments = new Uri(SiteLink.ToString() + "torrents.php?action=details&id=" + downloadId);
                    release.Guid     = new Uri(release.Comments.ToString() + "#comments");;
                    release.Seeders  = ParseUtil.CoerceInt(qRow.Find(".box_s2").Find("a").First().Text());
                    release.Peers    = ParseUtil.CoerceInt(qRow.Find(".box_l2").Find("a").First().Text()) + release.Seeders;
                    var imdblink = qRow.Find("a[href*=\".imdb.com/title\"]").Attr("href");
                    release.Imdb = ParseUtil.GetLongFromString(imdblink);
                    var banner = qRow.Find("img.infobar_ico").Attr("onmouseover");
                    if (banner != null)
                    {
                        Regex BannerRegEx = new Regex(@"mutat\('(.*?)', '", RegexOptions.Compiled);
                        var   BannerMatch = BannerRegEx.Match(banner);
                        var   bannerurl   = BannerMatch.Groups[1].Value;
                        release.BannerUrl = new Uri(bannerurl);
                    }
                    release.PublishDate = DateTime.Parse(qRow.Find(".box_feltoltve2").Get(0).InnerHTML.Replace("<br />", " "), CultureInfo.InvariantCulture);
                    string[] sizeSplit = qRow.Find(".box_meret2").Get(0).InnerText.Split(' ');
                    release.Size = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0]));
                    string catlink = qRow.Find("a:has(img[class='categ_link'])").First().Attr("href");
                    string cat     = ParseUtil.GetArgumentFromQueryString(catlink, "tipus");
                    release.Category = MapTrackerCatToNewznab(cat);
                    if (seasonep == null)
                    {
                        releases.Add(release);
                    }

                    else
                    {
                        if (query.MatchQueryStringAND(release.Title, null, seasonep))
                        {
                            /* For sonnar if the search querry was english the title must be english also so we need to change the Description and Title */
                            var temp = release.Title;

                            // releasedata everithing after Name.S0Xe0X
                            String releasedata = release.Title.Split(new[] { seasonep }, StringSplitOptions.None)[1].Trim();

                            /* if the release name not contains the language we add it because it is know from category */
                            if (cat.Contains("hun") && !releasedata.Contains("hun"))
                            {
                                releasedata += ".hun";
                            }

                            // release description contains [imdb: ****] but we only need the data before it for title
                            String[] description = { release.Description, "" };
                            if (release.Description.Contains("[imdb:"))
                            {
                                description    = release.Description.Split('[');
                                description[1] = "[" + description[1];
                            }
                            else
                            {
                                release.Title = (description[0].Trim() + "." + seasonep.Trim() + "." + releasedata.Trim('.')).Replace(' ', '.');
                            }

                            // if search is done for S0X than we dont want to put . between S0X and E0X
                            Match match = Regex.Match(releasedata, @"^E\d\d?");
                            if (seasonep.Length == 3 && match.Success)
                            {
                                release.Title = (description[0].Trim() + "." + seasonep.Trim() + releasedata.Trim('.')).Replace(' ', '.');
                            }

                            // add back imdb points to the description [imdb: 8.7]
                            release.Description = temp + " " + description[1];
                            release.Description = release.Description.Trim();
                            releases.Add(release);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

            return(releases);
        }
示例#20
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases     = new List <ReleaseInfo>();
            var searchString = query.GetQueryString();

            //  replace any space, special char, etc. with % (wildcard)
            Regex ReplaceRegex = new Regex("[^a-zA-Z0-9]+");

            searchString = ReplaceRegex.Replace(searchString, "%");

            var searchUrl       = SearchUrl;
            var queryCollection = new NameValueCollection();

            queryCollection.Add("total", "146"); // Not sure what this is about but its required!

            var cat       = "0";
            var queryCats = MapTorznabCapsToTrackers(query);

            if (queryCats.Count == 1)
            {
                cat = queryCats.First().ToString();
            }

            queryCollection.Add("cat", cat);
            queryCollection.Add("searchin", "filename");
            queryCollection.Add("search", searchString);
            queryCollection.Add("page", "1");
            searchUrl += "?" + queryCollection.GetQueryString();

            var extraHeaders = new Dictionary <string, string>()
            {
                { "X-Requested-With", "XMLHttpRequest" }
            };

            var response = await RequestStringWithCookiesAndRetry(searchUrl, null, SearchUrlReferer, extraHeaders);

            var results = response.Content;

            try
            {
                CQ dom = results;

                var rows = dom["tr"];
                foreach (var row in rows.Skip(1))
                {
                    var release    = new ReleaseInfo();
                    var qRow       = row.Cq();
                    var qTitleLink = qRow.Find("td:eq(1) a:eq(0)").First();
                    release.Title = qTitleLink.Text().Trim();

                    // If we search an get no results, we still get a table just with no info.
                    if (string.IsNullOrWhiteSpace(release.Title))
                    {
                        break;
                    }

                    release.Guid     = new Uri(qTitleLink.Attr("href"));
                    release.Comments = release.Guid;

                    var dateString = qRow.Find("td:eq(4)").Text();
                    release.PublishDate = DateTime.ParseExact(dateString, "dd MMM yy", CultureInfo.InvariantCulture);

                    var qLink = qRow.Find("td:eq(2) a");
                    if (qLink.Length != 0) // newbie users don't see DL links
                    {
                        release.Link = new Uri(qLink.Attr("href"));
                    }
                    else
                    {
                        // use comments link as placeholder
                        // null causes errors during export to torznab
                        // skipping the release prevents newbie users from adding the tracker (empty result)
                        release.Link = release.Comments;
                    }

                    var sizeStr = qRow.Find("td:eq(5)").Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    var connections = qRow.Find("td:eq(7)").Text().Trim().Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                    release.Seeders = ParseUtil.CoerceInt(connections[0].Trim());
                    release.Peers   = ParseUtil.CoerceInt(connections[1].Trim()) + release.Seeders;
                    release.Grabs   = ParseUtil.CoerceLong(connections[2].Trim());

                    var rCat    = row.Cq().Find("td:eq(0) a").First().Attr("href");
                    var rCatIdx = rCat.IndexOf("cat=");
                    if (rCatIdx > -1)
                    {
                        rCat = rCat.Substring(rCatIdx + 4);
                    }

                    release.Category = MapTrackerCatToNewznab(rCat);

                    if (qRow.Find("img[alt=\"Gold Torrent\"]").Length >= 1)
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else if (qRow.Find("img[alt=\"Silver Torrent\"]").Length >= 1)
                    {
                        release.DownloadVolumeFactor = 0.5;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    var ULFactorImg = qRow.Find("img[alt*=\"x Multiplier Torrent\"]");
                    if (ULFactorImg.Length >= 1)
                    {
                        release.UploadVolumeFactor = ParseUtil.CoerceDouble(ULFactorImg.Attr("alt").Split('x')[0]);
                    }
                    else
                    {
                        release.UploadVolumeFactor = 1;
                    }

                    qTitleLink.Remove();
                    release.Description = qRow.Find("td:eq(1)").Text();

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results, ex);
            }

            return(releases);
        }
示例#21
0
文件: Pier720.cs 项目: wwwwg/Jackett
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var searchString    = query.GetQueryString();
            var keywordSearch   = !string.IsNullOrWhiteSpace(searchString);
            var releases        = new List <ReleaseInfo>();
            var queryCollection = !keywordSearch
                ? new NameValueCollection
            {
                { "search_id", "active_topics" }
            }
                : new NameValueCollection
            {
                { "sr", "posts" }, //Search all posts
                { "ot", "1" },     //Search only in forums trackers (checked)
                { "keywords", searchString },
                { "sf", "titleonly" }
            };
            var searchUrl = SearchUrl + "?" + queryCollection.GetQueryString();
            var results   = await RequestStringWithCookies(searchUrl);

            if (!results.Content.Contains("ucp.php?mode=logout"))
            {
                await ApplyConfiguration(null);

                results = await RequestStringWithCookies(searchUrl);
            }

            try
            {
                var resultParser         = new HtmlParser();
                var searchResultDocument = resultParser.ParseDocument(results.Content);
                var rowSelector          = keywordSearch
                    ? "div.search div.postbody > h3 > a"
                    : "ul.topics > li.row:has(i.fa-paperclip) a.topictitle"; // Torrent lines have paperclip icon. Chat topics don't
                var rows = searchResultDocument.QuerySelectorAll(rowSelector);
                foreach (var rowLink in rows)
                {
                    var detailLink    = SiteLink + rowLink.GetAttribute("href");
                    var detailsResult = await RequestStringWithCookies(detailLink);

                    var detailsDocument = resultParser.ParseDocument(detailsResult.Content);
                    var detailRow       = detailsDocument.QuerySelector("table.table2 > tbody > tr");
                    if (detailRow == null)
                    {
                        continue; //No torrents in result
                    }
                    var qDownloadLink = detailRow.QuerySelector("a[href^=\"/download/torrent\"]");
                    var link          = new Uri(SiteLink + qDownloadLink.GetAttribute("href").TrimStart('/'));
                    var timestr       = detailRow.Children[0].QuerySelector("ul.dropdown-contents span.my_tt").TextContent;
                    var publishDate   = DateTimeUtil.FromUnknown(timestr, "UK");
                    var forumId       = detailsDocument.QuerySelector("li.breadcrumbs").LastElementChild
                                        .GetAttribute("data-forum-id");
                    var sizeString = detailRow.Children[4].QuerySelector("span.my_tt").GetAttribute("title");
                    var size       = ParseUtil.CoerceLong(Regex.Replace(sizeString, @"[^0-9]", string.Empty));
                    var comments   = new Uri(detailLink);
                    var grabs      = ParseUtil.CoerceInt(detailRow.Children[0].QuerySelector("span.complet").TextContent);
                    var seeders    = ParseUtil.CoerceInt(detailRow.Children[2].QuerySelector("span.seed").TextContent);
                    var leechers   = ParseUtil.CoerceInt(detailRow.Children[3].QuerySelector("span.leech").TextContent);
                    var release    = new ReleaseInfo
                    {
                        MinimumRatio         = 1,
                        MinimumSeedTime      = 0,
                        DownloadVolumeFactor = 1,
                        UploadVolumeFactor   = 1,
                        Seeders     = seeders,
                        Grabs       = grabs,
                        Peers       = leechers + seeders,
                        Title       = rowLink.TextContent,
                        Comments    = comments,
                        Guid        = comments,
                        Link        = link,
                        PublishDate = publishDate,
                        Category    = MapTrackerCatToNewznab(forumId),
                        Size        = size,
                    };
                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

            return(releases);
        }
示例#22
0
文件: NCore.cs 项目: waknaudt/Jackett
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases     = new List <ReleaseInfo>();
            var searchString = query.GetQueryString();
            var pairs        = new List <KeyValuePair <string, string> >();

            pairs.Add(new KeyValuePair <string, string>("nyit_sorozat_resz", "true"));
            pairs.Add(new KeyValuePair <string, string>("miben", "name"));
            pairs.Add(new KeyValuePair <string, string>("tipus", "kivalasztottak_kozott"));
            pairs.Add(new KeyValuePair <string, string>("submit.x", "1"));
            pairs.Add(new KeyValuePair <string, string>("submit.y", "1"));
            pairs.Add(new KeyValuePair <string, string>("submit", "Ok"));
            pairs.Add(new KeyValuePair <string, string>("mire", searchString));

            var cats = MapTorznabCapsToTrackers(query);

            if (cats.Count == 0)
            {
                cats = GetAllTrackerCategories();
            }

            foreach (var lcat in LanguageCats)
            {
                if (!configData.Hungarian.Value)
                {
                    cats.Remove(lcat + "_hun");
                }
                if (!configData.English.Value)
                {
                    cats.Remove(lcat);
                }
            }

            foreach (var cat in cats)
            {
                pairs.Add(new KeyValuePair <string, string>("kivalasztott_tipus[]", cat));
            }

            var results = await PostDataWithCookiesAndRetry(SearchUrl, pairs);

            try
            {
                CQ dom = results.Content;

                ReleaseInfo release;
                var         rows = dom[".box_torrent_all"].Find(".box_torrent");

                foreach (var row in rows)
                {
                    CQ qRow = row.Cq();

                    var key = dom ["link[rel=alternate]"].First().Attr("href").Split('=').Last();

                    release = new ReleaseInfo();
                    var torrentTxt = qRow.Find(".torrent_txt, .torrent_txt2").Find("a").Get(0);
                    //if (torrentTxt == null) continue;
                    release.Title                = torrentTxt.GetAttribute("title");
                    release.Description          = qRow.Find("div.siterank").Text();
                    release.MinimumRatio         = 1;
                    release.MinimumSeedTime      = 172800;
                    release.DownloadVolumeFactor = 0;
                    release.UploadVolumeFactor   = 1;

                    string downloadLink = SiteLink + torrentTxt.GetAttribute("href");
                    string downloadId   = downloadLink.Substring(downloadLink.IndexOf("&id=") + 4);

                    release.Link     = new Uri(SiteLink.ToString() + "torrents.php?action=download&id=" + downloadId + "&key=" + key);
                    release.Comments = new Uri(SiteLink.ToString() + "torrents.php?action=details&id=" + downloadId);
                    release.Guid     = new Uri(release.Comments.ToString() + "#comments");;
                    release.Seeders  = ParseUtil.CoerceInt(qRow.Find(".box_s2").Find("a").First().Text());
                    release.Peers    = ParseUtil.CoerceInt(qRow.Find(".box_l2").Find("a").First().Text()) + release.Seeders;
                    var imdblink = qRow.Find("a[href*=\".imdb.com/title\"]").Attr("href");
                    release.Imdb = ParseUtil.GetLongFromString(imdblink);
                    var banner = qRow.Find("img.infobar_ico").Attr("onmouseover");
                    if (banner != null)
                    {
                        Regex BannerRegEx = new Regex(@"mutat\('(.*?)', '", RegexOptions.Compiled);
                        var   BannerMatch = BannerRegEx.Match(banner);
                        var   bannerurl   = BannerMatch.Groups[1].Value;
                        release.BannerUrl = new Uri(bannerurl);
                    }
                    release.PublishDate = DateTime.Parse(qRow.Find(".box_feltoltve2").Get(0).InnerHTML.Replace("<br />", " "), CultureInfo.InvariantCulture);
                    string[] sizeSplit = qRow.Find(".box_meret2").Get(0).InnerText.Split(' ');
                    release.Size = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0]));
                    string catlink = qRow.Find("a:has(img[class='categ_link'])").First().Attr("href");
                    string cat     = ParseUtil.GetArgumentFromQueryString(catlink, "tipus");
                    release.Category = MapTrackerCatToNewznab(cat);

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

            return(releases);
        }
示例#23
0
        private async Task <List <ReleaseInfo> > ParseLast24HoursAsync()
        {
            var releases = new List <ReleaseInfo>();
            var results  = await RequestStringWithCookies(TodayUrl);

            if (results.IsRedirect)
            {
                // re-login
                await ApplyConfiguration(null);

                results = await RequestStringWithCookies(TodayUrl);
            }

            try
            {
                const string rowsSelector         = "table.torrent_table > tbody > tr:not(tr.colhead)";
                var          searchResultParser   = new HtmlParser();
                var          searchResultDocument = searchResultParser.ParseDocument(results.Content);
                var          rows = searchResultDocument.QuerySelectorAll(rowsSelector);
                foreach (var row in rows)
                {
                    try
                    {
                        var release = new ReleaseInfo
                        {
                            MinimumRatio    = 1,
                            MinimumSeedTime = 0
                        };
                        var qDetailsLink = row.QuerySelector("a.BJinfoBox");
                        var qBJinfoBox   = qDetailsLink.QuerySelector("span");
                        var qCatLink     = row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
                        var qDlLink      = row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
                        var qSeeders     = row.QuerySelector("td:nth-child(4)");
                        var qLeechers    = row.QuerySelector("td:nth-child(5)");
                        var qQuality     = row.QuerySelector("font[color=\"red\"]");
                        var qFreeLeech   = row.QuerySelector("font[color=\"green\"]:contains(Free)");
                        var qTitle       = qDetailsLink.QuerySelector("font");
                        // Get international title if available, or use the full title if not
                        release.Title = Regex.Replace(qTitle.TextContent, @".* \[(.*?)\](.*)", "$1$2");
                        var year = "";
                        release.Description = "";
                        var extraInfo = "";
                        foreach (var child in qBJinfoBox.ChildNodes)
                        {
                            var type = child.NodeType;
                            if (type != NodeType.Text)
                            {
                                continue;
                            }
                            var line = child.TextContent;
                            if (line.StartsWith("Tamanho:"))
                            {
                                var size = line.Substring("Tamanho: ".Length);
                                release.Size = ReleaseInfo.GetBytes(size);
                            }
                            else if (line.StartsWith("Lançado em: "))
                            {
                                var publishDateStr = line.Substring("Lançado em: ".Length).Replace("às ", "");
                                publishDateStr += " +0";
                                var publishDate = DateTime.SpecifyKind(
                                    DateTime.ParseExact(publishDateStr, "dd/MM/yyyy HH:mm z", CultureInfo.InvariantCulture),
                                    DateTimeKind.Unspecified);
                                release.PublishDate = publishDate.ToLocalTime();
                            }
                            else if (line.StartsWith("Ano:"))
                            {
                                year = line.Substring("Ano: ".Length);
                            }
                            else
                            {
                                release.Description += line + "\n";
                                if (line.Contains(":"))
                                {
                                    if (!(line.StartsWith("Lançado") || line.StartsWith("Resolução") ||
                                          line.StartsWith("Idioma") || line.StartsWith("Autor")))
                                    {
                                        var info = line.Substring(line.IndexOf(": ", StringComparison.Ordinal) + 2);
                                        if (info == "Dual Áudio")
                                        {
                                            info = "Dual";
                                        }
                                        extraInfo += info + " ";
                                    }
                                }
                            }
                        }

                        var catStr = qCatLink.GetAttribute("href").Split('=')[1].Split('&')[0];
                        release.Title = FixAbsoluteNumbering(release.Title);
                        if (!string.IsNullOrEmpty(year))
                        {
                            release.Title += " " + year;
                        }
                        if (qQuality != null)
                        {
                            var quality = qQuality.TextContent;
                            release.Title += quality switch
                            {
                                "4K" => " 2160p",
                                "Full HD" => " 1080p",
                                "HD" => " 720p",
                                _ => " 480p"
                            };
                        }

                        release.Title               += " " + extraInfo.TrimEnd();
                        release.Category             = MapTrackerCatToNewznab(catStr);
                        release.Link                 = new Uri(SiteLink + qDlLink.GetAttribute("href"));
                        release.Comments             = new Uri(SiteLink + qDetailsLink.GetAttribute("href"));
                        release.Guid                 = release.Link;
                        release.Seeders              = ParseUtil.CoerceInt(qSeeders.TextContent);
                        release.Peers                = ParseUtil.CoerceInt(qLeechers.TextContent) + release.Seeders;
                        release.DownloadVolumeFactor = qFreeLeech != null ? 0 : 1;
                        release.UploadVolumeFactor   = 1;
                        releases.Add(release);
                    }
                    catch (Exception ex)
                    {
                        logger.Error($"{ID}: Error while parsing row '{row.OuterHtml}': {ex.Message}");
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

            return(releases);
        }
示例#24
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases        = new List <ReleaseInfo>();
            var searchString    = query.GetQueryString();
            var searchUrl       = BrowseUrl;
            var queryCollection = new NameValueCollection();

            if (!string.IsNullOrWhiteSpace(query.ImdbID))
            {
                queryCollection.Add("q", query.ImdbID);
            }
            else if (!string.IsNullOrWhiteSpace(searchString))
            {
                queryCollection.Add("q", searchString);
            }

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add(cat, string.Empty);
            }

            if (queryCollection.Count > 0)
            {
                searchUrl += "?" + queryCollection.GetQueryString();
            }

            var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);

            var results = response.Content;

            try
            {
                CQ dom = results;

                var rows = dom["table[id='torrents'] > tbody > tr"];
                foreach (var row in rows.Skip(1))
                {
                    var release    = new ReleaseInfo();
                    var qRow       = row.Cq();
                    var qTitleLink = qRow.Find("a[href^=\"/details.php?id=\"]").First();
                    release.Title = qTitleLink.Text().Trim();

                    // If we search an get no results, we still get a table just with no info.
                    if (string.IsNullOrWhiteSpace(release.Title))
                    {
                        break;
                    }

                    release.Guid     = new Uri(SiteLink + qTitleLink.Attr("href").Substring(1));
                    release.Comments = release.Guid;

                    var descString = qRow.Find(".t_ctime").Text();
                    var dateString = descString.Split('|').Last().Trim();
                    dateString          = dateString.Split(new string[] { " by " }, StringSplitOptions.None)[0];
                    release.PublishDate = DateTimeUtil.FromTimeAgo(dateString);

                    var qLink = row.ChildElements.ElementAt(3).Cq().Children("a");
                    release.Link = new Uri(SiteLink + WebUtility.UrlEncode(qLink.Attr("href").TrimStart('/')));

                    var sizeStr = row.ChildElements.ElementAt(5).Cq().Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(qRow.Find(".t_seeders").Text().Trim());
                    release.Peers   = ParseUtil.CoerceInt(qRow.Find(".t_leechers").Text().Trim()) + release.Seeders;

                    var catIcon = row.Cq().Find("td:eq(0) a");
                    if (catIcon.Length >= 1) // Torrents - Category column == Icons
                    {
                        release.Category = MapTrackerCatToNewznab(catIcon.First().Attr("href").Substring(1));
                    }
                    else // Torrents - Category column == Text (Code is not supported)
                    {
                        release.Category = MapTrackerCatDescToNewznab(row.Cq().Find("td:eq(0)").Text());
                    }

                    var filesElement = row.Cq().Find("a[href*=\"/files\"]"); // optional
                    if (filesElement.Length == 1)
                    {
                        release.Files = ParseUtil.CoerceLong(filesElement.Text());
                    }

                    var grabs = row.Cq().Find("td:nth-last-child(3)").Text();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    if (row.Cq().Find("span.t_tag_free_leech").Any())
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    release.UploadVolumeFactor = 1;

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results, ex);
            }

            return(releases);
        }
示例#25
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            List <ReleaseInfo> releases = new List <ReleaseInfo>();

            var searchString    = query.GetQueryString();
            var searchUrl       = SearchUrl;
            var queryCollection = new NameValueCollection();

            queryCollection.Add("incldead", "1");
            queryCollection.Add("rel_type", "0"); // Alle

            if (query.ImdbID != null)
            {
                queryCollection.Add("searchin", "imdb");
                queryCollection.Add("search", query.ImdbID);
            }
            else
            {
                queryCollection.Add("searchin", "title");

                if (!string.IsNullOrWhiteSpace(searchString))
                {
                    // use AND+wildcard operator to avoid getting to many useless results
                    var searchStringArray = Regex.Split(searchString.Trim(), "[ _.-]+", RegexOptions.Compiled).ToList();
                    searchStringArray = searchStringArray.Where(x => x.Length >= 3).ToList();                                                      //  remove words with less than 3 characters
                    searchStringArray = searchStringArray.Where(x => !new string[] { "der", "die", "das", "the" }.Contains(x.ToLower())).ToList(); //  remove words with less than 3 characters
                    searchStringArray = searchStringArray.Select(x => "+" + x + "*").ToList();                                                     // add AND operators+wildcards
                    var searchStringFinal = String.Join(" ", searchStringArray);
                    queryCollection.Add("search", searchStringFinal);
                }
            }
            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add("c" + cat, "1");
            }

            searchUrl += "?" + queryCollection.GetQueryString();

            var results = await RequestStringWithCookiesAndRetry(searchUrl);

            if (results.IsRedirect)
            {
                await ApplyConfiguration(null);

                results = await RequestStringWithCookiesAndRetry(searchUrl);
            }

            try
            {
                CQ  dom             = results.Content;
                var rows            = dom["table.torrent_table > tbody > tr"];
                var globalFreeleech = dom.Find("legend:contains(\"Freeleech\")+ul > li > b:contains(\"Freeleech\")").Any();
                foreach (var row in rows.Skip(1))
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 96 * 60 * 60;

                    var qRow = row.Cq();

                    var catStr = row.ChildElements.ElementAt(0).FirstElementChild.GetAttribute("href").Split('=')[1];
                    release.Category = MapTrackerCatToNewznab(catStr);

                    var qLink = row.ChildElements.ElementAt(2).FirstElementChild.Cq();
                    release.Link = new Uri(SiteLink + qLink.Attr("href"));
                    var torrentId = qLink.Attr("href").Split('=').Last();

                    var descCol      = row.ChildElements.ElementAt(1);
                    var qCommentLink = descCol.FirstElementChild.Cq();
                    var torrentTag   = descCol.Cq().Find("span.torrent-tag");
                    var torrentTags  = torrentTag.Elements.Select(x => x.InnerHTML).ToList();
                    release.Title       = qCommentLink.Attr("title");
                    release.Description = String.Join(", ", torrentTags);
                    release.Comments    = new Uri(SiteLink + qCommentLink.Attr("href").Replace("&hit=1", ""));
                    release.Guid        = release.Comments;

                    var      torrent_details = descCol.Cq().Find(".torrent_details").Get(0);
                    var      rawDateStr      = torrent_details.ChildNodes.ElementAt(torrent_details.ChildNodes.Length - 3).Cq().Text();
                    var      dateStr         = rawDateStr.Trim().Replace("von", "").Trim();
                    DateTime dateGerman;
                    if (dateStr.StartsWith("Heute "))
                    {
                        dateGerman = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + TimeSpan.Parse(dateStr.Split(' ')[1]);
                    }
                    else if (dateStr.StartsWith("Gestern "))
                    {
                        dateGerman = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + TimeSpan.Parse(dateStr.Split(' ')[1]) - TimeSpan.FromDays(1);
                    }
                    else
                    {
                        dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
                    }

                    DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
                    release.PublishDate = pubDateUtc.ToLocalTime();

                    var imdbLink = descCol.Cq().Find("a[href*=\"&searchin=imdb\"]");
                    if (imdbLink.Any())
                    {
                        release.Imdb = ParseUtil.GetLongFromString(imdbLink.Attr("href"));
                    }

                    var sizeStr = row.ChildElements.ElementAt(5).Cq().Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(7).Cq().Text());
                    release.Peers   = ParseUtil.CoerceInt(row.ChildElements.ElementAt(8).Cq().Text()) + release.Seeders;

                    var grabs = qRow.Find("td:nth-child(7)").Text();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    if (globalFreeleech)
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else if (qRow.Find("span.torrent-tag-free").Length >= 1)
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    release.UploadVolumeFactor = 1;

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

            return(releases);
        }
示例#26
0
        /// <summary>
        /// Execute our search query
        /// </summary>
        /// <param name="query">Query</param>
        /// <returns>Releases</returns>
        public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases       = new List <ReleaseInfo>();
            var torrentRowList = new List <CQ>();
            var searchTerm     = query.GetQueryString();
            var searchUrl      = SearchUrl;
            int nbResults      = 0;
            int pageLinkCount  = 0;

            // 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.Where(i => i.Query == searchTerm).FirstOrDefault();
                    if (cachedResult != null)
                    {
                        return(cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray());
                    }
                }
            }

            // Build our query
            var request = buildQuery(searchTerm, query, searchUrl);

            // Getting results & Store content
            WebClientStringResult results = await queryExec(request);

            fDom = results.Content;

            try
            {
                // Find torrent rows
                var firstPageRows = findTorrentRows();

                // Add them to torrents list
                torrentRowList.AddRange(firstPageRows.Select(fRow => fRow.Cq()));

                // Check if there are pagination links at bottom
                Boolean pagination = (fDom[".pager_align > a"].Length != 0);

                // If pagination available
                if (pagination)
                {
                    // Calculate numbers of pages available for this search query (Based on number results and number of torrents on first page)
                    pageLinkCount = ParseUtil.CoerceInt(Regex.Match(fDom[".pager_align > a:not(:last-child)"].Last().Attr("href").ToString(), @"\d+").Value) + 1;

                    // Calculate average number of results (based on torrents rows lenght on first page)
                    nbResults = firstPageRows.Count() * pageLinkCount;
                }
                else
                {
                    // Check if we have a minimum of one result
                    if (firstPageRows.Length >= 1)
                    {
                        // Retrieve total count on our alone page
                        nbResults     = firstPageRows.Count();
                        pageLinkCount = 1;
                    }
                    else
                    {
                        output("\nNo result found for your query, please try another search term ...\n", "info");
                        // No result found for this query
                        return(releases);
                    }
                }
                output("\nFound " + nbResults + " result(s) (+/- " + firstPageRows.Length + ") in " + pageLinkCount + " page(s) for this query !");
                output("\nThere are " + firstPageRows.Length + " results on the first page !");

                // If we have a term used for search and pagination result superior to one
                if (!string.IsNullOrWhiteSpace(query.GetQueryString()) && pageLinkCount > 1)
                {
                    // Starting with page #2
                    for (int i = 2; i <= Math.Min(Int32.Parse(ConfigData.Pages.Value), pageLinkCount); i++)
                    {
                        output("\nProcessing page #" + i);

                        // Request our page
                        latencyNow();

                        // Build our query
                        var pageRequest = buildQuery(searchTerm, query, searchUrl, (i - 1));

                        // Getting results & Store content
                        WebClientStringResult pageResults = await queryExec(pageRequest);

                        // Assign response
                        fDom = pageResults.Content;

                        // Process page results
                        var additionalPageRows = findTorrentRows();

                        // Add them to torrents list
                        torrentRowList.AddRange(additionalPageRows.Select(fRow => fRow.Cq()));
                    }
                }
                else
                {
                    // No search term, maybe testing... so registring passkey for future uses
                    string         infosData    = firstPageRows.First().Find("td:eq(2) > a").Attr("href");
                    IList <string> infosList    = infosData.Split('&').Select(s => s.Trim()).Where(s => s != String.Empty).ToList();
                    IList <string> infosTracker = infosList.Select(s => s.Split(new[] { '=' }, 2)[1].Trim()).ToList();

                    output("\nStoring Passkey for future uses... \"" + infosTracker[2] + "\"");
                    ConfigData.PassKey.Value = infosTracker[2];
                }

                // Loop on results
                foreach (CQ tRow in torrentRowList)
                {
                    output("\n=>> Torrent #" + (releases.Count + 1));

                    // ID
                    string row = tRow.Html().ToString();
                    int    id  = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(1) > a").Attr("href").ToString(), @"\d+").Value);
                    output("ID: " + id);

                    // Release Name
                    string name = tRow.Find("td:eq(1) > a").Attr("title").ToString();
                    output("Release: " + name);

                    // Category
                    string         infosDataCategory = firstPageRows.First().Find("td:eq(0) > a").Attr("href");
                    IList <string> infosListCategory = infosDataCategory.Split('&').Select(s => s.Trim()).Where(s => s != String.Empty).ToList();
                    IList <string> infosCategory     = infosListCategory.Select(s => s.Split(new[] { '=' }, 2)[0].Trim()).ToList();
                    string         categoryID        = infosCategory.Last().TrimStart('c');
                    output("Category: " + MapTrackerCatToNewznab(categoryID) + " (" + categoryID + ")");

                    // Seeders
                    int seeders = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(6)").Text(), @"\d+").Value);
                    output("Seeders: " + seeders);

                    // Leechers
                    int leechers = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(7)").Text(), @"\d+").Value);
                    output("Leechers: " + leechers);

                    // Completed
                    int completed = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(5)").Text(), @"\d+").Value);
                    output("Completed: " + completed);

                    // Size
                    string sizeStr = tRow.Find("td:eq(4)").Text().Trim().Replace("Go", "gb").Replace("Mo", "mb").Replace("Ko", "kb");
                    long   size    = ReleaseInfo.GetBytes(sizeStr);
                    output("Size: " + sizeStr + " (" + size + " bytes)");

                    // Health
                    int percent = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(8) > img").Attr("alt").ToString(), @"\d+").Value);
                    output("Health: " + percent + "%");

                    // Publish DateToString
                    //var date = agoToDate(null);
                    int      timestamp = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(1)").Attr("data-added").ToString(), @"\d+").Value);
                    DateTime date      = unixTimeStampToDateTime(timestamp);
                    output("Released on: " + date.ToLocalTime() + " (TS >> " + timestamp + ")");

                    // Torrent Details URL
                    Uri detailsLink = new Uri(TorrentDescriptionUrl + id);
                    output("Details: " + detailsLink.AbsoluteUri);

                    // Torrent Comments URL
                    Uri commentsLink = new Uri(TorrentCommentUrl + id);
                    output("Comments Link: " + commentsLink.AbsoluteUri);

                    // Torrent Download URL
                    Uri downloadLink = new Uri(TorrentDownloadUrl.Replace("{id}", id.ToString()).Replace("{passkey}", ConfigData.PassKey.Value));
                    output("Download Link: " + downloadLink.AbsoluteUri);

                    // Building release infos
                    var release = new ReleaseInfo();
                    release.Category        = MapTrackerCatToNewznab(categoryID.ToString());
                    release.Title           = name;
                    release.Seeders         = seeders;
                    release.Peers           = seeders + leechers;
                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 345600;
                    release.PublishDate     = date;
                    release.Size            = size;
                    release.Guid            = detailsLink;
                    release.Comments        = commentsLink;
                    release.Link            = downloadLink;
                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError("Error, unable to parse result \n" + ex.StackTrace, ex);
            }

            // Return found releases
            return(releases);
        }
示例#27
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();

            var qc = new NameValueCollection
            {
                { "incldead", "1" }
            };

            if (query.IsImdbQuery)
            {
                qc.Add("titleonly", "0");
                qc.Add("search", query.ImdbID);
            }
            else
            {
                qc.Add("titleonly", "1");
                qc.Add("search", query.GetQueryString());
            }

            var cats = MapTorznabCapsToTrackers(query);

            if (cats.Count > 0)
            {
                foreach (var cat in cats)
                {
                    qc.Add($"c{cat}", "1");
                }
            }

            var searchUrl = SearchUrl + "?" + qc.GetQueryString();
            var results   = await RequestWithCookiesAndRetryAsync(searchUrl);

            if (results.IsRedirect) // re-login
            {
                await ApplyConfiguration(null);

                results = await RequestWithCookiesAndRetryAsync(searchUrl);
            }

            try
            {
                var parser = new HtmlParser();
                var dom    = parser.ParseDocument(results.ContentString);
                var rows   = dom.QuerySelectorAll("#torrents-table > tbody > tr");

                foreach (var row in rows.Skip(1))
                {
                    var qComments = row.QuerySelector(".br_right > a");
                    var comments  = new Uri(SiteLink + qComments.GetAttribute("href"));
                    var title     = qComments.QuerySelector("b").TextContent;

                    var qLink = row.QuerySelector("td:nth-child(4) > a");
                    if (qLink == null)
                    {
                        continue; // support/donation banner
                    }
                    var link = new Uri(SiteLink + qLink.GetAttribute("href"));

                    // dateString format "yyyy-MMM-dd hh:mm:ss" => eg "2015-04-25 23:38:12"
                    var dateString  = row.QuerySelector("td:nth-child(6) nobr").TextContent.Trim();
                    var publishDate = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);

                    var size     = ReleaseInfo.GetBytes(row.QuerySelector("td:nth-child(7)").InnerHtml.Split('<').First().Trim());
                    var files    = ParseUtil.GetLongFromString(row.QuerySelector("td:nth-child(7) > a").TextContent);
                    var grabs    = ParseUtil.GetLongFromString(row.QuerySelector("td:nth-child(8)").TextContent);
                    var seeders  = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(9)").TextContent);
                    var leechers = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(10)").TextContent);

                    var category = row.QuerySelector(".br_type > a").GetAttribute("href").Replace("browse.php?cat=", string.Empty);

                    var qImdb = row.QuerySelector("a[href*=\"www.imdb.com/\"]");
                    var imdb  = qImdb != null?ParseUtil.GetImdbID(qImdb.GetAttribute("href").Split('/').Last()) : null;

                    var release = new ReleaseInfo
                    {
                        Comments             = comments,
                        Guid                 = comments,
                        Title                = title,
                        Link                 = link,
                        PublishDate          = publishDate,
                        Size                 = size,
                        Seeders              = seeders,
                        Peers                = seeders + leechers,
                        Grabs                = grabs,
                        Files                = files,
                        Category             = MapTrackerCatToNewznab(category),
                        Imdb                 = imdb,
                        MinimumRatio         = 1,
                        MinimumSeedTime      = 172800, // 48 hours
                        UploadVolumeFactor   = 1,
                        DownloadVolumeFactor = 1
                    };
                    releases.Add(release);
                }
            }
            catch (Exception e)
            {
                OnParseError(results.ContentString, e);
            }

            return(releases);
        }
示例#28
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases     = new List <ReleaseInfo>();
            var searchString = query.GetQueryString();
            var searchUrl    = SearchUrl;

            if (!string.IsNullOrWhiteSpace(searchString))
            {
                searchUrl += "&search=" + WebUtilityHelpers.UrlEncode(searchString, Encoding);
            }
            string.Format(SearchUrl, WebUtilityHelpers.UrlEncode(searchString, Encoding));

            var cats = MapTorznabCapsToTrackers(query);

            if (cats.Count > 0)
            {
                foreach (var cat in cats)
                {
                    searchUrl += "&c" + cat + "=1";
                }
            }

            var response = await RequestStringWithCookies(searchUrl);

            try
            {
                CQ dom = response.Content;

                CQ qRows = dom[".browse > div > div"];

                foreach (var row in qRows)
                {
                    var release = new ReleaseInfo();

                    var qRow = row.Cq();

                    var debug = qRow.Html();

                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 172800;

                    var titleParts = qRow.Find(".bTitle").Text().Split('/');
                    if (titleParts.Length >= 2)
                    {
                        release.Title = titleParts[1].Trim();
                    }
                    else
                    {
                        release.Title = titleParts[0].Trim();
                    }

                    var qDetailsLink = qRow.Find("a[title][href^=\"details.php\"]");
                    release.Comments = new Uri(SiteLink + qDetailsLink.Attr("href"));
                    release.Link     = new Uri(SiteLink + qRow.Find("a[href^=\"download.php\"]").Attr("href"));
                    release.Guid     = release.Link;

                    var dateString = qRow.Find("div:last-child").Text().Trim();
                    var pattern    = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}";
                    var match      = Regex.Match(dateString, pattern);
                    if (match.Success)
                    {
                        release.PublishDate = DateTime.ParseExact(match.Value, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
                    }

                    var sizeStr = qRow.Find(".bSize").Text();
                    release.Size    = ReleaseInfo.GetBytes(sizeStr);
                    release.Seeders = ParseUtil.CoerceInt(qRow.Find(".bUping").Text().Trim());
                    release.Peers   = release.Seeders + ParseUtil.CoerceInt(qRow.Find(".bDowning").Text().Trim());

                    var files = qRow.Find("div.bFiles").Get(0).LastChild.ToString();
                    release.Files = ParseUtil.CoerceInt(files);

                    var grabs = qRow.Find("div.bFinish").Get(0).LastChild.ToString();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    if (qRow.Find("img[src=\"/pic/free.jpg\"]").Length >= 1)
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    if (qRow.Find("img[src=\"/pic/triple.jpg\"]").Length >= 1)
                    {
                        release.UploadVolumeFactor = 3;
                    }
                    else if (qRow.Find("img[src=\"/pic/double.jpg\"]").Length >= 1)
                    {
                        release.UploadVolumeFactor = 2;
                    }
                    else
                    {
                        release.UploadVolumeFactor = 1;
                    }

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(response.Content, ex);
            }

            return(releases);
        }
示例#29
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();

            var qc = new List <KeyValuePair <string, string> > // NameValueCollection don't support cat[]=19&cat[]=6
            {
                { "st", "1" } // search in title
            };

            if (query.IsImdbQuery)
            {
                qc.Add("search", query.ImdbID);
                qc.Add("sd", "1"); // search in description
            }
            else
            {
                qc.Add("search", query.GetQueryString());
            }

            // parse categories and tags
            var catGroups = new HashSet <string>(); // HashSet instead of List to avoid duplicates
            var tagGroups = new HashSet <string>();
            var cats      = MapTorznabCapsToTrackers(query);

            foreach (var cat in cats)
            {
                // "cat[]=7&tags=x264"
                var cSplit = cat.Split('&');

                var gSplit = cSplit[0].Split('=');
                if (gSplit.Length > 1)
                {
                    catGroups.Add(gSplit[1]); // category = 7
                }
                if (cSplit.Length > 1)
                {
                    var tSplit = cSplit[1].Split('=');
                    if (tSplit.Length > 1)
                    {
                        tagGroups.Add(tSplit[1]); // tag = x264
                    }
                }
            }

            // add categories
            foreach (var cat in catGroups)
            {
                qc.Add("cat[]", cat);
            }

            // do not include too many tags as it'll mess with their servers
            if (tagGroups.Count < 7)
            {
                qc.Add("tags", string.Join(",", tagGroups));
                // if tags are specified match any
                // if no tags are specified match all, with any we get random results
                qc.Add("tf", tagGroups.Any() ? "any" : "all");
            }

            var searchUrl = SearchUrl + "?" + qc.GetQueryString();
            var response  = await RequestStringWithCookiesAndRetry(searchUrl);

            if (response.IsRedirect) // re-login
            {
                await ApplyConfiguration(null);

                response = await RequestStringWithCookiesAndRetry(searchUrl);
            }

            try
            {
                var parser = new HtmlParser();
                var dom    = parser.ParseDocument(response.Content);
                var rows   = dom.QuerySelectorAll("table > tbody > tr.browse");
                foreach (var row in rows)
                {
                    var qLink = row.Children[1].QuerySelector("a");
                    var title = qLink.GetAttribute("title");
                    if (qLink.QuerySelectorAll("span").Length == 1 && title.StartsWith("NEW! |"))
                    {
                        title = title.Substring(6).Trim();
                    }

                    if (!query.MatchQueryStringAND(title))
                    {
                        continue; // we have to skip bad titles due to tags + any word search
                    }
                    var comments    = new Uri(SiteLink + qLink.GetAttribute("href"));
                    var link        = new Uri(SiteLink + row.Children[2].QuerySelector("a").GetAttribute("href"));
                    var dateStr     = Regex.Replace(row.Children[5].InnerHtml, @"\<br[\s]{0,1}[\/]{0,1}\>", " ");
                    var publishDate = DateTimeUtil.FromTimeAgo(dateStr);
                    var files       = ParseUtil.CoerceInt(row.Children[3].TextContent);
                    var size        = ReleaseInfo.GetBytes(row.Children[7].TextContent);
                    var grabs       = ParseUtil.CoerceInt(row.Children[8].TextContent);
                    var seeders     = ParseUtil.CoerceInt(row.Children[9].TextContent);
                    var leechers    = ParseUtil.CoerceInt(row.Children[10].TextContent);
                    var cat         = row.FirstElementChild.FirstElementChild.GetAttribute("href").Replace("browse.php?", string.Empty);

                    var release = new ReleaseInfo
                    {
                        Title                = title,
                        Comments             = comments,
                        Guid                 = comments,
                        Link                 = link,
                        PublishDate          = publishDate,
                        Size                 = size,
                        Category             = MapTrackerCatToNewznab(cat),
                        Files                = files,
                        Grabs                = grabs,
                        Seeders              = seeders,
                        Peers                = leechers + seeders,
                        MinimumRatio         = 1,
                        MinimumSeedTime      = 172800, // 48 hours
                        DownloadVolumeFactor = 0,      // ratioless
                        UploadVolumeFactor   = 1
                    };

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(response.Content, ex);
            }
            return(releases);
        }
示例#30
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();

            // TODO: IMDB search is available but it requires to parse the details page
            var qc = new NameValueCollection
            {
                { "order_by", "time" },
                { "order_way", "desc" },
                { "action", "basic" },
                { "searchsubmit", "1" },
                { "searchstr", query.IsImdbQuery ? query.ImdbID : query.GetQueryString() }
            };

            var catList = MapTorznabCapsToTrackers(query);

            foreach (var cat in catList)
            {
                qc.Add($"filter_cat[{cat}]", "1");
            }

            var searchUrl = BrowseUrl + "?" + qc.GetQueryString();
            var results   = await RequestWithCookiesAsync(searchUrl);

            try
            {
                var parser = new HtmlParser();
                var doc    = parser.ParseDocument(results.ContentString);
                var rows   = doc.QuerySelectorAll("table.torrent_table > tbody > tr.torrent");
                foreach (var row in rows)
                {
                    var qDetailsLink = row.QuerySelector("a.torrent_name");
                    var year         = qDetailsLink.NextSibling.TextContent.Replace("[", "").Replace("]", "").Trim();
                    var tags         = row.QuerySelector("div.torrent_info").FirstChild.TextContent.Replace(" / ", " ").Trim();
                    var title        = $"{qDetailsLink.TextContent} {year} {tags}";
                    var description  = row.QuerySelector("div.tags").TextContent.Trim();
                    var details      = new Uri(SiteLink + qDetailsLink.GetAttribute("href"));
                    var torrentId    = qDetailsLink.GetAttribute("href").Split('=').Last();
                    var link         = new Uri(SiteLink + "torrents.php?action=download&id=" + torrentId);
                    var posterStr    = qDetailsLink.GetAttribute("data-cover");
                    var poster       = !string.IsNullOrWhiteSpace(posterStr) ? new Uri(qDetailsLink.GetAttribute("data-cover")) : null;

                    var files       = ParseUtil.CoerceLong(row.QuerySelector("td:nth-child(3)").TextContent);
                    var publishDate = DateTimeUtil.FromTimeAgo(row.QuerySelector("td:nth-child(4)").TextContent);
                    var size        = ReleaseInfo.GetBytes(row.QuerySelector("td:nth-child(5)").FirstChild.TextContent);
                    var grabs       = ParseUtil.CoerceLong(row.QuerySelector("td:nth-child(6)").TextContent);
                    var seeders     = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(7)").TextContent);
                    var leechers    = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(8)").TextContent);

                    var dlVolumeFactor = row.QuerySelector("strong.tl_free") != null ? 0 : 1;

                    var cat      = row.QuerySelector("td.cats_col > div").GetAttribute("class").Replace("tooltip cats_", "");
                    var category = new List <int> {
                        cat switch
                        {
                            "featurefilm" => TorznabCatType.Movies.ID,
                            "shortfilm" => TorznabCatType.Movies.ID,
                            "miniseries" => TorznabCatType.TV.ID,
                            "other" => TorznabCatType.Other.ID,
                            _ => throw new Exception($"Unknown category: {cat}")
                        }
                    };

                    // TODO: TMDb is also available
                    var qImdb = row.QuerySelector("a[href^=\"https://www.imdb.com\"]");
                    var imdb  = qImdb != null?ParseUtil.GetImdbID(qImdb.GetAttribute("href").Split('/').Last()) : null;

                    var release = new ReleaseInfo
                    {
                        MinimumRatio         = 1,
                        MinimumSeedTime      = 259200,
                        Description          = description,
                        Title                = title,
                        PublishDate          = publishDate,
                        Category             = category,
                        Link                 = link,
                        Details              = details,
                        Guid                 = link,
                        Imdb                 = imdb,
                        Poster               = poster,
                        Seeders              = seeders,
                        Peers                = leechers + seeders,
                        Size                 = size,
                        Grabs                = grabs,
                        Files                = files,
                        DownloadVolumeFactor = dlVolumeFactor,
                        UploadVolumeFactor   = 1
                    };
                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.ContentString, ex);
            }

            return(releases);
        }