Example #1
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            NameValueCollection qParams = new NameValueCollection();
            qParams.Add("cata", "yes");
            qParams.Add("sec", "jax");

            List<string> catList = MapTorznabCapsToTrackers(query);
            foreach (string cat in catList)
            {
                qParams.Add("c" + cat, "1");
            }

            if (!string.IsNullOrEmpty(query.SanitizedSearchTerm))
            {
                qParams.Add("search", query.GetQueryString());
            }

            string torrentSearchUrl = $"{SearchUrl}?{qParams.GetQueryString()}";

            var results = await RequestStringWithCookiesAndRetry(torrentSearchUrl);
            List<ReleaseInfo> releases = ParseResponse(results.Content);
            
            return releases;
        }
Example #2
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var releases = new List<ReleaseInfo>();
            var searchString = query.GetQueryString();

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

            queryCollection.Add("action", "browse");
            //queryCollection.Add("group_results", "0"); # results won't include all information
            queryCollection.Add("order_by", "time");
            queryCollection.Add("order_way", "desc");

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

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

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

            var response = await RequestStringWithCookiesAndRetry(searchUrl);

            if (response.IsRedirect || query.IsTest)
            {
                // re-login
                await ApplyConfiguration(null);
                response = await RequestStringWithCookiesAndRetry(searchUrl);
            }

            try
            {
                var json = JObject.Parse(response.Content);
                foreach (JObject r in json["response"]["results"])
                {
                    var groupTime = DateTimeUtil.UnixTimestampToDateTime(long.Parse((string)r["groupTime"]));
                    var groupName = HttpUtility.HtmlDecode((string)r["groupName"]);
                    var artist = (string)r["artist"];
                    var cover = (string)r["cover"];
                    var tags = r["tags"].ToList();
                    var groupYear = (string)r["groupYear"];
                    var releaseType = (string)r["releaseType"];

                    var release = new ReleaseInfo();

                    release.PublishDate = groupTime;

                    if (!string.IsNullOrEmpty(cover))
                        release.BannerUrl = new Uri(cover);

                    release.Title = "";
                    if (!string.IsNullOrEmpty(artist))
                        release.Title += artist + " - ";
                    release.Title += groupName;
                    if (!string.IsNullOrEmpty(groupYear))
                        release.Title += " [" + groupYear + "]";
                    if (!string.IsNullOrEmpty(releaseType))
                        release.Title += " [" + releaseType + "]";

                    release.Description = "";
                    if (tags != null)
                        release.Description += "Tags: " + string.Join(", ", tags) + "\n";

                    if (r["torrents"] is JArray)
                    {
                        foreach (JObject torrent in r["torrents"])
                        {
                            ReleaseInfo release2 = (ReleaseInfo)release.Clone();
                            FillReleaseInfoFromJson(release2, torrent);
                            releases.Add(release2);
                        }
                    }
                    else
                    {
                        FillReleaseInfoFromJson(release, r);
                        releases.Add(release);
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(response.Content, ex);
            }

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

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

            var searchUrl = SearchUrl + queryCollection.GetQueryString();

            var trackerCats = MapTorznabCapsToTrackers(query, mapChildrenCatsToParent: true);

            var results = await RequestStringWithCookiesAndRetry(searchUrl);
            try
            {
                CQ dom = results.Content;
                dom["#needseed"].Remove();
                var rows = dom["table[width='750'] > tbody"].Children();
                foreach (var row in rows.Skip(1))
                {

                    var release = new ReleaseInfo();

                    var qRow = row.Cq();
                    var qLink = qRow.Children().ElementAt(2).Cq().Children("a").First();

                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 172800;
                    release.Title = qLink.Attr("title");
                    release.Description = release.Title;
                    release.Guid = new Uri(SiteLink + qLink.Attr("href").TrimStart('/'));
                    release.Comments = release.Guid;
                    release.Link = new Uri(string.Format(DownloadUrl, qLink.Attr("href").Split('=')[1]));

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

                    // This tracker cannot search multiple cats at a time, so search all cats then filter out results from different cats
                    if (trackerCats.Count > 0 && !trackerCats.Contains(catNum))
                        continue;

                    var dateString = qRow.Children().ElementAt(5).Cq().Text().Trim();
                    var pubDate = DateTime.ParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
                    release.PublishDate = DateTime.SpecifyKind(pubDate, DateTimeKind.Local);

                    var sizeStr = qRow.Children().ElementAt(6).Cq().Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(qRow.Children().ElementAt(8).Cq().Text().Trim());
                    release.Peers = ParseUtil.CoerceInt(qRow.Children().ElementAt(9).Cq().Text().Trim()) + release.Seeders;

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

            return releases;
        }
Example #4
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var loggedInCheck = await RequestStringWithCookies(SearchUrl);
            if (!loggedInCheck.Content.Contains("/logout.php"))
            {
                //Cookie appears to expire after a period of time or logging in to the site via browser
                await DoLogin();
            }


            var releases = new List<ReleaseInfo>();

            NameValueCollection qParams = new NameValueCollection();

            if (!string.IsNullOrEmpty(query.GetQueryString()))
            {
                qParams.Add("search", query.GetQueryString());
            }

            List<string> catList = MapTorznabCapsToTrackers(query);
            foreach (string cat in catList)
            {
                qParams.Add("c" + cat, "1");
            }

            string urlSearch = SearchUrl;
            if (qParams.Count > 0)
            {
                urlSearch += $"?{qParams.GetQueryString()}";
            }

            var response = await RequestStringWithCookiesAndRetry(urlSearch);

            try
            {
                CQ dom = response.Content;
                var rows = dom["div[id='torrentTable'] > div[class='box torrentBox'] > div[class='boxContent'] > table > tbody > tr"];

                foreach (IDomObject row in rows)
                {
                    CQ torrentData = row.OuterHTML;
                    CQ cells = row.Cq().Find("td");

                    string title = torrentData.Find("a[class='torrent']").First().Text().Trim();
                    Uri link = new Uri(SiteLink + torrentData.Find("img[class='icos save']").First().Parent().Attr("href").Trim());
                    Uri guid = new Uri(SiteLink + torrentData.Find("a[class='torrent']").First().Attr("href").Trim().TrimStart('/'));
                    long size = ReleaseInfo.GetBytes(cells.Elements.ElementAt(4).Cq().Text());
                    int seeders = ParseUtil.CoerceInt(cells.Elements.ElementAt(5).Cq().Text());
                    int leechers = ParseUtil.CoerceInt(cells.Elements.ElementAt(6).Cq().Text());

                    string pubDateStr = torrentData.Find("span[class^='elapsedDate']").First().Attr("title").Trim().Replace(" at", "");
                    DateTime publishDate = DateTime.ParseExact(pubDateStr, "dddd, MMMM d, yyyy h:mmtt", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime();

                    long category = 0;
                    string cat = torrentData.Find("a[class='cat']").First().Attr("id").Trim();
                    long.TryParse(cat, out category);


                    var release = new ReleaseInfo();

                    release.Title = title;
                    release.Guid = guid;
                    release.Link = link;
                    release.PublishDate = publishDate;
                    release.Size = size;
                    release.Description = release.Title;
                    release.Seeders = seeders;
                    release.Peers = seeders + leechers;
                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 172800;
                    release.Category = MapTrackerCatToNewznab(category.ToString());
                    release.Comments = guid;

                    releases.Add(release);
                }

            }
            catch (Exception ex)
            {
                OnParseError(response.Content, ex);
            }
            return releases;
        }
Example #5
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var releases = new List<ReleaseInfo>();
            var searchString = query.GetQueryString();
            var searchUrl = BrowseUrl;
            var trackerCats = MapTorznabCapsToTrackers(query);
            var queryCollection = new NameValueCollection();

            // Tracker can only search OR return things in categories
            if (!string.IsNullOrWhiteSpace(searchString))
            {
                queryCollection.Add("search", searchString);
                queryCollection.Add("cat", "0");
                queryCollection.Add("sc", "1");
            }
            else
            {
                foreach (var cat in MapTorznabCapsToTrackers(query))
                {
                    queryCollection.Add("c" + cat, "1");
                }

                queryCollection.Add("incldead", "0");
            }

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

            // 15 results per page - really don't want to call the server twice but only 15 results per page is a bit crap!
            await ProcessPage(releases, searchUrl);
            await ProcessPage(releases, searchUrl + "&page=1");
            return releases;
        }
Example #6
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 = BrowseUrl;
            var queryCollection = new NameValueCollection();
            queryCollection.Add("showsearch", "1");
            queryCollection.Add("incldead", "1");
            queryCollection.Add("blah", "0");
            queryCollection.Add("orderby", "added");
            queryCollection.Add("sort", "desc");

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

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add("c" + cat, "1");
            }
            searchUrl += "?" + queryCollection.GetQueryString();

            var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);
            var results = response.Content;
            try
            {
                CQ dom = results;
                var rows = dom["table.tableinborder > tbody > tr:has(td.tableb)"];

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

                    var qDetailsLink = qRow.Find("a[href^=details.php?id=]").First();
                    release.Title = qDetailsLink.Attr("title");

                    if (!query.MatchQueryStringAND(release.Title))
                        continue;

                    var qCatLink = qRow.Find("a[href^=browse.php?cat=]").First();

                    // use negative indexes as if a user has "Wartezeit" there's an extra column after the title
                    var qSeeders = qRow.Find("td:nth-last-child(4)");
                    var qLeechers = qRow.Find("td:nth-last-child(3)");
                    var qDateStr = qRow.Find("td:nth-last-child(7)");
                    var qSize = qRow.Find("td:nth-last-child(6)");

                    var torrentId = qDetailsLink.Attr("href").Replace("&hit=1", "").Split('=')[1];

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

                    release.Link = new Uri(SiteLink + "download.php?torrent="+torrentId);
                    release.Comments = new Uri(SiteLink + qDetailsLink.Attr("href"));
                    release.Guid = release.Link;

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

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

                    var dateStr = qDateStr.Text();
                    var dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dd.MM.yyyyHH:mm:ss", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
                    DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
                    release.PublishDate = pubDateUtc;

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

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

                    if (qRow.Find("font[color=\"red\"]:contains(OnlyUp)").Length >= 1)
                        release.DownloadVolumeFactor = 0;
                    else
                        release.DownloadVolumeFactor = 1;

                    release.UploadVolumeFactor = 1;

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

            return releases;
        }
Example #7
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var releases = new List<ReleaseInfo>();
            var searchurls = new List<string>();
            var searchUrl = SearchUrl;// string.Format(SearchUrl, HttpUtility.UrlEncode()));
            var queryCollection = new NameValueCollection();
            var searchString = query.GetQueryString();


            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                searchUrl += "category%5B%5D=" + cat + "&";
            }


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



            queryCollection.Add("active", "0");
            queryCollection.Add("options", "0");

            searchUrl += queryCollection.GetQueryString().Replace("(", "%28").Replace(")", "%29"); // maually url encode brackets to prevent "hacking" detection


            var results = await RequestStringWithCookiesAndRetry(searchUrl);
            try
            {
                CQ dom = results.Content;
                ReleaseInfo release;

                var rows = dom[".mainblockcontenttt > tbody > tr:has(a[href^=\"details.php?id=\"])"];
                foreach (var row in rows)
                {
                    CQ qRow = row.Cq();

                    release = new ReleaseInfo();

                    release.Title = qRow.Find("td.mainblockcontent b a").Text();
                    release.Description = qRow.Find("td:nth-child(3) > span").Text();

                    if (0 != qRow.Find("td.mainblockcontent u").Length)
                    {
                        var imdbStr = qRow.Find("td.mainblockcontent u").Parent().First().Attr("href").Replace("http://www.imdb.com/title/tt", "").Replace("/", "");
                        long imdb;
                        if (ParseUtil.TryCoerceLong(imdbStr, out imdb))
                        {
                            release.Imdb = imdb;
                        }
                    }

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



                    int seeders, peers;
                    if (ParseUtil.TryCoerceInt(qRow.Find("td").Get(9).FirstChild.FirstChild.InnerText, out seeders))
                    {
                        release.Seeders = seeders;
                        if (ParseUtil.TryCoerceInt(qRow.Find("td").Get(10).FirstChild.FirstChild.InnerText, out peers))
                        {
                            release.Peers = peers + release.Seeders;
                        }
                    }

                    release.Grabs = ParseUtil.CoerceLong(qRow.Find("td:nth-child(12)").Text());

                    string fullSize = qRow.Find("td.mainblockcontent").Get(6).InnerText;
                    release.Size = ReleaseInfo.GetBytes(fullSize);

                    release.Guid = new Uri(SiteLink + qRow.Find("td.mainblockcontent b a").Attr("href"));
                    release.Link = new Uri(SiteLink + qRow.Find("td.mainblockcontent").Get(3).FirstChild.GetAttribute("href"));
                    release.Comments = new Uri(SiteLink + qRow.Find("td.mainblockcontent b a").Attr("href"));

                    string[] dateSplit = qRow.Find("td.mainblockcontent").Get(5).InnerHTML.Split(',');
                    string dateString = dateSplit[1].Substring(0, dateSplit[1].IndexOf('>'));
                    release.PublishDate = DateTime.Parse(dateString, CultureInfo.InvariantCulture);

                    string category = qRow.Find("td:eq(0) a").Attr("href").Replace("torrents.php?category=", "");
                    release.Category = MapTrackerCatToNewznab(category);

                    release.UploadVolumeFactor = 1;

                    if (qRow.Find("img[alt=\"Free Torrent\"]").Length >= 1)
                    { 
                        release.DownloadVolumeFactor = 0;
                        release.UploadVolumeFactor = 0;
                    }
                    else if (qRow.Find("img[alt=\"Silver Torrent\"]").Length >= 1)
                        release.DownloadVolumeFactor = 0.5;
                    else if (qRow.Find("img[alt=\"Bronze Torrent\"]").Length >= 1)
                        release.DownloadVolumeFactor = 0.75;
                    else if (qRow.Find("img[alt=\"Blue Torrent\"]").Length >= 1)
                        release.DownloadVolumeFactor = 0.25;
                    else
                        release.DownloadVolumeFactor = 1;

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

            return releases;
        }
Example #8
0
        /// <summary>
        /// Build query to process
        /// </summary>
        /// <param name="term">Term to search</param>
        /// <param name="query">Torznab Query for categories mapping</param>
        /// <param name="url">Search url for provider</param>
        /// <param name="page">Page number to request</param>
        /// <returns>URL to query for parsing and processing results</returns>
        private string buildQuery(string term, TorznabQuery query, string url, int page = 0)
        {
            var parameters = new NameValueCollection();
            List<string> categoriesList = MapTorznabCapsToTrackers(query);

            // If search term provided
            if (!string.IsNullOrWhiteSpace(term))
            {
                // Add search term
                parameters.Add("q", term);
            }
            else
            {
                parameters.Add("q", string.Empty);
                // Showing all torrents (just for output function)
                term = "all";
            }

            // Default parameters
            parameters.Add("exact", "0");
            parameters.Add("sort", "normal");
            parameters.Add("order", "desc");

            // Check if we are processing a new page
            if (page > 0)
            {
                // Adding page number to query
                parameters.Add("page", page.ToString());
            }

            // Loop on Categories needed
            foreach (string category in categoriesList)
            {
                // Add categories
                parameters.Add("c" + category, "1");
            }

            // Building our query 
            url += "?" + parameters.GetQueryString();

            output("\nBuilded query for \"" + term + "\"... " + url);

            // Return our search url
            return url;
        }
Example #9
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("dlable", "1");
            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;
            if (!string.IsNullOrWhiteSpace(results))
            {
                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;
        }
Example #10
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var releases = new List<ReleaseInfo>();
            var searchString = query.GetQueryString();
            var queryCollection = new NameValueCollection();

            queryCollection.Add("view", "0");
            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, CookieHeader);
            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();

                    //CQ qLink = qRow.Children().ElementAt(1).Cq().Children("a").ElementAt(1).Cq();
                    CQ qLink;
                    CQ qTmp = qRow.Children().ElementAt(1).Cq().Find("a");                    
                    if (qTmp.Length < 2) {
                        qLink = qRow.Children().ElementAt(1).Cq().Find("a").ElementAt(0).Cq();
                    } else {
                        qLink = qRow.Children().ElementAt(1).Cq().Find("a").ElementAt(1).Cq();
                    }

                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 172800;
                    release.Title = qLink.Attr("title");
                    release.Description = release.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();
                    //var pubDate = DateTime.ParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
                    release.PublishDate = Jackett.Utils.DateTimeUtil.FromTimeAgo(dateString);

                    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;

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

            return releases;
        }
