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); }
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); }
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); }
private static IEnumerable <EraiRawsReleaseInfo> FilterForQuery(TorznabQuery query, IEnumerable <EraiRawsReleaseInfo> feedItems) { foreach (var fi in feedItems) { if (!query.MatchQueryStringAND(fi.Title)) { continue; } yield return(fi); } }
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))); }
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); }
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); }
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); }
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); }
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; }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }