示例#1
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var results = await base.PerformQuery(query);

            // results must contain search terms
            results = results.Where(release => query.MatchQueryStringAND(release.Title));
            return(results);
        }
示例#2
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases         = new List <ReleaseInfo>();
            var episodeSearchUrl = string.Format(SearchAllUrl);
            var result           = await RequestWithCookiesAndRetryAsync(episodeSearchUrl);

            var xmlDoc = new XmlDocument();

            try
            {
                xmlDoc.LoadXml(result.ContentString);
                foreach (XmlNode node in xmlDoc.GetElementsByTagName("item"))
                {
                    var title = node.SelectSingleNode(".//*[local-name()='raw_title']").InnerText;
                    if (!query.MatchQueryStringAND(title))
                    {
                        continue;
                    }

                    // TODO: use Jackett.Common.Utils.TvCategoryParser.ParseTvShowQuality
                    // guess category from title
                    var category = title.Contains("720p") || title.Contains("1080p") ?
                                   TorznabCatType.TVHD.ID :
                                   TorznabCatType.TVSD.ID;

                    var magnetUri   = new Uri(node.SelectSingleNode("link")?.InnerText);
                    var publishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture);
                    var infoHash    = node.SelectSingleNode(".//*[local-name()='info_hash']").InnerText;
                    var commentsUri = new Uri(BrowseUrl + node.SelectSingleNode(".//*[local-name()='show_id']").InnerText);

                    var release = new ReleaseInfo
                    {
                        Title    = title,
                        Comments = commentsUri,
                        Category = new List <int> {
                            category
                        },
                        Guid                 = magnetUri,
                        PublishDate          = publishDate,
                        InfoHash             = infoHash,
                        MagnetUri            = magnetUri,
                        Size                 = 0,
                        Seeders              = 1,
                        Peers                = 2,
                        DownloadVolumeFactor = 0,
                        UploadVolumeFactor   = 1
                    };
                    releases.Add(release);
                }
            }
            catch (Exception e)
            {
                OnParseError(result.ContentString, e);
            }

            return(releases);
        }
示例#3
0
        private IEnumerable <ReleaseInfo> contentToReleaseInfos(TorznabQuery query, CQ dom)
        {
            List <ReleaseInfo> releases = new List <ReleaseInfo>();

            // Doesn't handle pagination yet...
            var rows = dom["div.panel-body > table.table > tbody > tr"];

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

                var qRow = row.Cq();
                release.Title = qRow.Find("td:nth-child(2) > a").First().Text().Trim();

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

                release.Guid     = new Uri(SiteLink + qRow.Find("td:nth-child(2) > a").First().Attr("href"));
                release.Comments = release.Guid;
                release.Link     = new Uri(SiteLink + qRow.Find("td:nth-child(3) > a").First().Attr("href"));
                var pubDateElement = qRow.Find("td:nth-child(2) > span").First();
                pubDateElement.Find("a").Remove(); // remove snatchinfo links (added after completing a torrent)
                var pubDate = pubDateElement.Text().Trim().Replace("Added: ", "");
                release.PublishDate = DateTime.Parse(pubDate).ToLocalTime();
                release.Category    = MapTrackerCatToNewznab(qRow.Find("td:nth-child(1) > a").First().Attr("href").Split('=')[1]);
                release.Size        = ReleaseInfo.GetBytes(qRow.Find("td:nth-child(7)").First().Text());
                release.Seeders     = ParseUtil.CoerceInt(qRow.Find("td:nth-child(9)").First().Text());
                release.Peers       = ParseUtil.CoerceInt(qRow.Find("td:nth-child(10)").First().Text()) + release.Seeders;

                var files = row.Cq().Find("td:nth-child(5)").Text();
                release.Files = ParseUtil.CoerceInt(files);

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

                if (row.Cq().Find("i.fa-star").Any())
                {
                    release.DownloadVolumeFactor = 0;
                }
                else
                {
                    release.DownloadVolumeFactor = 1;
                }

                release.UploadVolumeFactor = 1;

                releases.Add(release);
            }

            return(releases);
        }
示例#4
0
        private static IEnumerable <EraiRawsReleaseInfo> FilterForQuery(TorznabQuery query, IEnumerable <EraiRawsReleaseInfo> feedItems)
        {
            foreach (var fi in feedItems)
            {
                if (!query.MatchQueryStringAND(fi.Title))
                {
                    continue;
                }

                yield return(fi);
            }
        }
示例#5
0
        private async Task <IEnumerable <ReleaseInfo> > PerformSearch(TorznabQuery query)
        {
            var queryParameters = new NameValueCollection
            {
                { "search", query.SearchTerm },
                { "filter", "names,poster.url,code,torrents.list,season.year" },
            };
            var response = await RequestWithCookiesAndRetryAsync(Configuration.ApiLink.Value + "/searchTitles?" + queryParameters.GetQueryString());

            if (response.Status != HttpStatusCode.OK)
            {
                throw new WebException($"AniLibria search returned unexpected result. Expected 200 OK but got {response.Status}.", WebExceptionStatus.ProtocolError);
            }

            var results = ParseApiResults(response.ContentString);

            return(results.Where(release => query.MatchQueryStringAND(release.Title)));
        }
示例#6
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var results = await base.PerformQuery(query);

            // results must contain search terms
            results = results.Where(release => query.MatchQueryStringAND(release.Title));
            foreach (var release in results)
            {
                // SecretCinema loads artist with the movie director and the gazelleTracker abstract
                // places it in front of the movie separated with a dash.
                // We need to strip it or Radarr will not get a title match for automatic DL
                var artistEndsAt = release.Title.IndexOf(" - ");
                if (artistEndsAt > -1)
                {
                    release.Title = release.Title.Substring(artistEndsAt + 3);
                }
            }
            return(results);
        }
示例#7
0
        private async Task <IEnumerable <ReleaseInfo> > PerformSearch(TorznabQuery query)
        {
            // If the search terms contain [SubsPlease] or SubsPlease, remove them from the query sent to the API
            string searchTerm = Regex.Replace(query.SearchTerm, "\\[?SubsPlease\\]?\\s*", string.Empty, RegexOptions.IgnoreCase).Trim();

            // If the search terms contain a resolution, remove it from the query sent to the API
            Match resMatch = Regex.Match(searchTerm, "\\d{3,4}[p|P]");

            if (resMatch.Success)
            {
                searchTerm = searchTerm.Replace(resMatch.Value, string.Empty);
            }

            var queryParameters = new NameValueCollection
            {
                { "f", "search" },
                { "tz", "America/New_York" },
                { "s", searchTerm }
            };
            var response = await RequestWithCookiesAndRetryAsync(ApiEndpoint + queryParameters.GetQueryString());

            if (response.Status != HttpStatusCode.OK)
            {
                throw new WebException($"SubsPlease search returned unexpected result. Expected 200 OK but got {response.Status}.", WebExceptionStatus.ProtocolError);
            }

            var results         = ParseApiResults(response.ContentString);
            var filteredResults = results.Where(release => query.MatchQueryStringAND(release.Title));

            // If we detected a resolution in the search terms earlier, filter by it
            if (resMatch.Success)
            {
                filteredResults = filteredResults.Where(release => release.Title.IndexOf(resMatch.Value, StringComparison.OrdinalIgnoreCase) >= 0);
            }

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

            TimeZoneInfo.AdjustmentRule   adjustment  = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1), DateTime.MaxValue.Date, delta, startTransition, endTransition);
            TimeZoneInfo.AdjustmentRule[] adjustments = { adjustment };
            TimeZoneInfo 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);
        }
示例#9
0
        public List <ReleaseInfo> ParseResponse(TorznabQuery query, string htmlResponse)
        {
            var releases = new List <ReleaseInfo>();

            try
            {
                CQ dom = htmlResponse;

                var headerColumns = dom["table[class*='movehere']"].First().Find("tbody > tr > td[class='cat_Head']").Select(x => x.Cq().Text()).ToList();
                var categoryIndex = headerColumns.FindIndex(x => x.Equals("Type"));
                var nameIndex     = headerColumns.FindIndex(x => x.Equals("Name"));
                var sizeIndex     = headerColumns.FindIndex(x => x.Equals("Size"));
                var seedersIndex  = headerColumns.FindIndex(x => x.Equals("Seeders"));
                var leechersIndex = headerColumns.FindIndex(x => x.Equals("Leechers"));

                var rows = dom["tr.browse"];
                foreach (var row in rows)
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 172800; // 48 hours

                    var categoryCol = row.ChildElements.ElementAt(categoryIndex);
                    var catLink     = categoryCol.Cq().Find("a").Attr("href");
                    if (catLink != null)
                    {
                        var catId = new Regex(@"\?cat=(\d*)").Match(catLink).Groups[1].ToString().Trim();
                        release.Category = MapTrackerCatToNewznab(catId);
                    }

                    var descCol  = row.ChildElements.ElementAt(nameIndex);
                    var qDescCol = descCol.Cq();
                    var qLink    = qDescCol.Find("a");
                    release.Title = qLink.Text();
                    if (!query.MatchQueryStringAND(release.Title))
                    {
                        continue;
                    }

                    release.Comments = new Uri(SiteLink + "/" + qLink.Attr("href"));
                    release.Guid     = release.Comments;
                    var torrentId = qLink.Attr("href").Split('=')[1];
                    release.Link = new Uri(string.Format(DownloadUrl, torrentId));

                    release.PublishDate = DateTimeUtil.FromTimeAgo(descCol.ChildNodes.Last().InnerText);

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

                    release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(seedersIndex).Cq().Text().Trim());
                    release.Peers   = ParseUtil.CoerceInt(row.ChildElements.ElementAt(leechersIndex).Cq().Text().Trim()) + release.Seeders;

                    if (row.Cq().Find("font > b:contains(Freeleech)").Length >= 1)
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    release.UploadVolumeFactor = 1;

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

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

            var queryCollection = new NameValueCollection
            {
                {"searchstr", searchString},
                {"order_by", "time"},
                {"order_way", "desc"},
                {"action", "basic"},
                {"searchsubmit", "1"}
            };

            var i = 0;
            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                queryCollection.Add("artistcheck["+i+"]", cat);
                i++;
            }

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

            var results = await RequestStringWithCookies(searchUrl);
            try
            {
                string RowsSelector = ".torrent_table > tbody > tr";

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

                bool stickyGroup = false;
                string CategoryStr;
                ICollection<int> GroupCategory = null;
                string GroupTitle = null;
                //Nullable<DateTime> GroupPublishDate = null;

                foreach (var Row in Rows)
                {
                    if (Row.ClassList.Contains("torrent"))
                    {
                        // garbage rows
                        continue;
                    }
                    else if (Row.ClassList.Contains("group"))
                    {
                        stickyGroup = Row.ClassList.Contains("sticky");
                        var dispalyname = Row.QuerySelector("#displayname");
                        var qCat = Row.QuerySelector("td.cats_col > div");
                        CategoryStr = qCat.GetAttribute("title");
                        var qArtistLink = dispalyname.QuerySelector("#groupplatform > a");
                        if (qArtistLink != null)
                            CategoryStr = ParseUtil.GetArgumentFromQueryString(qArtistLink.GetAttribute("href"), "artistname");
                        GroupCategory = MapTrackerCatToNewznab(CategoryStr);

                        var qDetailsLink = dispalyname.QuerySelector("#groupname > a");
                        GroupTitle = qDetailsLink.TextContent;
                    }
                    else if (Row.ClassList.Contains("group_torrent"))
                    {
                        if (Row.QuerySelector("td.edition_info") != null) // ignore edition rows
                            continue;

                        var release = new ReleaseInfo();

                        release.MinimumRatio = 1;
                        release.MinimumSeedTime = 80 * 3600;

                        var qDetailsLink = Row.QuerySelector("a[href^=\"torrents.php?id=\"]");
                        var qDescription = qDetailsLink.QuerySelector("span.torrent_info_tags");
                        var qDLLink = Row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
                        var qTime = Row.QuerySelector("span.time");
                        // some users have an extra colum (8), we can't use nth-last-child
                        var qSize = Row.QuerySelector("td:nth-child(4)"); 
                        var qGrabs = Row.QuerySelector("td:nth-child(5)");
                        var qSeeders = Row.QuerySelector("td:nth-child(6)");
                        var qLeechers = Row.QuerySelector("td:nth-child(7)");
                        var qFreeLeech = Row.QuerySelector("strong.freeleech_label");
                        var qNeutralLeech = Row.QuerySelector("strong.neutralleech_label");
                        var RowTitle = Row.GetAttribute("title");
                        
                        var Time = qTime.GetAttribute("title");
                        release.PublishDate = DateTime.SpecifyKind(DateTime.ParseExact(Time, "MMM dd yyyy, HH:mm", CultureInfo.InvariantCulture), DateTimeKind.Unspecified).ToLocalTime();
                        release.Category = GroupCategory;

                        if (qDescription != null)
                            release.Description = qDescription.TextContent;

                        release.Title = qDetailsLink.TextContent;
                        release.Title = release.Title.Replace(", Freeleech!", "");
                        release.Title = release.Title.Replace(", Neutral Leech!", "");

                        if (stickyGroup) // AND match for sticky releases
                            if ((query.ImdbID == null || !TorznabCaps.SupportsImdbSearch) && !query.MatchQueryStringAND(release.Title))
                                continue;

                        var Size = qSize.TextContent;
                        if (string.IsNullOrEmpty(Size)) // external links, example BlazBlue: Calamity Trigger Manual - Guide [GameDOX - External Link]
                            continue;
                        release.Size = ReleaseInfo.GetBytes(Size);

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

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

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

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

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

            var pairs        = new Dictionary <string, string>();
            var searchString = query.GetQueryString();
            var searchUrl    = SearchUrl;

            pairs.Add("draw", "1");
            pairs.Add("columns[0][data]", "");
            pairs.Add("columns[0][name]", "");
            pairs.Add("columns[0][searchable]", "false");
            pairs.Add("columns[0][orderable]", "false");
            pairs.Add("columns[0][search][value]", "");
            pairs.Add("columns[0][search][regex]", "false");
            pairs.Add("columns[1][data]", "id");
            pairs.Add("columns[1][name]", "");
            pairs.Add("columns[1][searchable]", "false");
            pairs.Add("columns[1][orderable]", "true");
            pairs.Add("columns[1][search][value]", "");
            pairs.Add("columns[1][search][regex]", "false");
            pairs.Add("columns[2][data]", "cat");
            pairs.Add("columns[2][name]", "");
            pairs.Add("columns[2][searchable]", "false");
            pairs.Add("columns[2][orderable]", "true");
            pairs.Add("columns[2][search][value]", "");
            pairs.Add("columns[2][search][regex]", "false");
            pairs.Add("columns[3][data]", "name");
            pairs.Add("columns[3][name]", "");
            pairs.Add("columns[3][searchable]", "true");
            pairs.Add("columns[3][orderable]", "true");
            pairs.Add("columns[3][search][value]", "");
            pairs.Add("columns[3][search][regex]", "false");
            pairs.Add("columns[4][data]", "username");
            pairs.Add("columns[4][name]", "");
            pairs.Add("columns[4][searchable]", "true");
            pairs.Add("columns[4][orderable]", "true");
            pairs.Add("columns[4][search][value]", "");
            pairs.Add("columns[4][search][regex]", "false");
            pairs.Add("columns[5][data]", "cat-image");
            pairs.Add("columns[5][name]", "");
            pairs.Add("columns[5][searchable]", "false");
            pairs.Add("columns[5][orderable]", "true");
            pairs.Add("columns[5][search][value]", "");
            pairs.Add("columns[5][search][regex]", "false");
            pairs.Add("columns[6][data]", "cat-name");
            pairs.Add("columns[6][name]", "");
            pairs.Add("columns[6][searchable]", "false");
            pairs.Add("columns[6][orderable]", "true");
            pairs.Add("columns[6][search][value]", "");
            pairs.Add("columns[6][search][regex]", "false");
            pairs.Add("columns[7][data]", "imdbid");
            pairs.Add("columns[7][name]", "");
            pairs.Add("columns[7][searchable]", "true");
            pairs.Add("columns[7][orderable]", "true");
            pairs.Add("columns[7][search][value]", "");
            pairs.Add("columns[7][search][regex]", "false");
            pairs.Add("columns[8][data]", "genre");
            pairs.Add("columns[8][name]", "");
            pairs.Add("columns[8][searchable]", "false");
            pairs.Add("columns[8][orderable]", "true");
            pairs.Add("columns[8][search][value]", "");
            pairs.Add("columns[8][search][regex]", "false");
            pairs.Add("columns[9][data]", "added");
            pairs.Add("columns[9][name]", "");
            pairs.Add("columns[9][searchable]", "false");
            pairs.Add("columns[9][orderable]", "true");
            pairs.Add("columns[9][search][value]", "");
            pairs.Add("columns[9][search][regex]", "false");
            pairs.Add("columns[10][data]", "size");
            pairs.Add("columns[10][name]", "");
            pairs.Add("columns[10][searchable]", "false");
            pairs.Add("columns[10][orderable]", "true");
            pairs.Add("columns[10][search][value]", "");
            pairs.Add("columns[10][search][regex]", "false");
            pairs.Add("columns[11][data]", "rating");
            pairs.Add("columns[11][name]", "");
            pairs.Add("columns[11][searchable]", "false");
            pairs.Add("columns[11][orderable]", "true");
            pairs.Add("columns[11][search][value]", "");
            pairs.Add("columns[11][search][regex]", "false");
            pairs.Add("columns[12][data]", "comments");
            pairs.Add("columns[12][name]", "");
            pairs.Add("columns[12][searchable]", "false");
            pairs.Add("columns[12][orderable]", "true");
            pairs.Add("columns[12][search][value]", "");
            pairs.Add("columns[12][search][regex]", "false");
            pairs.Add("columns[13][data]", "numfiles");
            pairs.Add("columns[13][name]", "");
            pairs.Add("columns[13][searchable]", "false");
            pairs.Add("columns[13][orderable]", "true");
            pairs.Add("columns[13][search][value]", "");
            pairs.Add("columns[13][search][regex]", "false");
            pairs.Add("columns[14][data]", "seeders");
            pairs.Add("columns[14][name]", "");
            pairs.Add("columns[14][searchable]", "false");
            pairs.Add("columns[14][orderable]", "true");
            pairs.Add("columns[14][search][value]", "");
            pairs.Add("columns[14][search][regex]", "false");
            pairs.Add("columns[15][data]", "leechers");
            pairs.Add("columns[15][name]", "");
            pairs.Add("columns[15][searchable]", "false");
            pairs.Add("columns[15][orderable]", "true");
            pairs.Add("columns[15][search][value]", "");
            pairs.Add("columns[15][search][regex]", "false");
            pairs.Add("columns[16][data]", "to_go");
            pairs.Add("columns[16][name]", "");
            pairs.Add("columns[16][searchable]", "false");
            pairs.Add("columns[16][orderable]", "true");
            pairs.Add("columns[16][search][value]", "");
            pairs.Add("columns[16][search][regex]", "false");
            pairs.Add("columns[17][data]", "genre");
            pairs.Add("columns[17][name]", "");
            pairs.Add("columns[17][searchable]", "true");
            pairs.Add("columns[17][orderable]", "true");
            pairs.Add("columns[17][search][value]", "");
            pairs.Add("columns[17][search][regex]", "false");
            pairs.Add("order[0][column]", "9");
            pairs.Add("order[0][dir]", "desc");
            pairs.Add("start", "0");
            pairs.Add("length", "100");
            pairs.Add("visible", "1");
            pairs.Add("uid", "-1");
            pairs.Add("genre", "");

            pairs.Add("cats", string.Join(",+", MapTorznabCapsToTrackers(query)));

            if (query.ImdbID != null)
            {
                pairs.Add("search[value]", query.ImdbID);
                pairs.Add("search[regex]", "false");
            }
            else if (!string.IsNullOrWhiteSpace(searchString))
            {
                pairs.Add("search[value]", searchString);
                pairs.Add("search[regex]", "false");
            }

            var results = await PostDataWithCookiesAndRetry(searchUrl, pairs);

            try
            {
                var json = JObject.Parse(results.Content);
                foreach (var row in json["data"])
                {
                    var release = new ReleaseInfo();
                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 72 * 24 * 60 * 60;

                    var hParser   = new HtmlParser();
                    var hName     = hParser.Parse(row["name"].ToString());
                    var hComments = hParser.Parse(row["comments"].ToString());
                    var hNumfiles = hParser.Parse(row["numfiles"].ToString());
                    var hSeeders  = hParser.Parse(row["seeders"].ToString());
                    var hLeechers = hParser.Parse(row["leechers"].ToString());

                    var hDetailsLink  = hName.QuerySelector("a[href^=\"details.php?id=\"]");
                    var hCommentsLink = hComments.QuerySelector("a");
                    var hDownloadLink = hName.QuerySelector("a[title=\"Download Torrent\"]");

                    release.Title = hDetailsLink.TextContent;
                    if (query.ImdbID == null && !query.MatchQueryStringAND(release.Title))
                    {
                        continue;
                    }

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

                    release.Description = row["genre"].ToString();

                    var poster = row["poster"].ToString();
                    if (!string.IsNullOrWhiteSpace(poster))
                    {
                        var posterurl = poster;
                        if (!poster.StartsWith("http"))
                        {
                            posterurl = SiteLink + poster;
                        }
                        release.BannerUrl = new Uri(posterurl);
                    }

                    release.Size = ReleaseInfo.GetBytes(row["size"].ToString());
                    var imdbId = row["imdbid"].ToString();
                    if (imdbId.StartsWith("tt"))
                    {
                        release.Imdb = ParseUtil.CoerceLong(imdbId.Substring(2));
                    }

                    var added = row["added"].ToString().Replace("<br>", " ");
                    release.PublishDate = DateTimeUtil.FromUnknown(added);

                    var catid = row["catid"].ToString();
                    release.Category = MapTrackerCatToNewznab(catid);

                    release.Seeders = ParseUtil.CoerceInt(hSeeders.QuerySelector("a").TextContent);
                    release.Peers   = ParseUtil.CoerceInt(hLeechers.QuerySelector("a").TextContent) + release.Seeders;

                    release.Files = ParseUtil.CoerceInt(hNumfiles.QuerySelector("a").TextContent);

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

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

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

            //var categoryMapping = MapTorznabCapsToTrackers(query).Distinct().ToList();
            var qc = new List <KeyValuePair <string, string> > // NameValueCollection don't support cat[]=19&cat[]=6
            {
                { "itemsPerPage", "100" },
                { "sort", "torrent.createdAt" },
                { "direction", "desc" }
            };

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                qc.Add("categories[]", cat);
            }

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

            if (string.IsNullOrWhiteSpace(_token)) // fist time login
            {
                await RenewalTokenAsync();
            }

            var searchUrl = SearchUrl + "?" + qc.GetQueryString();
            var response  = await RequestWithCookiesAsync(searchUrl, headers : GetSearchHeaders());

            if (response.Status == HttpStatusCode.Unauthorized)
            {
                await RenewalTokenAsync(); // re-login

                response = await RequestWithCookiesAsync(searchUrl, headers : GetSearchHeaders());
            }
            else if (response.Status != HttpStatusCode.OK)
            {
                throw new Exception($"Unknown error in search: {response.ContentString}");
            }

            try
            {
                var rows = JArray.Parse(response.ContentString);
                foreach (var row in rows)
                {
                    var id          = row.Value <string>("id");
                    var link        = new Uri($"{SiteLink}api/torrent/{id}/download");
                    var urlStr      = row.Value <string>("url");
                    var details     = new Uri(urlStr);
                    var publishDate = DateTime.Parse(row.Value <string>("created_at"), CultureInfo.InvariantCulture);
                    var cat         = row.Value <JToken>("category").Value <string>("id");

                    // "description" field in API has too much HTML code
                    var description = row.Value <string>("short_description");

                    var posterStr = row.Value <string>("poster");
                    var poster    = Uri.TryCreate(posterStr, UriKind.Absolute, out var posterUri) ? posterUri : null;

                    var dlVolumeFactor = row.Value <double>("download_volume_factor");
                    var ulVolumeFactor = row.Value <double>("upload_volume_factor");

                    var title = row.Value <string>("name");
                    // fix for #10883
                    if (UseP2PReleaseName && !string.IsNullOrWhiteSpace(row.Value <string>("p2p_release_name")))
                    {
                        title = row.Value <string>("p2p_release_name");
                    }

                    if (!query.IsImdbQuery && !query.MatchQueryStringAND(title))
                    {
                        continue;
                    }

                    var release = new ReleaseInfo
                    {
                        Title                = title,
                        Link                 = link,
                        Details              = details,
                        Guid                 = details,
                        Category             = MapTrackerCatToNewznab(cat),
                        PublishDate          = publishDate,
                        Description          = description,
                        Poster               = poster,
                        Size                 = row.Value <long>("size"),
                        Grabs                = row.Value <long>("times_completed"),
                        Seeders              = row.Value <int>("seeders"),
                        Peers                = row.Value <int>("leechers") + row.Value <int>("seeders"),
                        DownloadVolumeFactor = dlVolumeFactor,
                        UploadVolumeFactor   = ulVolumeFactor,
                        MinimumRatio         = 1,
                        MinimumSeedTime      = 172800 // 48 hours
                    };

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(response.ContentString, ex);
            }
            return(releases);
        }
示例#13
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 globalFreeleech = dom.Find("div > img[alt=\"Only Upload\"][title^=\"ONLY UPLOAD \"]").Any();
                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 (globalFreeleech)
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else 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);
        }
示例#14
0
        private List <ReleaseInfo> ParseResponse(TorznabQuery query, string htmlResponse)
        {
            var releases = new List <ReleaseInfo>();

            try
            {
                var parser = new HtmlParser();
                var dom    = parser.ParseDocument(htmlResponse);

                var table = dom.QuerySelector("table.movehere");
                if (table == null)
                {
                    return(releases); // no results
                }
                var headerColumns = table.QuerySelectorAll("tbody > tr > td.cat_Head")
                                    .Select(x => x.TextContent).ToList();
                var categoryIndex = headerColumns.FindIndex(x => x.Equals("Type"));
                var nameIndex     = headerColumns.FindIndex(x => x.Equals("Name"));
                var sizeIndex     = headerColumns.FindIndex(x => x.Equals("Size"));
                var seedersIndex  = headerColumns.FindIndex(x => x.Equals("Seeders"));
                var leechersIndex = headerColumns.FindIndex(x => x.Equals("Leechers"));

                var rows = dom.QuerySelectorAll("tr.browse");
                foreach (var row in rows)
                {
                    // TODO convert to initializer
                    var release = new ReleaseInfo();
                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 172800; // 48 hours

                    var qCatLink = row.Children[categoryIndex].QuerySelector("a");
                    if (qCatLink != null)
                    {
                        var catId = new Regex(@"\?cat=(\d*)").Match(qCatLink.GetAttribute("href")).Groups[1].ToString().Trim();
                        release.Category = MapTrackerCatToNewznab(catId);
                    }

                    var qDescCol = row.Children[nameIndex];
                    var qLink    = qDescCol.QuerySelector("a");
                    release.Title = qLink.TextContent;
                    if (!query.MatchQueryStringAND(release.Title))
                    {
                        continue;
                    }

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

                    var torrentId = qLink.GetAttribute("href").Split('=')[1];
                    release.Link = new Uri(string.Format(DownloadUrl, torrentId));

                    release.PublishDate = DateTimeUtil.FromTimeAgo(qDescCol.ChildNodes.Last().TextContent);

                    var sizeStr = row.Children[sizeIndex].TextContent;
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(row.Children[seedersIndex].TextContent.Trim());
                    release.Peers   = ParseUtil.CoerceInt(row.Children[leechersIndex].TextContent.Trim()) + release.Seeders;

                    release.DownloadVolumeFactor = row.QuerySelector("font > b:contains(Freeleech)") != null ? 0 : 1;
                    release.UploadVolumeFactor   = 1;

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

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

            searchString = Regex.Replace(searchString, @"(^|\s)-", " "); // remove dashes at the beginning of keywords as they exclude search strings (see issue #3096)
            var searchUrl = SearchUrl;

            if (!string.IsNullOrWhiteSpace(searchString))
            {
                searchUrl += "query/" + WebUtility.UrlEncode(searchString) + "/";
            }
            string.Format(SearchUrl, WebUtility.UrlEncode(searchString));

            var cats = MapTorznabCapsToTrackers(query);

            if (cats.Count > 0)
            {
                searchUrl += "categories/";
                foreach (var cat in cats)
                {
                    if (!searchUrl.EndsWith("/"))
                    {
                        searchUrl += ",";
                    }
                    searchUrl += cat;
                }
            }
            else
            {
                searchUrl += "newfilter/2"; // include 0day and music
            }

            var results = await RequestStringWithCookiesAndRetry(searchUrl);

            if (results.Content.Contains("/user/account/login"))
            {
                //Cookie appears to expire after a period of time or logging in to the site via browser
                await DoLogin();

                results = await RequestStringWithCookiesAndRetry(searchUrl);
            }

            try
            {
                dynamic jsonObj = JsonConvert.DeserializeObject(results.Content);

                foreach (var torrent in jsonObj.torrentList)
                {
                    var release = new ReleaseInfo();

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

                    release.Guid     = new Uri(SiteLink + "torrent/" + torrent.fid);
                    release.Comments = release.Guid;
                    release.Title    = torrent.name;

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

                    release.Link = new Uri(SiteLink + "download/" + torrent.fid + "/" + torrent.filename);

                    release.PublishDate = DateTime.ParseExact(torrent.addedTimestamp.ToString(), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);

                    release.Size = (long)torrent.size;

                    release.Seeders = ParseUtil.CoerceInt(torrent.seeders.ToString());
                    release.Peers   = release.Seeders + ParseUtil.CoerceInt(torrent.leechers.ToString());

                    release.Category = MapTrackerCatToNewznab(torrent.categoryID.ToString());

                    release.Grabs = ParseUtil.CoerceInt(torrent.completed.ToString());

                    release.Imdb = ParseUtil.GetImdbID(torrent.imdbID.ToString());

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

                    // look at tags for freeleech #6579
                    // "tags": ["comedy","Family","FREELEECH"],
                    if (torrent.tags.ToString().Contains("FREELEECH"))
                    {
                        release.DownloadVolumeFactor = 0;
                    }

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

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

            var cats = MapTorznabCapsToTrackers(query);

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

            var catStr = string.Join(";", cats);

            queryUrl += "?" + catStr;

            if (!string.IsNullOrWhiteSpace(query.ImdbID))
            {
                queryUrl += ";q=" + query.ImdbID;
            }
            else
            {
                queryUrl += ";q=" + WebUtilityHelpers.UrlEncode(searchString, Encoding);
            }

            var results = await RequestStringWithCookiesAndRetry(queryUrl);

            // Check for being logged out
            if (results.IsRedirect)
            {
                if (results.RedirectingTo.Contains("login.php"))
                {
                    throw new ExceptionWithConfigData("Login failed, please reconfigure the tracker to update the cookies", configData);
                }
                else
                {
                    throw new ExceptionWithConfigData(string.Format("Got a redirect to {0}, please adjust your the alternative link", results.RedirectingTo), configData);
                }
            }

            try
            {
                dynamic json = JsonConvert.DeserializeObject <dynamic>(results.Content);

                foreach (var torrent in json)
                {
                    var release = new ReleaseInfo();

                    release.Title = torrent.name;
                    if ((query.ImdbID == null || !TorznabCaps.SupportsImdbMovieSearch) && !query.MatchQueryStringAND(release.Title))
                    {
                        continue;
                    }

                    release.MinimumRatio    = 1;
                    release.MinimumSeedTime = 172800; // 48 hours
                    release.Category        = MapTrackerCatToNewznab(torrent.c.ToString());

                    var torrentID = (long)torrent.t;
                    release.Comments    = new Uri(SiteLink + "details.php?id=" + torrentID);
                    release.Guid        = release.Comments;
                    release.Link        = new Uri(SiteLink + "download.php/" + torrentID + "/" + torrentID + ".torrent");
                    release.PublishDate = DateTimeUtil.UnixTimestampToDateTime((long)torrent.ctime).ToLocalTime();

                    release.Size    = (long)torrent.size;
                    release.Seeders = (int)torrent.seeders;
                    release.Peers   = release.Seeders + (int)torrent.leechers;
                    release.Files   = (long)torrent.files;
                    release.Grabs   = (long)torrent.completed;
                    var imdbId = (string)torrent["imdb-id"];
                    release.Imdb = ParseUtil.GetImdbID(imdbId);
                    var downloadMultiplier = (double?)torrent["download-multiplier"];
                    release.DownloadVolumeFactor = downloadMultiplier ?? 1;
                    release.UploadVolumeFactor   = 1;

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }
            return(releases);
        }
示例#17
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);
        }
示例#18
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            List <ReleaseInfo> releases = new List <ReleaseInfo>();
            Regex IMDBRegEx             = new Regex(@"tt(\d+)", RegexOptions.Compiled);

            var searchString            = query.GetQueryString();
            var searchUrl               = SearchUrl;
            var queryCollection         = new NameValueCollection();
            var searchStringIsImdbQuery = (ParseUtil.GetImdbID(searchString) != null);

            if (query.IsImdbQuery)
            {
                queryCollection.Add("search", query.ImdbID);
            }
            else if (searchStringIsImdbQuery)
            {
                queryCollection.Add("search", searchString);
            }
            else if (!string.IsNullOrWhiteSpace(searchString))
            {
                Regex ReplaceRegex = new Regex("[^a-zA-Z0-9]+");
                searchString = "%" + ReplaceRegex.Replace(searchString, "%") + "%";
                searchString = Regex.Replace(searchString, @"(%\d{3,4})[ip](%)", "$1$2"); // remove i/p from resolution tags (see #835)
                queryCollection.Add("search", searchString);
            }

            foreach (var cat in MapTorznabCapsToTrackers(query))
            {
                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, table.torrenttable > tbody > tr.highlight"];
                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();
                    if (!query.IsImdbQuery && !query.MatchQueryStringAND(release.Title))
                    {
                        continue;
                    }
                    release.Comments = new Uri(SiteLink + qCommentLink.Attr("href"));
                    release.Guid     = release.Comments;
                    release.Link     = new Uri($"{SiteLink}download.php?torrent={torrentId}");

                    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;

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

                    var grabs = qRow.Find("td:nth-child(9) > a").Get(0).FirstChild.ToString();
                    release.Grabs = ParseUtil.CoerceInt(grabs);

                    var imdbLink = qRow.Find("a[href*=\"imdb.com/title/\"]").Attr("href");
                    if (imdbLink != null)
                    {
                        var IMDBMatch = IMDBRegEx.Match(imdbLink);
                        release.Imdb = ParseUtil.CoerceLong(IMDBMatch.Groups[1].Value);
                    }

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

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

            return(releases);
        }
示例#19
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);
            }

            queryCollection.Add("incldead", "1");

            var searchUrl = SearchUrl + queryCollection.GetQueryString();

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

            var results = await RequestStringWithCookiesAndRetry(searchUrl);

            try
            {
                CQ dom = results.Content;
                dom["#needseed"].Remove();
                foreach (var table in dom["table[align=center] + br + table > tbody"])
                {
                    var rows = table.Cq().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");
                        if (!query.MatchQueryStringAND(release.Title))
                        {
                            continue;
                        }
                        release.Files    = ParseUtil.CoerceLong(qRow.Find("td:nth-child(4)").Text());
                        release.Grabs    = ParseUtil.CoerceLong(qRow.Find("td:nth-child(8)").Text());
                        release.Guid     = new Uri(qLink.Attr("href"));
                        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-ddHH: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;

                        var bgcolor = qRow.Attr("bgcolor");
                        if (bgcolor == "#DDDDDD")
                        {
                            release.DownloadVolumeFactor = 1;
                            release.UploadVolumeFactor   = 2;
                        }
                        else if (bgcolor == "#FFFF99")
                        {
                            release.DownloadVolumeFactor = 0;
                            release.UploadVolumeFactor   = 1;
                        }
                        else if (bgcolor == "#CCFF99")
                        {
                            release.DownloadVolumeFactor = 0;
                            release.UploadVolumeFactor   = 2;
                        }
                        else
                        {
                            release.DownloadVolumeFactor = 1;
                            release.UploadVolumeFactor   = 1;
                        }
                        releases.Add(release);
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

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

            var    cats = MapTorznabCapsToTrackers(query);
            string cat  = "0";

            if (cats.Count == 1)
            {
                cat = cats[0];
            }

            var queryCollection = new NameValueCollection();

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

            queryCollection.Add("cat", cat);
            queryCollection.Add("searchin", "0");
            queryCollection.Add("sort", "0");

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

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

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

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

            var results = response.Content;

            try
            {
                CQ  dom             = results;
                var globalFreeLeech = dom.Find("div.globalFreeLeech").Any();
                var rows            = dom[".torrentrow"];
                foreach (var row in rows)
                {
                    var release    = new ReleaseInfo();
                    var qRow       = row.Cq();
                    var qTitleLink = qRow.Find(".torrenttable:eq(1) a").First();
                    release.Title = qRow.Find(".torrenttable:eq(1) b").Text();
                    var longtitle = qRow.Find(".torrenttable:eq(1) a[title]").Attr("title");
                    if (!string.IsNullOrEmpty(longtitle) && !longtitle.Contains("<")) // releases with cover image have no full title
                    {
                        release.Title = longtitle;
                    }

                    if (query.ImdbID == null && !query.MatchQueryStringAND(release.Title))
                    {
                        continue;
                    }

                    release.Description = qRow.Find(".torrenttable:eq(1) > span > font.small").First().Text();

                    var tooltip = qTitleLink.Attr("title");
                    if (!string.IsNullOrEmpty(tooltip))
                    {
                        var ImgRegexp      = new Regex("src='(.*?)'");
                        var ImgRegexpMatch = ImgRegexp.Match(tooltip);
                        if (ImgRegexpMatch.Success)
                        {
                            release.BannerUrl = new Uri(ImgRegexpMatch.Groups[1].Value);
                        }
                    }

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

                    //22:05:3716/02/2013
                    var dateStr = qRow.Find(".torrenttable:eq(5)").Text().Trim() + " +0200";
                    release.PublishDate = DateTime.ParseExact(dateStr, "H:mm:ssdd/MM/yyyy zzz", CultureInfo.InvariantCulture);

                    var qLink = qRow.Find("a[href^=\"download.php?id=\"]").First();
                    release.Link = new Uri(SiteLink + qLink.Attr("href").Replace("&usetoken=1", ""));

                    var sizeStr = qRow.Find(".torrenttable:eq(6)").Text().Trim();
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(qRow.Find(".torrenttable:eq(8)").Text().Trim());
                    release.Peers   = ParseUtil.CoerceInt(qRow.Find(".torrenttable:eq(9)").Text().Trim()) + release.Seeders;

                    var catId = qRow.Find(".torrenttable:eq(0) a").First().Attr("href").Substring(15);
                    release.Category = MapTrackerCatToNewznab(catId);

                    var grabs = qRow.Find(".torrenttable:eq(7)").First().Get(0).FirstChild;
                    release.Grabs = ParseUtil.CoerceLong(catId);

                    if (globalFreeLeech || row.Cq().Find("img[alt=\"FreeLeech\"]").Any())
                    {
                        release.DownloadVolumeFactor = 0;
                    }
                    else
                    {
                        release.DownloadVolumeFactor = 1;
                    }

                    release.UploadVolumeFactor = 1;

                    // Skip Romanian releases
                    if (release.Category.Contains(TorznabCatType.MoviesForeign.ID) && !configData.IncludeRomanianReleases.Value)
                    {
                        continue;
                    }

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

            return(releases);
        }
示例#21
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases         = new List <ReleaseInfo>();
            var episodeSearchUrl = string.Format(SearchAllUrl);
            var result           = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);

            var xmlDoc = new XmlDocument();

            try
            {
                xmlDoc.LoadXml(result.Content);
                ReleaseInfo release;
                string      serie_title;

                foreach (XmlNode node in xmlDoc.GetElementsByTagName("item"))
                {
                    release = new ReleaseInfo();

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

                    serie_title   = node.SelectSingleNode(".//*[local-name()='raw_title']").InnerText;
                    release.Title = serie_title;

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

                    release.Comments = new Uri(node.SelectSingleNode("link").InnerText);

                    // Try to guess the category... I'm not proud of myself...
                    int category = 5030;
                    if (serie_title.Contains("720p"))
                    {
                        category = 5040;
                    }
                    release.Category = new List <int> {
                        category
                    };
                    var test = node.SelectSingleNode("enclosure");
                    release.Guid        = new Uri(test.Attributes["url"].Value);
                    release.PublishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture);

                    release.Description          = node.SelectSingleNode("description").InnerText;
                    release.InfoHash             = node.SelectSingleNode("description").InnerText;
                    release.Size                 = 0;
                    release.Seeders              = 1;
                    release.Peers                = 1;
                    release.DownloadVolumeFactor = 0;
                    release.UploadVolumeFactor   = 1;
                    release.MagnetUri            = new Uri(node.SelectSingleNode("link").InnerText);
                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(result.Content, ex);
            }

            return(releases);
        }
示例#22
0
        private List <ReleaseInfo> ParseTorrents(WebResult results, string episodeString, TorznabQuery query,
                                                 int alreadyFound, int limit, int previouslyParsedOnPage)
        {
            var releases = new List <ReleaseInfo>();

            try
            {
                var parser = new HtmlParser();
                var dom    = parser.ParseDocument(results.ContentString);
                var rows   = dom.QuerySelectorAll(".box_torrent").Skip(previouslyParsedOnPage).Take(limit - alreadyFound);

                var key = ParseUtil.GetArgumentFromQueryString(
                    dom.QuerySelector("link[rel=alternate]").GetAttribute("href"), "key");
                // Check torrents only till we reach the query Limit
                foreach (var row in rows)
                {
                    try
                    {
                        var torrentTxt = row.QuerySelector(".torrent_txt, .torrent_txt2").QuerySelector("a");
                        //if (torrentTxt == null) continue;
                        var infoLink = row.QuerySelector("a.infolink");
                        var imdbId   = ParseUtil.GetLongFromString(infoLink?.GetAttribute("href"));
                        var desc     = row.QuerySelector("span")?.GetAttribute("title") + " " +
                                       infoLink?.TextContent;
                        var torrentLink = SiteLink + torrentTxt.GetAttribute("href");
                        var downloadId  = ParseUtil.GetArgumentFromQueryString(torrentLink, "id");

                        //Build site links
                        var baseLink     = SiteLink + "torrents.php?action=details&id=" + downloadId;
                        var downloadLink = SiteLink + "torrents.php?action=download&id=" + downloadId;
                        var commentsUri  = new Uri(baseLink + "#comments");
                        var guidUri      = new Uri(baseLink);
                        var linkUri      = new Uri(QueryHelpers.AddQueryString(downloadLink, "key", key));

                        var seeders     = ParseUtil.CoerceInt(row.QuerySelector(".box_s2 a").TextContent);
                        var leechers    = ParseUtil.CoerceInt(row.QuerySelector(".box_l2 a").TextContent);
                        var publishDate = DateTime.Parse(
                            row.QuerySelector(".box_feltoltve2").InnerHtml.Replace("<br>", " "),
                            CultureInfo.InvariantCulture);
                        var sizeSplit = row.QuerySelector(".box_meret2").TextContent.Split(' ');
                        var size      = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0]));
                        var catLink   = row.QuerySelector("a:has(img[class='categ_link'])").GetAttribute("href");
                        var cat       = ParseUtil.GetArgumentFromQueryString(catLink, "tipus");
                        var title     = torrentTxt.GetAttribute("title");
                        // if the release name does not contain the language we add from the category
                        if (cat.Contains("hun") && !title.ToLower().Contains("hun"))
                        {
                            title += ".hun";
                        }

                        // Minimum seed time is 48 hours + 24 minutes (.4 hours) per GB of torrent size if downloaded in full.
                        // Or a 1.0 ratio on the torrent
                        var seedTime = TimeSpan.FromHours(48) +
                                       TimeSpan.FromMinutes(24 * ReleaseInfo.GigabytesFromBytes(size).Value);

                        var release = new ReleaseInfo
                        {
                            Title                = title,
                            Description          = desc.Trim(),
                            MinimumRatio         = 1,
                            MinimumSeedTime      = (long)seedTime.TotalSeconds,
                            DownloadVolumeFactor = 0,
                            UploadVolumeFactor   = 1,
                            Link        = linkUri,
                            Comments    = commentsUri,
                            Guid        = guidUri,
                            Seeders     = seeders,
                            Peers       = leechers + seeders,
                            Imdb        = imdbId,
                            PublishDate = publishDate,
                            Size        = size,
                            Category    = MapTrackerCatToNewznab(cat)
                        };
                        var banner = row.QuerySelector("img.infobar_ico")?.GetAttribute("onmouseover");
                        if (banner != null)
                        {
                            // static call to Regex.Match caches the pattern, so we aren't recompiling every loop.
                            var bannerMatch = Regex.Match(banner, @"mutat\('(.*?)', '", RegexOptions.Compiled);
                            release.BannerUrl = new Uri(bannerMatch.Groups[1].Value);
                        }

                        //TODO there is room for improvement here.
                        if (episodeString != null &&
                            query.MatchQueryStringAND(release.Title, queryStringOverride: episodeString) &&
                            !query.IsImdbQuery)
                        {
                            // For Sonarr if the search query was english the title must be english also
                            // The description holds the alternate language name
                            // so we need to swap title and description names
                            var tempTitle = release.Title;

                            // releaseData everything after Name.S0Xe0X
                            var releaseIndex = tempTitle.IndexOf(episodeString, StringComparison.OrdinalIgnoreCase) +
                                               episodeString.Length;
                            var releaseData = tempTitle.Substring(releaseIndex).Trim();

                            // release description contains [imdb: ****] but we only need the data before it for title
                            var description = new[]
                            {
                                release.Description,
                                ""
                            };
                            if (release.Description.Contains("[imdb:"))
                            {
                                description    = release.Description.Split('[');
                                description[1] = "[" + description[1];
                            }

                            var match = Regex.Match(releaseData, @"^E\d\d?");
                            // if search is done for S0X than we don't want to put . between S0X and E0X
                            var episodeSeparator = episodeString.Length == 3 && match.Success ? null : ".";
                            release.Title =
                                (description[0].Trim() + "." + episodeString.Trim() + episodeSeparator +
                                 releaseData.Trim('.')).Replace(' ', '.');

                            // add back imdb points to the description [imdb: 8.7]
                            release.Description = tempTitle + " " + description[1];
                            release.Description = release.Description.Trim();
                        }

                        releases.Add(release);
                    }
                    catch (FormatException ex)
                    {
                        logger.Error("Problem of parsing Torrent:" + row.InnerHtml);
                        logger.Error("Exception was the following:" + ex);
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.ContentString, ex);
            }

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

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

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

                results = await RequestWithCookiesAsync(searchUrl);
            }

            try
            {
                const string      rowsSelector         = "table.torrent_table > tbody > tr:not(tr.colhead)";
                var               searchResultParser   = new HtmlParser();
                var               searchResultDocument = searchResultParser.ParseDocument(results.ContentString);
                var               rows          = searchResultDocument.QuerySelectorAll(rowsSelector);
                ICollection <int> groupCategory = null;
                string            groupTitle    = null;
                string            groupYearStr  = null;
                var               categoryStr   = "";
                foreach (var row in rows)
                {
                    try
                    {
                        // ignore sub groups info row, it's just an row with an info about the next section, something like "Dual Áudio" or "Legendado"
                        if (row.QuerySelector(".edition_info") != null)
                        {
                            continue;
                        }

                        // some torrents has more than one link, and the one with .tooltip is the wrong one in that case,
                        // so let's try to pick up first without the .tooltip class,
                        // if nothing is found, then we try again without that filter
                        var qDetailsLink = row.QuerySelector("a[href^=\"torrents.php?id=\"]:not(.tooltip)");
                        if (qDetailsLink == null)
                        {
                            qDetailsLink = row.QuerySelector("a[href^=\"torrents.php?id=\"]");
                            // if still can't find the right link, skip it
                            if (qDetailsLink == null)
                            {
                                logger.Error($"{Id}: Error while parsing row '{row.OuterHtml}': Can't find the right details link");
                                continue;
                            }
                        }
                        var title = StripSearchString(qDetailsLink.TextContent, false);

                        var    seasonEl = row.QuerySelector("a[href^=\"torrents.php?torrentid=\"]");
                        string seasonEp = null;
                        if (seasonEl != null)
                        {
                            var seasonMatch = _EpisodeRegex.Match(seasonEl.TextContent);
                            seasonEp = seasonMatch.Success ? seasonMatch.Value : null;
                        }
                        seasonEp ??= _EpisodeRegex.Match(qDetailsLink.TextContent).Value;

                        ICollection <int> category = null;
                        string            yearStr  = null;
                        if (row.ClassList.Contains("group") || row.ClassList.Contains("torrent")) // group/ungrouped headers
                        {
                            var qCatLink = row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
                            categoryStr = qCatLink.GetAttribute("href").Split('=')[1].Split('&')[0];
                            category    = MapTrackerCatToNewznab(categoryStr);

                            var torrentInfoEl = row.QuerySelector("div.torrent_info");
                            if (torrentInfoEl != null)
                            {
                                // valid for torrent grouped but that has only 1 episode yet
                                yearStr = torrentInfoEl.GetAttribute("data-year");
                            }
                            yearStr ??= qDetailsLink.NextSibling.TextContent.Trim().TrimStart('[').TrimEnd(']');

                            if (row.ClassList.Contains("group")) // group headers
                            {
                                groupCategory = category;
                                groupTitle    = title;
                                groupYearStr  = yearStr;
                                continue;
                            }
                        }

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

                        release.Description = release.Description.Replace(" / Free", "");         // Remove Free Tag
                        release.Description = release.Description.Replace("/ WEB ", "/ WEB-DL "); // Fix web/web-dl
                        release.Description = release.Description.Replace("Full HD", "1080p");
                        // Handles HDR conflict
                        release.Description = release.Description.Replace("/ HD /", "/ 720p /");
                        release.Description = release.Description.Replace("/ HD]", "/ 720p]");
                        release.Description = release.Description.Replace("4K", "2160p");
                        release.Description = release.Description.Replace("SD", "480p");
                        release.Description = release.Description.Replace("Dual Áudio", "Dual");

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

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

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

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

            return(releases);
        }
示例#24
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();
            var qc       = new NameValueCollection
            {
                { "cat", MapTorznabCapsToTrackers(query, true).FirstIfSingleOrDefault("0") }
            };
            var results = new List <WebClientStringResult>();
            var search  = new UriBuilder(SearchUrl);

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

            var parser = new HtmlParser();

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

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

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

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

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

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

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

            searchString = searchString.Replace('-', ' '); // remove dashes as they exclude search strings
            var searchUrl = SearchUrl;

            if (!string.IsNullOrWhiteSpace(searchString))
            {
                searchUrl += "query/" + HttpUtility.UrlEncode(searchString) + "/";
            }
            string.Format(SearchUrl, HttpUtility.UrlEncode(searchString));

            var cats = MapTorznabCapsToTrackers(query);

            if (cats.Count > 0)
            {
                searchUrl += "categories/";
                foreach (var cat in cats)
                {
                    if (!searchUrl.EndsWith("/"))
                    {
                        searchUrl += ",";
                    }
                    searchUrl += cat;
                }
            }
            else
            {
                searchUrl += "newfilter/2"; // include 0day and music
            }

            var results = await RequestStringWithCookiesAndRetry(searchUrl);

            if (!results.Content.Contains("/user/account/logout"))
            {
                //Cookie appears to expire after a period of time or logging in to the site via browser
                await DoLogin();

                results = await RequestStringWithCookiesAndRetry(searchUrl);
            }

            try
            {
                CQ dom = results.Content;

                CQ qRows = dom["#torrenttable > tbody > tr"];

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

                    var qRow = row.Cq();

                    var debug = qRow.Html();

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

                    CQ qLink = qRow.Find(".title > a").First();
                    release.Guid     = new Uri(SiteLink + qLink.Attr("href").Substring(1));
                    release.Comments = release.Guid;
                    release.Title    = qLink.Text();

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

                    release.Link = new Uri(qRow.Find(".quickdownload > a").Attr("href"));

                    var dateString = qRow.Find("span.addedInLine").Get(0).LastChild.NodeValue.Replace("on", string.Empty).Trim();;
                    release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);

                    var sizeStr = qRow.Children().ElementAt(4).InnerText;
                    release.Size = ReleaseInfo.GetBytes(sizeStr);

                    release.Seeders = ParseUtil.CoerceInt(qRow.Find(".seeders").Text());
                    release.Peers   = release.Seeders + ParseUtil.CoerceInt(qRow.Find(".leechers").Text());

                    var category = qRow.Find(".category a").Attr("href").Replace("/torrents/browse/index/categories/", string.Empty);
                    release.Category = MapTrackerCatToNewznab(category);

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

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

                    releases.Add(release);
                }
            }

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

            return(releases);
        }
示例#26
0
        List <ReleaseInfo> parseTorrents(WebClientStringResult results, String seasonep, TorznabQuery query, int already_founded, int limit)
        {
            var releases = new List <ReleaseInfo>();

            try
            {
                CQ dom = results.Content;

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

                // Check torrents only till we reach the query Limit
                for (int i = 0; (i < rows.Length && ((already_founded + releases.Count) < limit)); i++)
                {
                    try
                    {
                        CQ  qRow = rows[i].Cq();
                        var key  = dom["link[rel=alternate]"].First().Attr("href").Split('=').Last();

                        release = new ReleaseInfo();
                        var torrentTxt = qRow.Find(".torrent_txt, .torrent_txt2").Find("a").Get(0);
                        //if (torrentTxt == null) continue;
                        release.Title       = torrentTxt.GetAttribute("title");
                        release.Description = qRow.Find("span").Get(0).GetAttribute("title") + " " + qRow.Find("a.infolink").Text();

                        release.MinimumRatio         = 1;
                        release.MinimumSeedTime      = 172800;
                        release.DownloadVolumeFactor = 0;
                        release.UploadVolumeFactor   = 1;

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

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

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

                        if (seasonep == null)
                        {
                            releases.Add(release);
                        }

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

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

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

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

                                release.Title = (description[0].Trim() + "." + seasonep.Trim() + "." + releasedata.Trim('.')).Replace(' ', '.');

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

                                // add back imdb points to the description [imdb: 8.7]
                                release.Description = temp + " " + description[1];
                                release.Description = release.Description.Trim();
                                releases.Add(release);
                            }
                        }
                    }
                    catch (FormatException ex)
                    {
                        logger.Error("Problem of parsing Torrent:" + rows[i].InnerHTML);
                        logger.Error("Exception was the following:" + ex);
                    }
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.Content, ex);
            }

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

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

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

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

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

                            var release = new ReleaseInfo();

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

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

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

                            release.Description = release.Description.Replace(" / Free", ""); // Remove Free Tag
                            release.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);
        }
示例#28
0
        protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query)
        {
            var releases = new List <ReleaseInfo>();

            var cats = MapTorznabCapsToTrackers(query);

            if (cats.Count == 0)
            {
                cats = GetAllTrackerCategories();
            }
            var catStr    = string.Join(";", cats);
            var searchUrl = SearchUrl + "?" + catStr;

            if (query.IsImdbQuery)
            {
                searchUrl += ";q=" + query.ImdbID;
            }
            else
            {
                searchUrl += ";q=" + WebUtilityHelpers.UrlEncode(query.GetQueryString(), Encoding);
            }

            if (((BoolConfigurationItem)configData.GetDynamic("freeleech")).Value)
            {
                searchUrl += ";free=on";
            }

            var results = await RequestWithCookiesAndRetryAsync(searchUrl);

            // Check for being logged out
            if (results.IsRedirect)
            {
                if (results.RedirectingTo.Contains("login.php"))
                {
                    throw new Exception("The user is not logged in. It is possible that the cookie has expired or you made a mistake when copying it. Please check the settings.");
                }
                else
                {
                    throw new Exception($"Got a redirect to {results.RedirectingTo}, please adjust your the alternative link");
                }
            }

            try
            {
                var rows = JsonConvert.DeserializeObject <dynamic>(results.ContentString);

                foreach (var row in rows)
                {
                    var title = (string)row.name;
                    if ((!query.IsImdbQuery || !TorznabCaps.MovieSearchImdbAvailable) && !query.MatchQueryStringAND(title))
                    {
                        continue;
                    }
                    var torrentId          = (long)row.t;
                    var details            = new Uri(SiteLink + "details.php?id=" + torrentId);
                    var seeders            = (int)row.seeders;
                    var imdbId             = (string)row["imdb-id"];
                    var downloadMultiplier = (double?)row["download-multiplier"] ?? 1;
                    var link        = new Uri(SiteLink + "download.php/" + torrentId + "/" + torrentId + ".torrent");
                    var publishDate = DateTimeUtil.UnixTimestampToDateTime((long)row.ctime).ToLocalTime();
                    var imdb        = ParseUtil.GetImdbID(imdbId);

                    var release = new ReleaseInfo
                    {
                        Title                = title,
                        Details              = details,
                        Guid                 = details,
                        Link                 = link,
                        PublishDate          = publishDate,
                        Category             = MapTrackerCatToNewznab(row.c.ToString()),
                        Size                 = (long)row.size,
                        Files                = (long)row.files,
                        Grabs                = (long)row.completed,
                        Seeders              = seeders,
                        Peers                = seeders + (int)row.leechers,
                        Imdb                 = imdb,
                        DownloadVolumeFactor = downloadMultiplier,
                        UploadVolumeFactor   = 1,
                        MinimumRatio         = 1,
                        MinimumSeedTime      = 172800 // 48 hours
                    };

                    releases.Add(release);
                }
            }
            catch (Exception ex)
            {
                OnParseError(results.ContentString, ex);
            }
            return(releases);
        }