Example #11
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 = BrowseUrl;
            var queryCollection = new NameValueCollection();
            queryCollection.Add("showsearch", "1");
            queryCollection.Add("incldead", "1");
            queryCollection.Add("orderby", "added");
            queryCollection.Add("sort", "desc");

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

            var cats = MapTorznabCapsToTrackers(query);
            string cat = "0";
            if (cats.Count == 1)
            {
                cat = cats[0];
            }
            queryCollection.Add("cat", cat);

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

            var response = await RequestStringWithCookies(searchUrl);
            var results = response.Content;
            try
            {
                CQ dom = results;
                var rows = dom["table.testtable> tbody > tr:has(td.tableb)"];

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

                    var qDetailsLink = qRow.Find("a[href^=details.php?id=]").First();
                    release.Title = qDetailsLink.Text();

                    if (!query.MatchQueryStringAND(release.Title))
                        continue;

                    var qCatLink = qRow.Find("a[href^=browse.php?cat=]").First();
                    var qSeeders = qRow.Find("td > table.testtable > tbody > tr > td > strong:eq(3)");
                    var qLeechers = qRow.Find("td > table.testtable > tbody > tr > td > strong:eq(4)");
                    var qDateStr = qRow.Find("td > table.testtable > tbody > tr > td:eq(6)");
                    var qSize = qRow.Find("td > table.testtable > tbody > tr > td > strong:eq(1)");
                    var qDownloadLink = qRow.Find("a[href*=download]").First();

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

                    var dlLink = qDownloadLink.Attr("href");
                    if(dlLink.Contains("javascript")) // depending on the user agent the DL link is a javascript call
                    {
                        var dlLinkParts = dlLink.Split(new char[] { '\'', ',' });
                        dlLink = SiteLink + "download/" + dlLinkParts[3] + "/" + dlLinkParts[5];
                    }
                    release.Link = new Uri(dlLink);
                    release.Comments = new Uri(SiteLink + qDetailsLink.Attr("href"));
                    release.Guid = release.Link;

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

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

                    var dateStr = qDateStr.Text().Replace('\xA0', ' ');
                    var dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dd.MM.yyyy HH:mm:ss", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
                    DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
                    release.PublishDate = pubDateUtc;

                    var files = qRow.Find("td:contains(Datei) > strong ~ strong").Text();
                    release.Files = ParseUtil.CoerceInt(files);

                    if (qRow.Find("img[title=\"OnlyUpload\"]").Length >= 1)
                        release.DownloadVolumeFactor = 0;
                    else
                        release.DownloadVolumeFactor = 1;

                    release.UploadVolumeFactor = 1;

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

            return releases;
        }
Example #12
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            List<ReleaseInfo> releases = new List<ReleaseInfo>();

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

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

            var cats = new List<string>();
            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                cats.AddRange(cat.Split(','));
            }
            foreach (var cat in cats.Distinct())
            {
                queryCollection.Add("c" + cat, "1");
            }

            searchUrl += queryCollection.GetQueryString();

            var results = await RequestStringWithCookiesAndRetry(searchUrl);
            await FollowIfRedirect(results);
            try
            {
                CQ dom = results.Content;
                var rows = dom["table.torrenttable > tbody > tr.browse_color"];
                foreach (var row in rows)
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 172800;

                    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).FirstChild.Cq();
                    release.Link = new Uri(SiteLink + "/" + qLink.Attr("href"));
                    var torrentID = qLink.Attr("href").Split('=').Last();

                    var descCol = row.ChildElements.ElementAt(3);
                    var qCommentLink = descCol.FirstChild.Cq();
                    release.Title = qCommentLink.Text();
                    release.Description = release.Title;
                    release.Comments = new Uri(SiteLink + "/" + qCommentLink.Attr("href"));
                    release.Guid = release.Comments;

                    var dateStr = descCol.ChildElements.Last().Cq().Text().Split('|').Last().ToLowerInvariant().Replace("ago.", "").Trim();
                    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).Cq().Text());
                    release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(10).Cq().Text()) + release.Seeders;

                    releases.Add(release);

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

            return releases;
        }
Example #13
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();
            queryCollection.Add("showsearch", "0");
            queryCollection.Add("incldead", "1");
            queryCollection.Add("blah", "0");
            queryCollection.Add("team", "0");
            queryCollection.Add("orderby", "added");
            queryCollection.Add("sort", "desc");

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

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add("c" + cat, "1");
            }
            searchUrl += "?" + queryCollection.GetQueryString();

            var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);
            var results = response.Content;
            try
            {
                CQ dom = results;
                var rows = dom["table.tableinborder[cellpadding=0] > tbody > tr"];

                foreach (var row in rows)
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio = 0.7;
                    release.MinimumSeedTime = 48 * 60 * 60;
                    var qRow = row.Cq();
                    var flagImgs = qRow.Find("table tbody tr: eq(0) td > img");
                    List<string> flags = new List<string>();
                    flagImgs.Each(flagImg => {
                        flags.Add(flagImg.GetAttribute("src").Replace("pic/torrent_", "").Replace(".gif", "").ToUpper());
                    });
                        
                    var titleLink = qRow.Find("table tbody tr:eq(0) td a:has(b)").First();
                    var DLLink = qRow.Find("td.tableb > a:has(img[title=\"Torrent herunterladen\"])").First();
                    release.Comments = new Uri(SiteLink + titleLink.Attr("href").Replace("&hit=1", ""));
                    release.Link = new Uri(SiteLink + DLLink.Attr("href"));
                    release.Title = titleLink.Text().Trim();

                    if (!query.MatchQueryStringAND(release.Title))
                        continue;

                    release.Description = String.Join(", ", flags);
                    release.Guid = release.Link;

                    var dateStr = qRow.Find("table tbody tr:eq(1) td:eq(4)").Html().Replace("&nbsp;", " ").Trim();
                    var dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dd.MM.yyyy HH:mm:ss", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
                    DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
                    release.PublishDate = pubDateUtc.ToLocalTime();

                    var sizeStr = qRow.Find("table tbody tr:eq(1) td b").First().Text().Trim();
                    release.Size = ReleaseInfo.GetBytes(sizeStr.Replace(",", "."));

                    release.Seeders = ParseUtil.CoerceInt(qRow.Find("table tbody tr:eq(1) td:eq(1) b:eq(0) font").Text().Trim());
                    release.Peers = ParseUtil.CoerceInt(qRow.Find("table tbody tr:eq(1) td:eq(1) b:eq(1) font").Text().Trim()) + release.Seeders;

                    var catId = qRow.Find("td:eq(0) a").First().Attr("href").Split('=')[1];
                    release.Category = MapTrackerCatToNewznab(catId);

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

                    var files = qRow.Find("td:has(a[href*=\"&filelist=1\"])> b:nth-child(2)").Text();
                    release.Files = ParseUtil.CoerceInt(files);

                    var grabs = qRow.Find("td:has(a[href*=\"&tosnatchers=1\"])> b:nth-child(1)").Text();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    if (qRow.Find("img[src=\"pic/torrent_ou.gif\"]").Length >= 1)
                        release.DownloadVolumeFactor = 0;
                    else
                        release.DownloadVolumeFactor = 1;

                    release.UploadVolumeFactor = 1;

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

            return releases;
        }
Example #14
0
        public 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);

                    int GroupCategory = 0;
                    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;
                            int Category = 0;
                            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.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;
        }
Example #15
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var releases = new List<ReleaseInfo>(); // Create new variable to hold release info list
            var releasesAppend = new List<ReleaseInfo>(); // Create new list to hold release info to be appended
            var searchString = query.GetQueryString(); // Get the query string
            var searchUrl = SearchUrl; // Get the search url
            var qParams = new NameValueCollection(); // Greate a new variable to hold query string parameters
            int i = 1; // Creaate new variable to control loop limit
            CQ csquery; // Create new csquery object for html selections

            // If exists then add the search parameter to the query string parameters
            if (!string.IsNullOrWhiteSpace(searchString))
            {
                qParams.Add("search", searchString);
            }

            // Add category parameters to the query string parameters
            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                qParams.Add("c" + cat, "1");
            }

            // Append the query string parameters to the search url
            if (qParams.Count > 0)
            {
                searchUrl += qParams.GetQueryString();
            }

            // Begin loop (if looped 10 times (10 page requests, each containing 25 torrents) or torrent with zero seeds is found then exist loop)
            while (i <= 10 && !releases.Exists(x => x.Seeders == 0))
            {
                // Execute web request to Speed.cd
                var response = await RequestStringWithCookiesAndRetry(searchUrl + "&p=" + i);

                try
                {
                    // Populate the csquery wiht the web request response content
                    csquery = response.Content;
                    // Query the cs object for the rows of the torrent table
                    var rows = csquery["#torrentTable > div > div.boxContent > table > tbody > tr"];

                    // Populate append variable with release info to append
                    releasesAppend = rows.Select(r => {
                        try {
                            string id = r.Attributes["id"].Remove(0, 2); // Get ID
                            int seeders = 0; int.TryParse(r.ChildNodes[5].Cq().Text(), out seeders); // Get seeders
                            int leechers = 0; int.TryParse(r.ChildNodes[6].Cq().Text(), out leechers); // Get leechers
                            long category; long.TryParse(csquery["a.cat", r].Attr("id").Trim(), out category); // Get category code

                            // Create release info
                            ReleaseInfo info = new ReleaseInfo()
                            {
                                Guid = new Uri(string.Format(CommentsUrl, id)),
                                Title = csquery["a.torrent", r].Text(),
                                Description = csquery["a.torrent", r].Text(),
                                Comments = new Uri(string.Format(CommentsUrl, id)),
                                Link = new Uri(string.Format(DownloadUrl, id)),
                                PublishDate = DateTime.ParseExact(csquery["span.elapsedDate", r].FirstOrDefault().Attributes["title"].Replace(" at", ""), "dddd, MMMM d, yyyy h:mmtt", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime(),
                                Size = ReleaseInfo.GetBytes(r.ChildNodes[4].InnerText),
                                Seeders = seeders,
                                Peers = seeders + leechers,
                                Category = MapTrackerCatToNewznab(category.ToString()),
                                MinimumSeedTime = 172800,
                                MinimumRatio = 1
                            };

                            // Return release info
                            return info;
                        } catch(Exception ex) {
                            // Log error if individual row parsing fails
                            logger.Error("Speed.cd row parsing error", ex, new { searchUrl, r.OuterHTML });
                            return null;
                        }
                    })
                    .Where(x => x != null) // Ensure that failed rows are not appended
                    .ToList<ReleaseInfo>(); // Convert results to list of release info

                    // Add the rows to the append to the releases list
                    releases.AddRange(releasesAppend);

                    // Increment to next page
                    i++;

                }
                catch (Exception ex)
                {
                    // Log parser error is entire routine fails
                    OnParseError(response.Content, ex);
                }

            }

            // Return the releases
            return releases;
        }
Example #16
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 = MapTrackerResultCatToNewznab(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;
        }
Example #17
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var releases = new List<ReleaseInfo>();
            var searchString = query.GetQueryString();
            var searchUrl = BrowseUrl;
            var trackerCats = MapTorznabCapsToTrackers(query);
            var queryCollection = new NameValueCollection();


            queryCollection.Add("search", string.IsNullOrWhiteSpace(searchString)? "" : searchString);
            if (trackerCats.Count > 1)
            {
               for (var ct = 0; ct < trackerCats.Count; ct++) queryCollection.Add("cat" + (ct+1), trackerCats.ElementAt(ct));
            } else
            {
                queryCollection.Add("cat", (trackerCats.Count == 1 ? trackerCats.ElementAt(0) : "0"));
            }
            //queryCollection.Add("cat", (trackerCats.Count == 1 ? trackerCats.ElementAt(0) : "0"));
            searchUrl += "?" + queryCollection.GetQueryString();
            await ProcessPage(releases, searchUrl);

            return releases;
        }