示例#29
0
        protected override 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);

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

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

            // remove dashes at the beginning of keywords as they exclude search strings (see issue #3096)
            var searchString = query.GetQueryString();

            searchString = Regex.Replace(searchString, @"(^|\s)-", " ");

            var searchUrl = SearchUrl;

            if (((BoolConfigurationItem)configData.GetDynamic("freeleech")).Value)
            {
                searchUrl += "facets/tags%3AFREELEECH/";
            }

            if (query.IsImdbQuery)
            {
                searchUrl += "imdbID/" + query.ImdbID + "/";
            }
            else if (!string.IsNullOrWhiteSpace(searchString))
            {
                searchUrl += "exact/1/query/" + WebUtility.UrlEncode(searchString) + "/";
            }

            var cats = MapTorznabCapsToTrackers(query);

            if (cats.Count > 0)
            {
                searchUrl += "categories/" + string.Join(",", cats);
            }
            else
            {
                searchUrl += "newfilter/2"; // include 0day and music
            }
            var results = await RequestWithCookiesAndRetryAsync(searchUrl);

            if (results.ContentString.Contains("/user/account/login")) // re-login
            {
                await DoLogin();

                results = await RequestWithCookiesAndRetryAsync(searchUrl);
            }

            try
            {
                var rows = (JArray)((JObject)JsonConvert.DeserializeObject(results.ContentString))["torrentList"];
                foreach (var row in rows)
                {
                    var title = row["name"].ToString();
                    if (!query.MatchQueryStringAND(title))
                    {
                        continue;
                    }

                    var torrentId   = row["fid"].ToString();
                    var details     = new Uri(SiteLink + "torrent/" + torrentId);
                    var link        = new Uri(SiteLink + "download/" + torrentId + "/" + row["filename"]);
                    var publishDate = DateTime.ParseExact(row["addedTimestamp"].ToString(), "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
                    var seeders     = (int)row["seeders"];

                    // freeleech #6579 #6624 #7367
                    var dlMultiplier   = row["download_multiplier"].ToString();
                    var dlVolumeFactor = string.IsNullOrEmpty(dlMultiplier) ? 1 : ParseUtil.CoerceInt(dlMultiplier);

                    var release = new ReleaseInfo
                    {
                        Title                = title,
                        Details              = details,
                        Guid                 = details,
                        Link                 = link,
                        PublishDate          = publishDate,
                        Category             = MapTrackerCatToNewznab(row["categoryID"].ToString()),
                        Size                 = (long)row["size"],
                        Grabs                = (int)row["completed"],
                        Seeders              = seeders,
                        Peers                = seeders + (int)row["leechers"],
                        Imdb                 = ParseUtil.GetImdbID(row["imdbID"].ToString()),
                        UploadVolumeFactor   = 1,
                        DownloadVolumeFactor = dlVolumeFactor,
                        MinimumRatio         = 1,
                        MinimumSeedTime      = 864000 // 10 days for registered users, less for upgraded users
                    };

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

            return(releases);
        }