Example #18
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 = BrowseUrl;
            var queryCollection = new NameValueCollection();
            queryCollection.Add("showsearch", "1");
            queryCollection.Add("incldead", "1");
            queryCollection.Add("orderby", "added");
            queryCollection.Add("sort", "desc");

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

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add("c" + cat, "1");
            }
            searchUrl += "?" + queryCollection.GetQueryString();

            var response = await RequestStringWithCookies(searchUrl);
            var results = response.Content;
            try
            {
                CQ dom = results;
                var rows = dom["table.tableinborder > tbody > tr:has(td.tableb)"];

                foreach (var row in rows)
                {
                    var release = new ReleaseInfo();
                    var qRow = row.Cq();

                    var qDetailsLink = qRow.Find("a[href^=details.php?id=]").First();
                    release.Title = qDetailsLink.Attr("title");

                    if (!query.MatchQueryStringAND(release.Title))
                        continue;

                    var qCatLink = qRow.Find("a[href^=browse.php?cat=]").First();
                    var qDLLink = qRow.Find("a[href^=download.php?torrent=]").First();
                    var qSeeders = qRow.Find("span:contains(Seeder) > b:eq(0)");
                    var qLeechers = qRow.Find("span:contains(Seeder) > b:eq(1)");
                    var qDateStr = qRow.Find("td > table > tbody > tr > td:eq(7)").First();
                    var qSize = qRow.Find("span:contains(Volumen) > b:eq(0)").First();
                    var qOnlyUpload = qRow.Find("img[title=OnlyUpload]");

                    if(qOnlyUpload.Any())
                    {
                        release.MinimumRatio = 2;
                        release.MinimumSeedTime = 144 * 60 * 60;
                    }
                    else
                    {
                        release.MinimumRatio = 1;
                        release.MinimumSeedTime = 72 * 60 * 60;
                    }

                    var catStr = qCatLink.Attr("href").Split('=')[1];
                    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().Replace('\xA0', ' ');
                    DateTime 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 files = qRow.Find("a[href*=\"&filelist=1\"] ~ font ~ b").Text();
                    release.Files = ParseUtil.CoerceInt(files);

                    var grabs = qRow.Find("a[href*=\"&tosnatchers=1\"] ~ font ~ b").Text();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    if (qRow.Find("img[alt=\"OU\"]").Length >= 1)
                        release.DownloadVolumeFactor = 0;
                    else
                        release.DownloadVolumeFactor = 1;

                    release.UploadVolumeFactor = 1;

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

            return releases;
        }
Example #19
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 = BrowseUrl;
            var queryCollection = new NameValueCollection();
            queryCollection.Add("incldead", "1");
            queryCollection.Add("freeleech", "0");
            queryCollection.Add("inclexternal", "0");
            queryCollection.Add("lang", "0");

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

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add("c" + cat, "1");
            }
            searchUrl += "?" + queryCollection.GetQueryString();

            var response = await RequestStringWithCookies(searchUrl);
            var results = response.Content;
            try
            {
                CQ dom = results;
                var rows = dom["table.ttable_headinner > tbody > tr.t-row"];

                foreach (var row in rows)
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 90 * 60;

                    var qRow = row.Cq();

                    var qDetailsLink = qRow.Find("a[href^=torrents-details.php?id=]").First();
                    release.Title = qDetailsLink.Attr("title");

                    if (!query.MatchQueryStringAND(release.Title))
                        continue;

                    var qCatLink = qRow.Find("a[href^=torrents.php?cat=]").First();
                    var qDLLink = qRow.Find("a[href^=download.php]").First();
                    var qSeeders = qRow.Find("td:eq(6)");
                    var qLeechers = qRow.Find("td:eq(7)");
                    var qDateStr = qRow.Find("td:eq(9)").First();
                    var qSize = qRow.Find("td:eq(4)").First();

                    var catStr = qCatLink.Attr("href").Split('=')[1];
                    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();
                    DateTime dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dd.MM.yy HH:mm:ss", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);

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

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

                    if (qRow.Find("img[src=\"images/free.gif\"]").Length >= 1)
                        release.DownloadVolumeFactor = 0;
                    else
                        release.DownloadVolumeFactor = 1;

                    release.UploadVolumeFactor = 1;

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

            return releases;
        }
Example #20
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            List<ReleaseInfo> releases = new List<ReleaseInfo>();

            NameValueCollection qParams = new NameValueCollection();
            if (ConfigData.French.Value && !ConfigData.English.Value && !ConfigData.Spanish.Value)
            {
                qParams.Add("lang", "1");
            }
            else
            {
                if (!ConfigData.French.Value && ConfigData.English.Value && !ConfigData.Spanish.Value)
                {
                    qParams.Add("lang", "2");
                }
                else
                {
                    if (!ConfigData.French.Value && !ConfigData.English.Value && ConfigData.Spanish.Value)
                    {
                        qParams.Add("lang", "3");
                    }
                    else
                    {
                        qParams.Add("lang", "0");
                    }
                }
                     
            } 
                
            List<string> catList = MapTorznabCapsToTrackers(query);
            foreach (string cat in catList)
            {
                qParams.Add("cat", cat);
            }

            if (!string.IsNullOrEmpty(query.SanitizedSearchTerm))
            {
                qParams.Add("search", query.GetQueryString());
            }

            string queryStr = qParams.GetQueryString();
            string searchUrl = $"{TorrentSearchUrl}?incldead=0&freeleech=0&sort=id&order=ascdesc&{queryStr}";

            List<CQ> torrentRowList = new List<CQ>();

            var results = await RequestStringWithCookiesAndRetry(searchUrl);
            try
            {
                CQ fDom = results.Content;
                var firstPageRows = fDom["table[class='ttable_headinner'] > tbody > tr:not(:First-child)"];
                torrentRowList.AddRange(firstPageRows.Select(fRow => fRow.Cq()));

                //If a search term is used, follow upto the first 4 pages (initial plus 3 more)
                if (!string.IsNullOrWhiteSpace(query.GetQueryString()) && fDom["a[class='boutons']"].Filter("a[href*=&page=]").Length > 0)
                {
                    int pageLinkCount;
                    int.TryParse(fDom["a[class='boutons']"].Filter("a[href*=&page=]").Last().Attr("href").Split(new[] { "&page=" }, StringSplitOptions.None).LastOrDefault(), out pageLinkCount);
                    for (int i = 1; i < Math.Min(4, pageLinkCount + 1); i++)
                    {
                        var sResults = await RequestStringWithCookiesAndRetry($"{searchUrl}&page={i}");
                        CQ sDom = sResults.Content;
                        var additionalPageRows = sDom["table[class='ttable_headinner'] > tbody > tr:not(:First-child)"];
                        torrentRowList.AddRange(additionalPageRows.Select(sRow => sRow.Cq()));
                    }
                }

                foreach (CQ tRow in torrentRowList)
                {
                    long torrentId = 0;
                    string idTarget = "bookmarks.php?torrent=";
                    string id = tRow.Find("a[href*=" + idTarget + "]").First().Attr("href").Trim();
                    if (!string.IsNullOrEmpty(id) && id.Contains(idTarget))
                    {
                        long.TryParse(id.Substring(id.LastIndexOf(idTarget, StringComparison.Ordinal) + idTarget.Length), out torrentId);
                    }

                    if (torrentId <= 0) continue;

                    long category = 0;
                    string catTarget = "torrents.php?cat=";
                    string cat = tRow.Find("a[href*=" + catTarget + "]").First().Attr("href").Trim();
                    if (!string.IsNullOrEmpty(cat) && cat.Contains(catTarget))
                    {
                        long.TryParse(cat.Substring(cat.LastIndexOf(catTarget, StringComparison.Ordinal) + catTarget.Length), out category);
                    }

                    Uri guid = new Uri($"{SiteLink}torrents-details.php?hit=1&id={torrentId}");
                    Uri link = new Uri($"{SiteLink}download.php?hit=1&id={torrentId}");
                    Uri comments = new Uri($"{SiteLink}comments.php?type=torrent&id={torrentId}");
                    string title = tRow.Find("a[href*=torrents-details.php?id=]").First().Text().Trim();
                    string stats = tRow.Find("div[id=kt" + torrentId.ToString() + "]").First().Text();
                    string sizeStr = new Regex("Taille:(.*)Vitesse:").Match(stats).Groups[1].ToString().Trim();
                    string pubDateStr = new Regex("Ajout.:(.*)Compl.t.s").Match(stats).Groups[1].ToString().Trim();
                    DateTime pubDate = DateTime.ParseExact(pubDateStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToLocalTime();

                    string statistics = tRow.Find("a[href*=torrents-details.php?id=]").First().RenderSelection().Trim();
                    string startTag = "<table ";
                    string endTag = "</table>";
                    CQ statsCq = startTag + new Regex(startTag + "(.*)" + endTag).Match(statistics).Groups[1].ToString().Trim() + endTag;
                    int seeders;
                    int leechers;
                    int.TryParse(statsCq.Find("font[color=#05FC09]").First().Text(), out seeders);
                    int.TryParse(statsCq.Find("font[color=red]").First().Text(), out leechers);

                    var release = new ReleaseInfo();

                    release.Title = title;
                    release.Guid = guid;
                    release.Link = link;
                    release.PublishDate = pubDate;
                    release.Size = ReleaseInfo.GetBytes(sizeStr);
                    release.Description = title;
                    release.Seeders = seeders;
                    release.Peers = leechers + seeders;
                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 172800;
                    release.Category = MapTrackerCatToNewznab(category.ToString());
                    release.Comments = comments;

                    releases.Add(release);
                }

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

            return releases;
        }
Example #21
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(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 + 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;
        }
Example #22
0
        protected async Task<bool> DoLogin()
        {
            var Login = Definition.Login;

            if (Login == null)
                return false;

            if (Login.Method == "post")
            {
                var pairs = new Dictionary<string, string>();
                foreach (var Input in Definition.Login.Inputs)
                {
                    var value = applyGoTemplateText(Input.Value);
                    pairs.Add(Input.Key, value);
                }

                var LoginUrl = SiteLink + Login.Path;
                configData.CookieHeader.Value = null;
                var loginResult = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, SiteLink, true);
                configData.CookieHeader.Value = loginResult.Cookies;

                checkForLoginError(loginResult);
            }
            else if (Login.Method == "form")
            {
                var LoginUrl = SiteLink + Login.Path;

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

                var CaptchaConfigItem = (RecaptchaItem)configData.GetDynamic("Captcha");

                if (CaptchaConfigItem != null)
                { 
                    if (!string.IsNullOrWhiteSpace(CaptchaConfigItem.Cookie))
                    {
                        // for remote users just set the cookie and return
                        CookieHeader = CaptchaConfigItem.Cookie;
                        return true;
                    }

                    var CloudFlareCaptchaChallenge = landingResultDocument.QuerySelector("script[src=\"/cdn-cgi/scripts/cf.challenge.js\"]");
                    if (CloudFlareCaptchaChallenge != null)
                    {
                        var CloudFlareQueryCollection = new NameValueCollection();
                        CloudFlareQueryCollection["id"] = CloudFlareCaptchaChallenge.GetAttribute("data-ray");
                    
                        CloudFlareQueryCollection["g-recaptcha-response"] = CaptchaConfigItem.Value;
                        var ClearanceUrl = resolvePath("/cdn-cgi/l/chk_captcha?" + CloudFlareQueryCollection.GetQueryString());

                        var ClearanceResult = await RequestStringWithCookies(ClearanceUrl.ToString(), null, SiteLink);

                        if (ClearanceResult.IsRedirect) // clearance successfull
                        {
                            // request real login page again
                            landingResult = await RequestStringWithCookies(LoginUrl, null, SiteLink);
                            var htmlParser = new HtmlParser();
                            landingResultDocument = htmlParser.Parse(landingResult.Content);
                        }
                        else
                        {
                            throw new ExceptionWithConfigData(string.Format("Login failed: Cloudflare clearance failed using cookies {0}: {1}", CookieHeader, ClearanceResult.Content), configData);
                        }
                    }
                    else
                    {
                        pairs.Add("g-recaptcha-response", CaptchaConfigItem.Value);
                    }
                }

                var FormSelector = Login.Form;
                if (FormSelector == null)
                    FormSelector = "form";

                // landingResultDocument might not be initiated if the login is caused by a relogin during a query
                if (landingResultDocument == null)
                {
                    await GetConfigurationForSetup();
                }

                var form = landingResultDocument.QuerySelector(FormSelector);
                if (form == null)
                {
                    throw new ExceptionWithConfigData(string.Format("Login failed: No form found on {0} using form selector {1}", LoginUrl, FormSelector), configData);
                }

                var inputs = form.QuerySelectorAll("input");
                if (inputs == null)
                {
                    throw new ExceptionWithConfigData(string.Format("Login failed: No inputs found on {0} using form selector {1}", LoginUrl, FormSelector), configData);
                }

                var submitUrl = resolvePath(form.GetAttribute("action"));
                
                foreach (var input in inputs)
                {
                    var name = input.GetAttribute("name");
                    if (name == null)
                        continue;

                    var value = input.GetAttribute("value");
                    if (value == null)
                        value = "";

                    pairs[name] = value;
                }
   
                foreach (var Input in Definition.Login.Inputs)
                {
                    var value = applyGoTemplateText(Input.Value);
                    pairs[Input.Key] = value;
                }

                // automatically solve simpleCaptchas, if used
                var simpleCaptchaPresent = landingResultDocument.QuerySelector("script[src*=\"simpleCaptcha\"]");
                if(simpleCaptchaPresent != null)
                {
                    var captchaUrl = resolvePath("simpleCaptcha.php?numImages=1");
                    var simpleCaptchaResult = await RequestStringWithCookies(captchaUrl.ToString(), null, LoginUrl);
                    var simpleCaptchaJSON = JObject.Parse(simpleCaptchaResult.Content);
                    var captchaSelection = simpleCaptchaJSON["images"][0]["hash"].ToString();
                    pairs["captchaSelection"] = captchaSelection;
                    pairs["submitme"] = "X";
                }

                // clear landingResults/Document, otherwise we might use an old version for a new relogin (if GetConfigurationForSetup() wasn't called before)
                landingResult = null;
                landingResultDocument = null;

                WebClientStringResult loginResult = null;
                var enctype = form.GetAttribute("enctype");
                if (enctype == "multipart/form-data")
                {
                    var headers = new Dictionary<string, string>();
                    var boundary = "---------------------------" + (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds.ToString().Replace(".", "");
                    var bodyParts = new List<string>();

                    foreach (var pair in pairs)
                    {
                        var part = "--" + boundary + "\r\n" +
                          "Content-Disposition: form-data; name=\"" + pair.Key + "\"\r\n" +
                          "\r\n" +
                          pair.Value;
                        bodyParts.Add(part);
                    }

                    bodyParts.Add("--" + boundary + "--");

                    headers.Add("Content-Type", "multipart/form-data; boundary=" + boundary);
                    var body = string.Join("\r\n",  bodyParts);
                    loginResult = await PostDataWithCookies(submitUrl.ToString(), pairs, configData.CookieHeader.Value, SiteLink, headers, body);
                } else {
                    loginResult = await RequestLoginAndFollowRedirect(submitUrl.ToString(), pairs, configData.CookieHeader.Value, true, null, SiteLink, true);
                }

                configData.CookieHeader.Value = loginResult.Cookies;

                checkForLoginError(loginResult);
            }
            else if (Login.Method == "cookie")
            {
                configData.CookieHeader.Value = ((StringItem)configData.GetDynamic("cookie")).Value;
            }
            else
            {
                throw new NotImplementedException("Login method " + Definition.Login.Method + " not implemented");
            }
            return true;
        }
Example #23
0
        public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
        {
            var releases = new List<ReleaseInfo>();
            var searchString = query.GetQueryString();
            var queryUrl = SearchUrl;
            var queryCollection = new NameValueCollection();

            if (!string.IsNullOrWhiteSpace(searchString))
                queryCollection.Add("search", searchString);

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

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

            var results = await RequestStringWithCookiesAndRetry(queryUrl);

            // Check for being logged out
            if (results.IsRedirect)
                throw new AuthenticationException();

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

                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 172800;
                    release.Title = qRow.Find(".torrentName").Text();
                    release.Description = release.Title;
                    release.Guid = new Uri(SiteLink + qRow.Find(".torrentName").Attr("href"));
                    release.Comments = release.Guid;
                    release.Link = new Uri(SiteLink + qRow.Find(".dlLinksInfo > a").Attr("href"));

                    var sizeStr = qRow.Find(".sizeInfo").Text();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    var dateStr = qRow.Find(".ulInfo").Text().Split('|').Last().Trim();
                    var agoIdx = dateStr.IndexOf("ago");
                    if (agoIdx > -1)
                    {
                        dateStr = dateStr.Substring(0, agoIdx);
                    }
                    release.PublishDate = DateTimeUtil.FromTimeAgo(dateStr);

                    release.Seeders = ParseUtil.CoerceInt(qRow.Find(".seedersInfo").Text());
                    release.Peers = ParseUtil.CoerceInt(qRow.Find(".leechersInfo").Text()) + release.Seeders;

                    var cat = qRow.Find("td:eq(0) a").First().Attr("href").Substring(15);//browse.php?cat=24
                    release.Category = MapTrackerCatToNewznab(cat);

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }
            return releases;
        }
Example #24
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 "minimumratio":
                                        release.MinimumRatio = ParseUtil.CoerceDouble(value);
                                        break;
                                    case "minimumseedtime":
                                        release.MinimumSeedTime = ParseUtil.CoerceLong(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;
                                    case "rageid":
                                        Regex RageIDRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
                                        var RageIDMatch = RageIDRegEx.Match(value);
                                        var RageID = RageIDMatch.Groups[1].Value;
                                        release.RageID = ParseUtil.CoerceLong(RageID);
                                        break;
                                    case "tvdbid":
                                        Regex TVDBIdRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
                                        var TVDBIdMatch = TVDBIdRegEx.Match(value);
                                        var TVDBId = TVDBIdMatch.Groups[1].Value;
                                        release.TVDBId = ParseUtil.CoerceLong(TVDBId);
                                        break;
                                    case "banner":
                                        if(!string.IsNullOrWhiteSpace(value)) { 
                                            var bannerurl = resolvePath(value);
                                            release.BannerUrl = bannerurl;
                                        }
                                        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;
        }
Example #25
0
        /// <summary>
        /// Build query to process
        /// </summary>
        /// <param name="term">Term to search</param>
        /// <param name="query">Torznab Query for categories mapping</param>
        /// <param name="url">Search url for provider</param>
        /// <param name="page">Page number to request</param>
        /// <returns>URL to query for parsing and processing results</returns>
        private string BuildQuery(string term, TorznabQuery query, string url, int page = 0)
        {
            var parameters = new NameValueCollection();
            var categoriesList = MapTorznabCapsToTrackers(query);
            string searchterm = term;

            // Building our tracker query
            parameters.Add("incldead", "0");
            parameters.Add("fullsearch", "0");
            parameters.Add("scenerelease", "0");

            // If search term provided
            if (!string.IsNullOrWhiteSpace(term))
            {
                searchterm = "search=" + System.Web.HttpUtility.UrlEncode(term, Encoding.GetEncoding(28591));
            }
            else
            {
                // Showing all torrents (just for output function)
                searchterm = "search=";
                term = "all";
            }

            var CatAll = "main_cat[]=2";

        var CatTest = categoriesList.Count > 0 ? string.Join(",", categoriesList) : "";
            Output(CatTest);
            if (CatTest == "" || CatTest == "main_cat[]=2&sub2_cat[]=22,main_cat[]=2&sub2_cat[]=20")
            {
                CatTest = Uri.EscapeUriString(CatAll);
            }


            // Building our query
            url += "?" + searchterm + "&" + parameters.GetQueryString() + "&" + CatTest;

            Output("\nBuilded query for \"" + term + "\"... " + url);

            // Return our search url
            return url;
        }
Example #26
0
        public 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("searchin", "title");
            queryCollection.Add("incldead", "1");
            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.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.tt > tbody > tr"];
                foreach (var row in rows.Skip(1))
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 72 * 60 * 60;

                    var qRow = row.Cq();

                    var qDetailsLink = qRow.Find("a[href^=details.php?id=]").First();
                    release.Title = qDetailsLink.Text().Trim();

                    // HoT search returns should support AND search but it simply doesn't work, so we AND filter it manualy
                    if (!query.MatchQueryStringAND(release.Title))
                        continue;

                    var qCatLink = qRow.Find("a[href^=browse.php?cat=]").First();
                    var qSeeders = qRow.Find("td:eq(8)");
                    var qLeechers = qRow.Find("td:eq(9)");
                    var qDownloadLink = qRow.Find("a[href^=download.php]").First();
                    var qTimeAgo = qRow.Find("td:eq(5)");
                    var qSize = qRow.Find("td:eq(6)");

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

                    release.Link = new Uri(SiteLink + qDownloadLink.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 = qTimeAgo.Text();
                    DateTime pubDateUtc;
                    var Timeparts = dateStr.Split(new char[] { ' ' }, 2)[1];
                    if (dateStr.StartsWith("Today "))
                        pubDateUtc = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + DateTime.ParseExact(dateStr.Split(new char[] { ' ' }, 2)[1], "hh:mm tt", System.Globalization.CultureInfo.InvariantCulture).TimeOfDay;
                    else if (dateStr.StartsWith("Yesterday "))
                        pubDateUtc = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) +
                            DateTime.ParseExact(dateStr.Split(new char[] { ' ' }, 2)[1], "hh:mm tt", System.Globalization.CultureInfo.InvariantCulture).TimeOfDay - TimeSpan.FromDays(1);
                    else
                        pubDateUtc = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "MMM d yyyy hh:mm tt", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);

                    release.PublishDate = pubDateUtc.ToLocalTime();

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

                    var grabs = qRow.Find("td:nth-child(8) > a").Html();
                    release.Grabs = ParseUtil.CoerceInt(grabs.Split('<')[0]);

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

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

            return releases;
        }
Example #27
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();

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

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

            searchUrl += queryCollection.GetQueryString();
            var response = await RequestStringWithCookiesAndRetry(searchUrl);
            if (response.IsRedirect)
            {
                await ApplyConfiguration(null);
                response = await RequestStringWithCookiesAndRetry(searchUrl);
            }

            try
            {
                var json = JObject.Parse(response.Content);
                foreach (JObject r in json["response"]["results"])
                {
                    DateTime pubDate = DateTime.MinValue;
                    double dateNum;
                    if (double.TryParse((string)r["groupTime"], out dateNum))
                        pubDate = UnixTimestampToDateTime(dateNum);

                    var groupName = (string)r["groupName"];

                    if (r["torrents"] is JArray)
                    {
                        foreach (JObject t in r["torrents"])
                        {
                            var release = new ReleaseInfo();
                            release.PublishDate = pubDate;
                            release.Title = groupName;
                            release.Description = groupName;
                            FillReleaseInfoFromJson(release, t);
                            releases.Add(release);
                        }
                    }
                    else
                    {
                        var release = new ReleaseInfo();
                        release.PublishDate = pubDate;
                        release.Title = groupName;
                        release.Description = groupName;
                        FillReleaseInfoFromJson(release, r);
                        releases.Add(release);
                    }

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

            return releases;
        }
Example #28
0
        /// <summary>
        /// Build query to process
        /// </summary>
        /// <param name="term">Term to search</param>
        /// <param name="query">Torznab Query for categories mapping</param>
        /// <param name="url">Search url for provider</param>
        /// <param name="page">Page number to request</param>
        /// <returns>URL to query for parsing and processing results</returns>
        private string buildQuery(string term, TorznabQuery query, string url, int page = 0)
        {
            var parameters = new NameValueCollection();
            List<string> categoriesList = MapTorznabCapsToTrackers(query);

            // Building our tracker query
            parameters.Add("afficher", "1");

            // If search term provided
            if (!string.IsNullOrWhiteSpace(term))
            {
                // Add search term
                parameters.Add("recherche", term);
            }
            else
            {
                // Showing all torrents (just for output function)
                term = "all";
            }

            // Building our tracker query
            parameters.Add("visible", (ConfigData.Dead.Value == true) ? "0" : "1");
            parameters.Add("freeleech", (ConfigData.Freeleech.Value == true) ? "2" : "0");
            parameters.Add("nuke", (ConfigData.Nuke.Value == true) ? "0" : "1");
            parameters.Add("3D", (ConfigData.ThreeD.Value == true) ? "2" : "0");
            parameters.Add("langue", (ConfigData.Language.Value == true) ? "2" : "0");

            // Loop on Categories needed
            foreach (string category in categoriesList)
            {
                    parameters.Add("c" + category, Convert.ToString(1));
            }

            // Check if we are processing a new page
            if (page > 0)
            {
                // Adding page number to query
                parameters.Add("page", page.ToString());
            }

            // Building our query -- Cannot use GetQueryString due to UrlEncode (generating wrong subcat[] param)
            url += "?" + parameters.GetQueryString();

            output("\nBuilded query for \"" + term + "\"... " + url);

            // Return our search url
            return url;
        }
Example #29
0
        public 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("action", "torrentstable");
            queryCollection.Add("viewtype", "0");
            queryCollection.Add("visiblecategories", "Action,Adventure,Animation,Biography,Comedy,Crime,Documentary,Drama,Eastern,Family,Fantasy,History,Holiday,Horror,Kids,Musical,Mystery,Romance,Sci-Fi,Short,Sports,Thriller,War,Western");
            queryCollection.Add("page", "1");
            queryCollection.Add("visibility", "showall");
            queryCollection.Add("compression", "showall");
            queryCollection.Add("sort", "added");
            queryCollection.Add("order", "DESC");
            queryCollection.Add("titleonly", "true");
            queryCollection.Add("packs", "showall");
            queryCollection.Add("bookmarks", "showall");
            queryCollection.Add("subscriptions", "showall");
            queryCollection.Add("skw", "showall");
            queryCollection.Add("advancedsearchparameters", "");

            if (!string.IsNullOrWhiteSpace(searchString))
            {
                // search keywords use OR by default and it seems like there's no way to change it, expect unwanted results
                queryCollection.Add("searchstring", searchString);
            }

            var cats = MapTorznabCapsToTrackers(query);
            var hiddenqualities = "";
            if (cats.Count > 0)
            {
                hiddenqualities = String.Join(",", categories.Where(cat => !cats.Contains(cat)));
            }
            queryCollection.Add("hiddenqualities", hiddenqualities);

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

            var results = await RequestStringWithCookiesAndRetry(searchUrl);
            try
            {
                CQ dom = results.Content;
                /*
                // parse logic for viewtype=1, unfortunately it's missing the release time so we can't use it
                var movieBlocks = dom["table.main"];
                foreach (var movieBlock in movieBlocks)
                {
                    var qMovieBlock = movieBlock.Cq();

                    var movieLink = qMovieBlock.Find("tr > td[class=colhead] > a").First();
                    var movieName = movieLink.Text();

                    var qDetailsBlock = qMovieBlock.Find("tr > td.torrentstd > table > tbody > tr");
                    var qDetailsHeader = qDetailsBlock.ElementAt(0);
                    var qDetailsTags = qDetailsBlock.ElementAt(1);
                    var qTorrents = qDetailsBlock.Find("td.moviestorrentstd > table > tbody > tr:eq(0)");

                    foreach (var torrent in qTorrents)
                    {
                        var qTorrent = torrent.Cq();
                        var qCatIcon = qTorrent.Find("td:eq(0) > img");
                        var qDetailsLink = qTorrent.Find("td:eq(1) > a:eq(0)");
                        var qSeeders = qTorrent.Find("td:eq(1) > b > a[alt=\"Number of Seeders\"]");
                        var qLeechers = qTorrent.Find("td:eq(1) > span[alt=\"Number of Leechers\"]");
                        var qDownloadLink = qTorrent.Find("td:eq(1) > a:has(img[alt=\"Download Torrent\"])");
                    }
                }
                */

                var rows = dom["table.main > tbody > tr"];
                foreach (var row in rows.Skip(1))
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio = 1;
                    release.MinimumSeedTime = 72 * 60 * 60;

                    var qRow = row.Cq();

                    var qDetailsLink = qRow.Find("td:eq(1) > a:eq(0)"); // link to the movie, not the actual torrent
                    release.Title = qDetailsLink.Attr("alt");

                    var qCatIcon = qRow.Find("td:eq(0) > img");
                    var qSeeders = qRow.Find("td:eq(8)");
                    var qLeechers = qRow.Find("td:eq(9)");
                    var qDownloadLink = qRow.Find("td > a:has(img[alt=\"Download Torrent\"])");
                    var qPudDate = qRow.Find("td:eq(5) > nobr");
                    var qSize = qRow.Find("td:eq(6)");

                    var catStr = qCatIcon.Attr("alt");
                    release.Category = MapTrackerCatToNewznab(catStr);
                    release.Link = new Uri(SiteLink + qDownloadLink.Attr("href").Substring(1));
                    release.Title = qDetailsLink.Attr("alt");
                    release.Comments = new Uri(SiteLink + qDetailsLink.Attr("href"));
                    release.Guid = release.Link;

                    var dateStr = qPudDate.Text().Trim();
                    DateTime pubDateUtc;
                    var Timeparts = dateStr.Split(new char[] { ' ' }, 2)[1];
                    if (dateStr.StartsWith("Today "))
                        pubDateUtc = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) + DateTime.ParseExact(dateStr.Split(new char[] { ' ' }, 2)[1], "hh:mm tt", System.Globalization.CultureInfo.InvariantCulture).TimeOfDay;
                    else if (dateStr.StartsWith("Yesterday "))
                        pubDateUtc = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified) +
                            DateTime.ParseExact(dateStr.Split(new char[] { ' ' }, 2)[1], "hh:mm tt", System.Globalization.CultureInfo.InvariantCulture).TimeOfDay - TimeSpan.FromDays(1);
                    else
                        pubDateUtc = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "MMM d yyyy hh:mm tt", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);

                    release.PublishDate = pubDateUtc.ToLocalTime();

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

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

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

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

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

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

            return releases;
        }
Example #30
0
        /// <summary>
        /// Build query to process
        /// </summary>
        /// <param name="term">Term to search</param>
        /// <param name="query">Torznab Query for categories mapping</param>
        /// <param name="url">Search url for provider</param>
        /// <param name="page">Page number to request</param>
        /// <returns>URL to query for parsing and processing results</returns>
        private string BuildQuery(string term, TorznabQuery query, string url, int page = 0)
        {
            var parameters = new NameValueCollection();
            var categoriesList = MapTorznabCapsToTrackers(query);

            // Building our tracker query
            parameters.Add("do", "search");

            // If search term provided
            if (!string.IsNullOrWhiteSpace(term))
            {
                // Add search term ~~ Strange search engine, need to replace space with dot for results !
                parameters.Add("keywords", term.Replace(' ', '.'));
            }
            else
            {
                // Showing all torrents (just for output function)
                parameters.Add("keywords", "");
                term = "all";
            }

            // Adding requested categories
            parameters.Add("category", categoriesList.Count > 0 ? string.Join(",", categoriesList) : "");

            // Building our tracker query
            parameters.Add("search_type", "t_name");

            // Check if we are processing a new page
            if (page > 1)
            {
                // Adding page number to query
                parameters.Add("page", page.ToString());
            }

            // Building our query
            url += "?" + parameters.GetQueryString();

            Output("\nBuilded query for \"" + term + "\"... " + url);

            // Return our search url
            return url;
        }