public static void AddReleaseInfoMoreInfoRows(ReleaseInfo info, PmSettings.ReleaseInfoMoreInfoDialogProperties skin) { DrawMoreInfoRow(skin, "Name", info.Name); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Version", string.IsNullOrEmpty(info.Version) ? NotAvailableLabel : info.Version); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Release Date", !string.IsNullOrEmpty(info.AssetStoreInfo.PublishDate) ? info.AssetStoreInfo.PublishDate : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Modification Date", !string.IsNullOrEmpty(info.FileModificationDate) ? info.FileModificationDate : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Compressed Size", info.HasCompressedSize ? MiscUtil.ConvertByteSizeToDisplayValue(info.CompressedSize) : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Publisher", !string.IsNullOrEmpty(info.AssetStoreInfo.PublisherLabel) ? info.AssetStoreInfo.PublisherLabel : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Category", !string.IsNullOrEmpty(info.AssetStoreInfo.CategoryLabel) ? info.AssetStoreInfo.CategoryLabel : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Description", !string.IsNullOrEmpty(info.AssetStoreInfo.Description) ? info.AssetStoreInfo.Description : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Unity Version", !string.IsNullOrEmpty(info.AssetStoreInfo.UnityVersion) ? info.AssetStoreInfo.UnityVersion : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "ID", info.Id); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Source URL", string.IsNullOrEmpty(info.Url) ? NotAvailableLabel : info.Url); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Publish Notes", !string.IsNullOrEmpty(info.AssetStoreInfo.PublishNotes) ? info.AssetStoreInfo.PublishNotes : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); DrawMoreInfoRow(skin, "Version Code", info.HasVersionCode ? info.VersionCode.ToString() : NotAvailableLabel); GUILayout.Space(skin.RowSpacing); }
public void DiscoversIssueNumbersInCommits() { var commit = Substitute.For<Commit>(); commit.Message.Returns("Fixing issue #123"); var commit2 = Substitute.For<Commit>(); commit2.Message.Returns("Fixing issue #51401"); var commits = new List<Commit> { commit, commit2 }; var releaseInfo = new ReleaseInfo(); var releases = new Dictionary<ReleaseInfo, List<Commit>> { {releaseInfo, commits} }; var issueNumbers = new IssueNumberExtractor().GetIssueNumbers(new GitReleaseNotesArguments(), releases, new Regex("#(?<issueNumber>\\d+)")); issueNumbers[releaseInfo].ShouldContain("123"); issueNumbers[releaseInfo].ShouldContain("51401"); }
public DownloadClientRejectedReleaseException(ReleaseInfo release, string message, params object[] args) : base(release, message, args) { }
DragList.ItemDescriptor CreateListItem(ReleaseInfo info) { string caption; if (_model.IsReleaseInstalled(info)) { caption = ImguiUtil.WrapWithColor( info.Name, _pmSettings.View.Theme.DraggableItemAlreadyAddedColor); } else { caption = info.Name; } caption = string.IsNullOrEmpty(info.Version) ? caption : "{0} {1}" .Fmt(caption, ImguiUtil.WrapWithColor("v" + info.Version, _pmSettings.View.Theme.VersionColor)); return new DragList.ItemDescriptor() { Caption = caption, Model = info, }; }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { "%20" }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString)); var message = new HttpRequestMessage(); message.Method = HttpMethod.Get; message.RequestUri = new Uri(episodeSearchUrl); message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken()); var response = await client.SendAsync(message); var results = await response.Content.ReadAsStringAsync(); var jsonResult = JObject.Parse(results); try { var items = (JArray)jsonResult["torrents"]; foreach (var item in items) { var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; var torrentId = (string)item["id"]; release.Link = new Uri(string.Format(DownloadUrl, torrentId)); release.Title = (string)item["name"]; release.Description = release.Title; release.Comments = new Uri(string.Format(CommentsUrl, (string)item["rewritename"])); release.Guid = release.Comments; var dateUtc = DateTime.ParseExact((string)item["added"], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); release.PublishDate = DateTime.SpecifyKind(dateUtc, DateTimeKind.Utc).ToLocalTime(); release.Seeders = ParseUtil.CoerceInt((string)item["seeders"]); release.Peers = ParseUtil.CoerceInt((string)item["leechers"]) + release.Seeders; release.Size = ParseUtil.CoerceLong((string)item["size"]); releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var searchSection = string.IsNullOrEmpty(query.Episode) ? "archive" : "browse"; var searchCategory = string.IsNullOrEmpty(query.Episode) ? "26" : "27"; var searchUrl = string.Format(SearchUrl, searchSection, searchCategory, searchString); string results; if (Program.IsWindows) { results = await client.GetStringAsync(searchUrl); } else { var response = await CurlHelper.GetAsync(searchUrl, cookieHeader); results = Encoding.UTF8.GetString(response.Content); } try { CQ dom = results; var rows = dom["#torrents-table > tbody > tr.tt_row"]; foreach (var row in rows) { CQ qRow = row.Cq(); var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 129600; release.Title = qRow.Find(".ttr_name > a").Text(); release.Description = release.Title; release.Guid = new Uri(BaseUrl + "/" + qRow.Find(".ttr_name > a").Attr("href")); release.Comments = release.Guid; release.Link = new Uri(BaseUrl + "/" + qRow.Find(".td_dl > a").Attr("href")); var sizeStr = qRow.Find(".ttr_size").Contents()[0].NodeValue; var sizeParts = sizeStr.Split(' '); release.Size = ReleaseInfo.GetBytes(sizeParts[1], float.Parse(sizeParts[0], NumberStyles.Float | NumberStyles.AllowThousands)); var timeStr = qRow.Find(".ttr_added").Text(); DateTime time; if (DateTime.TryParseExact(timeStr, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out time)) { release.PublishDate = time; } release.Seeders = int.Parse(qRow.Find(".ttr_seeders").Text(), NumberStyles.AllowThousands); release.Peers = int.Parse(qRow.Find(".ttr_leechers").Text(), NumberStyles.AllowThousands) + release.Seeders; releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query, string baseUrl) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); List<string> searchurls = new List<string>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); for (int page = 0; page < MAXPAGES; page++) searchurls.Add(string.Format(SearchUrl, HttpUtility.UrlEncode(searchString.Trim()), page)); } foreach (string SearchUrl in searchurls) { var results = await client.GetStringAsync(SearchUrl); try { CQ dom = results; ReleaseInfo release; int rowCount = 0; var rows = dom[".mainblockcontenttt > tbody > tr"]; foreach (var row in rows) { CQ qRow = row.Cq(); if (rowCount < 2 || qRow.Children().Count() != 12) //skip 2 rows because there's an empty row & a title/sort row { rowCount++; continue; } release = new ReleaseInfo(); long? size; release.Title = qRow.Find("td.mainblockcontent b a").Text(); release.Description = release.Title; if (0 != qRow.Find("td.mainblockcontent u").Length) { var imdbStr = qRow.Find("td.mainblockcontent u").Parent().First().Attr("href").Replace("http://www.imdb.com/title/tt", "").Replace("/", ""); long imdb; if (ParseUtil.TryCoerceLong(imdbStr, out imdb)) { release.Imdb = imdb; } } release.MinimumRatio = 1; release.MinimumSeedTime = 172800; int seeders, peers; if (ParseUtil.TryCoerceInt(qRow.Find("td").Get(9).FirstChild.FirstChild.InnerText, out seeders)) { release.Seeders = seeders; if (ParseUtil.TryCoerceInt(qRow.Find("td").Get(10).FirstChild.FirstChild.InnerText, out peers)) { release.Peers = peers + release.Seeders; } } string fullSize = qRow.Find("td.mainblockcontent").Get(6).InnerText; string[] sizeSplit = fullSize.Split(' '); switch (sizeSplit[1].ToLower()) { case "kb": size = ReleaseInfo.BytesFromKB(ParseUtil.CoerceFloat(sizeSplit[0])); break; case "mb": size = ReleaseInfo.BytesFromMB(ParseUtil.CoerceFloat(sizeSplit[0])); break; case "gb": size = ReleaseInfo.BytesFromGB(ParseUtil.CoerceFloat(sizeSplit[0])); break; default: size = null; break; } release.Size = size; release.Guid = new Uri(DefaultUrl + "/" + qRow.Find("td.mainblockcontent b a").Attr("href")); release.Link = new Uri(DefaultUrl + "/" + qRow.Find("td.mainblockcontent").Get(3).FirstChild.GetAttribute("href")); release.Comments = new Uri(DefaultUrl + "/" + qRow.Find("td.mainblockcontent b a").Attr("href") + "#comments"); string[] dateSplit = qRow.Find("td.mainblockcontent").Get(5).InnerHTML.Split(','); string dateString = dateSplit[1].Substring(0, dateSplit[1].IndexOf('>')); release.PublishDate = DateTime.Parse(dateString, CultureInfo.InvariantCulture); releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
IEnumerator CheckShouldInstallInternal(ReleaseInfo releaseInfo) { var packageInfo = TryFindPackageInfoForRelease(releaseInfo); if (packageInfo == null) { yield return InstallReleaseUserChoices.Install; yield break; } Assert.IsNotNull(packageInfo.InstallInfo); var packageReleaseInfo = packageInfo.InstallInfo.ReleaseInfo; Assert.IsNotNull(packageReleaseInfo); // TODO - how to handle? Assert.That(packageReleaseInfo.HasVersionCode); Assert.That(releaseInfo.HasVersionCode); IEnumerator<int> userChoice; if (packageReleaseInfo.VersionCode == releaseInfo.VersionCode) { Assert.IsEqual(releaseInfo.Version, packageReleaseInfo.Version); userChoice = _view.PromptForUserChoice( "Package '{0}' is already installed with the same version ('{1}'). Would you like to re-install it anyway? Note that any local changes you've made to the package will be reverted." .Fmt(packageReleaseInfo.Name, packageReleaseInfo.Version), new[] { "Overwrite", "Skip", "Cancel" }, null, null, 0, 2); } else if (releaseInfo.VersionCode > packageReleaseInfo.VersionCode) { userChoice = _view.PromptForUserChoice( "Package '{0}' is already installed with version '{1}'. Would you like to UPGRADE it to version '{2}'? Note that any local changes you've made to the package will be lost." .Fmt(releaseInfo.Name, packageReleaseInfo.Version, releaseInfo.Version), new[] { "Upgrade", "Skip", "Cancel" }, null, null, 0, 2); } else { Assert.That(releaseInfo.VersionCode < packageReleaseInfo.VersionCode); userChoice = _view.PromptForUserChoice( "Package '{0}' is already installed with version '{1}'. Would you like to DOWNGRADE it to version '{2}'? Note that any local changes you've made to the package will be lost." .Fmt(releaseInfo.Name, packageReleaseInfo.Version, releaseInfo.Version), new[] { "Downgrade", "Skip", "Cancel" }, null, null, 0, 2); } yield return userChoice; switch (userChoice.Current) { case 0: { yield return InstallReleaseUserChoices.Install; break; } case 1: { yield return InstallReleaseUserChoices.Skip; break; } case 2: { yield return InstallReleaseUserChoices.Cancel; break; } default: { Assert.Throw(); break; } } }
public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var searchString = query.GetQueryString(); var prevCook = CookieHeader + ""; // If we have no query use the RSS Page as their server is slow enough at times! if (query.IsTest || string.IsNullOrWhiteSpace(searchString)) { var rssPage = await RequestStringWithCookiesAndRetry(string.Format(RSSUrl, configData.RSSKey.Value)); try { if (rssPage.Content.EndsWith("\0")) { rssPage.Content = rssPage.Content.Substring(0, rssPage.Content.Length - 1); } rssPage.Content = RemoveInvalidXmlChars(rssPage.Content); var rssDoc = XDocument.Parse(rssPage.Content); foreach (var item in rssDoc.Descendants("item")) { var title = item.Descendants("title").First().Value; var description = item.Descendants("description").First().Value; var link = item.Descendants("link").First().Value; var category = item.Descendants("category").First().Value; var date = item.Descendants("pubDate").First().Value; var torrentIdMatch = Regex.Match(link, "(?<=id=)(\\d)*"); var torrentId = torrentIdMatch.Success ? torrentIdMatch.Value : string.Empty; if (string.IsNullOrWhiteSpace(torrentId)) { throw new Exception("Missing torrent id"); } var infoMatch = Regex.Match(description, @"Category:\W(?<cat>.*)\W\/\WSeeders:\W(?<seeders>[\d\,]*)\W\/\WLeechers:\W(?<leechers>[\d\,]*)\W\/\WSize:\W(?<size>[\d\.]*\W\S*)"); if (!infoMatch.Success) { throw new Exception("Unable to find info"); } var release = new ReleaseInfo { Title = title, Description = title, Guid = new Uri(string.Format(DownloadUrl, torrentId)), Comments = new Uri(string.Format(CommentUrl, torrentId)), PublishDate = DateTime.ParseExact(date, "yyyy-MM-dd H:mm:ss", CultureInfo.InvariantCulture), //2015-08-08 21:20:31 Link = new Uri(string.Format(DownloadUrl, torrentId)), Seeders = ParseUtil.CoerceInt(infoMatch.Groups["seeders"].Value), Peers = ParseUtil.CoerceInt(infoMatch.Groups["leechers"].Value), Size = ReleaseInfo.GetBytes(infoMatch.Groups["size"].Value), Category = MapTrackerCatToNewznab(category) }; release.Peers += release.Seeders; releases.Add(release); } } catch (Exception ex) { logger.Error("XSpeeds: Error while parsing the RSS feed:"); logger.Error(rssPage.Content); throw ex; } } if (query.IsTest || !string.IsNullOrWhiteSpace(searchString)) { if (searchString.Length < 3 && !query.IsTest) { OnParseError("", new Exception("Minimum search length is 3")); return(releases); } var searchParams = new Dictionary <string, string> { { "do", "search" }, { "keywords", searchString }, { "search_type", "t_name" }, { "category", "0" }, { "include_dead_torrents", "no" } }; var pairs = new Dictionary <string, string> { { "username", configData.Username.Value }, { "password", configData.Password.Value } }; var searchPage = await PostDataWithCookiesAndRetry(SearchUrl, searchParams, CookieHeader); // Occasionally the cookies become invalid, login again if that happens if (searchPage.IsRedirect) { await ApplyConfiguration(null); searchPage = await PostDataWithCookiesAndRetry(SearchUrl, searchParams, CookieHeader); } try { CQ dom = searchPage.Content; var rows = dom["table#sortabletable > tbody > tr:has(div > a[href*=\"details.php?id=\"])"]; foreach (var row in rows) { var release = new ReleaseInfo(); var qRow = row.Cq(); var qDetails = qRow.Find("div > a[href*=\"details.php?id=\"]"); // details link, release name get's shortened if it's to long var qTitle = qRow.Find("td:eq(1) .tooltip-content div:eq(0)"); // use Title from tooltip if (!qTitle.Any()) // fallback to Details link if there's no tooltip { qTitle = qDetails; } release.Title = qTitle.Text(); release.Guid = new Uri(qRow.Find("td:eq(2) a").Attr("href")); release.Link = release.Guid; release.Comments = new Uri(qDetails.Attr("href")); release.PublishDate = DateTime.ParseExact(qRow.Find("td:eq(1) div").Last().Text().Trim(), "dd-MM-yyyy H:mm", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); //08-08-2015 12:51 release.Seeders = ParseUtil.CoerceInt(qRow.Find("td:eq(6)").Text()); release.Peers = release.Seeders + ParseUtil.CoerceInt(qRow.Find("td:eq(7)").Text().Trim()); release.Size = ReleaseInfo.GetBytes(qRow.Find("td:eq(4)").Text().Trim()); var cat = row.Cq().Find("td:eq(0) a").First().Attr("href"); var catSplit = cat.LastIndexOf('='); if (catSplit > -1) { cat = cat.Substring(catSplit + 1); } release.Category = MapTrackerCatToNewznab(cat); // If its not apps or audio we can only mark as general TV if (release.Category == 0) { release.Category = 5030; } var grabs = qRow.Find("td:nth-child(6)").Text(); release.Grabs = ParseUtil.CoerceInt(grabs); if (qRow.Find("img[alt^=\"Free Torrent\"]").Length >= 1) { release.DownloadVolumeFactor = 0; } else if (qRow.Find("img[alt^=\"Silver Torrent\"]").Length >= 1) { release.DownloadVolumeFactor = 0.5; } else { release.DownloadVolumeFactor = 1; } if (qRow.Find("img[alt^=\"x2 Torrent\"]").Length >= 1) { release.UploadVolumeFactor = 2; } else { release.UploadVolumeFactor = 1; } releases.Add(release); } } catch (Exception ex) { OnParseError(searchPage.Content, ex); } } if (!CookieHeader.Trim().Equals(prevCook.Trim())) { SaveConfig(); } return(releases); }
public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query, int attempts) { var releases = new List <ReleaseInfo>(); var searchString = query.GetQueryString(); var queryCollection = new NameValueCollection(); if (query.ImdbID != null) { queryCollection.Add("query_term", query.ImdbID); } else if (!string.IsNullOrWhiteSpace(searchString)) { searchString = searchString.Replace("'", ""); // ignore ' (e.g. search for america's Next Top Model) queryCollection.Add("query_term", searchString); } // This API does not seem to be working for quality=720p or quality=1080p // Only quality=3D seems to return a proper result? //var cats = string.Join(";", MapTorznabCapsToTrackers(query)); //if (!string.IsNullOrEmpty(cats)) //{ // if (cats == "45") // { // queryCollection.Add("quality", "720p"); // } // if (cats == "44") // { // queryCollection.Add("quality", "1080p"); // } // if (cats == "2050") // { // queryCollection.Add("quality", "3D"); // } //} var searchUrl = ApiEndpoint + "?" + queryCollection.GetQueryString(); var response = await RequestStringWithCookiesAndRetry(searchUrl, string.Empty); try { // returned content might start with an html error message, remove it first var jsonStart = response.Content.IndexOf('{'); var jsonContentStr = response.Content.Remove(0, jsonStart); var jsonContent = JObject.Parse(jsonContentStr); string result = jsonContent.Value <string>("status"); if (result != "ok") // query was not successful { return(releases.ToArray()); } var data_items = jsonContent.Value <JToken>("data"); int movie_count = data_items.Value <int>("movie_count"); if (movie_count < 1) // no results found in query { return(releases.ToArray()); } foreach (var movie_item in data_items.Value <JToken>("movies")) { var torrents = movie_item.Value <JArray>("torrents"); if (torrents == null) { continue; } foreach (var torrent_info in torrents) { var release = new ReleaseInfo(); // Append the quality to the title because thats how radarr seems to be determining the quality? // All releases are BRRips, see issue #2200 release.Title = movie_item.Value <string>("title_long") + " " + torrent_info.Value <string>("quality") + " BRRip"; var imdb = movie_item.Value <string>("imdb_code"); release.Imdb = ParseUtil.GetImdbID(imdb); // API does not provide magnet link, so, construct it string magnet_uri = "magnet:?xt=urn:btih:" + torrent_info.Value <string>("hash") + "&dn=" + movie_item.Value <string>("slug") + "&tr=udp://open.demonii.com:1337/announce" + "&tr=udp://tracker.openbittorrent.com:80" + "&tr=udp://tracker.coppersurfer.tk:6969" + "&tr=udp://glotorrents.pw:6969/announce" + "&tr=udp://tracker.opentrackr.org:1337/announce" + "&tr=udp://torrent.gresille.org:80/announce" + "&tr=udp://p4p.arenabg.com:1337&tr=udp://tracker.leechers-paradise.org:6969"; release.MagnetUri = new Uri(magnet_uri); release.InfoHash = torrent_info.Value <string>("hash"); // ex: 2015-08-16 21:25:08 +0000 var dateStr = torrent_info.Value <string>("date_uploaded"); var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); release.PublishDate = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc).ToLocalTime(); release.Link = new Uri(torrent_info.Value <string>("url")); release.Seeders = torrent_info.Value <int>("seeds"); release.Peers = torrent_info.Value <int>("peers") + release.Seeders; release.Size = torrent_info.Value <long>("size_bytes"); release.DownloadVolumeFactor = 0; release.UploadVolumeFactor = 1; release.Comments = new Uri(movie_item.Value <string>("url")); release.BannerUrl = new Uri(movie_item.Value <string>("large_cover_image")); release.Guid = release.Link; // Hack to prevent adding non-specified catogery, since API doesn't seem to be working string categories = string.Join(";", MapTorznabCapsToTrackers(query)); if (!string.IsNullOrEmpty(categories)) { if (categories.Contains("45") || categories.Contains("2040")) { if (torrent_info.Value <string>("quality") == "720p") { release.Category = MapTrackerCatToNewznab("45"); releases.Add(release); } } if (categories.Contains("44") || categories.Contains("2040")) { if (torrent_info.Value <string>("quality") == "1080p") { release.Category = MapTrackerCatToNewznab("44"); releases.Add(release); } } if (categories.Contains("47")) { if (torrent_info.Value <string>("quality") == "3D") { release.Category = MapTrackerCatToNewznab("47"); releases.Add(release); } } } else { release.Category = MapTrackerCatToNewznab("45"); releases.Add(release); } } } } catch (Exception ex) { OnParseError(response.Content, ex); } return(releases); }
public List <ReleaseInfo> ParseResponse(TorznabQuery query, string htmlResponse) { List <ReleaseInfo> releases = new List <ReleaseInfo>(); try { CQ dom = htmlResponse; List <string> headerColumns = dom["table[class*='movehere']"].First().Find("tbody > tr > td[class='cat_Head']").Select(x => x.Cq().Text()).ToList(); int categoryIndex = headerColumns.FindIndex(x => x.Equals("Type")); int nameIndex = headerColumns.FindIndex(x => x.Equals("Name")); int sizeIndex = headerColumns.FindIndex(x => x.Equals("Size")); int seedersIndex = headerColumns.FindIndex(x => x.Equals("Seeders")); int 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); string catLink = categoryCol.Cq().Find("a").Attr("href"); if (catLink != null) { string 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 virtual ReleaseInfo PostProcess(XElement item, ReleaseInfo releaseInfo) { return(releaseInfo); }
public void Setup() { _artist = Builder <Author> .CreateNew() .Build(); _album = Builder <Book> .CreateNew() .Build(); _profile = new QualityProfile { Name = "Test", Cutoff = Quality.MP3_320.Id, Items = new List <QualityProfileQualityItem> { new QualityProfileQualityItem { Allowed = true, Quality = Quality.MP3_320 }, new QualityProfileQualityItem { Allowed = true, Quality = Quality.MP3_320 }, new QualityProfileQualityItem { Allowed = true, Quality = Quality.MP3_320 } }, }; _artist.QualityProfile = new LazyLoaded <QualityProfile>(_profile); _release = Builder <ReleaseInfo> .CreateNew().Build(); _parsedBookInfo = Builder <ParsedBookInfo> .CreateNew().Build(); _parsedBookInfo.Quality = new QualityModel(Quality.MP3_320); _remoteBook = new RemoteBook(); _remoteBook.Books = new List <Book> { _album }; _remoteBook.Author = _artist; _remoteBook.ParsedBookInfo = _parsedBookInfo; _remoteBook.Release = _release; _temporarilyRejected = new DownloadDecision(_remoteBook, new Rejection("Temp Rejected", RejectionType.Temporary)); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.All()) .Returns(new List <PendingRelease>()); Mocker.GetMock <IAuthorService>() .Setup(s => s.GetAuthor(It.IsAny <int>())) .Returns(_artist); Mocker.GetMock <IAuthorService>() .Setup(s => s.GetAuthors(It.IsAny <IEnumerable <int> >())) .Returns(new List <Author> { _artist }); Mocker.GetMock <IParsingService>() .Setup(s => s.GetAlbums(It.IsAny <ParsedBookInfo>(), _artist, null)) .Returns(new List <Book> { _album }); Mocker.GetMock <IPrioritizeDownloadDecision>() .Setup(s => s.PrioritizeDecisions(It.IsAny <List <DownloadDecision> >())) .Returns((List <DownloadDecision> d) => d); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var trackerCats = MapTorznabCapsToTrackers(query); var cat = (trackerCats.Count == 1 ? trackerCats.ElementAt(0) : "0"); var episodeSearchUrl = string.Format(SearchUrl, cat, WebUtility.UrlEncode(query.GetQueryString())); var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl); if (results.Content.Contains("No torrents found")) { return(releases); } try { CQ dom = results.Content; var rows = dom[".ctable_content_no_pad > table > tbody > tr"].ToArray(); DateTime lastDateTime = default(DateTime); for (var i = 0; i < rows.Length; i++) { var rowA = rows[i]; var rAlign = rowA.Attributes["align"]; if (rAlign == "right" || rAlign == "center") { continue; } if (rAlign == "left") { // ex: "Monday, Jun 01, 2015", "Monday, Aug 03, 2015" var dateStr = rowA.Cq().Text().Trim().Replace("Added on ", ""); if (string.IsNullOrWhiteSpace(dateStr) || dateStr == "Sponsored links" || dateStr.StartsWith("!function") || dateStr.StartsWith("atOptions")) { continue; // ignore ads } if (dateStr.ToLowerInvariant().Contains("today")) { lastDateTime = DateTime.Now; } else { lastDateTime = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dddd, MMM dd, yyyy", CultureInfo.InvariantCulture), DateTimeKind.Utc).ToLocalTime(); } continue; } if (rowA.ChildElements.Count() < 2) { continue; } var rowB = rows[++i]; var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; release.PublishDate = lastDateTime; var catUrl = rowA.ChildElements.ElementAt(0).FirstElementChild.GetAttribute("href"); var catId = QueryHelpers.ParseQuery(catUrl)["category"].First(); release.Category = MapTrackerCatToNewznab(catId); var qLink = rowA.ChildElements.ElementAt(1).FirstElementChild.Cq(); release.Title = qLink.Text().Trim(); release.Description = rowB.ChildElements.ElementAt(0).Cq().Text(); if (release.Category != null && release.Category.Contains(TorznabCatType.Audio.ID)) { if (release.Description.Contains("Lossless")) { release.Category = new List <int> { TorznabCatType.AudioLossless.ID } } ; else if (release.Description.Contains("MP3")) { release.Category = new List <int> { TorznabCatType.AudioMP3.ID } } ; else { release.Category = new List <int> { TorznabCatType.AudioOther.ID } }; } release.Comments = new Uri(new Uri(SiteLink), qLink.Attr("href")); release.Guid = release.Comments; var qDownload = rowB.ChildElements.ElementAt(2).ChildElements.ElementAt(0).Cq(); release.Link = new Uri(qDownload.Attr("href")); var sizeStr = rowB.ChildElements.ElementAt(3).Cq().Text(); release.Size = ReleaseInfo.GetBytes(sizeStr); release.Seeders = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(6).Cq().Text()); release.Peers = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(6).Cq().Text()) + release.Seeders; var grabs = rowB.Cq().Find("td:nth-child(6)").Text(); release.Grabs = ParseUtil.CoerceInt(grabs); release.DownloadVolumeFactor = 0; // ratioless release.UploadVolumeFactor = 1; releases.Add(release); } } catch (Exception ex) { OnParseError(results.Content, ex); } return(releases); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var qc = new List <KeyValuePair <string, string> > // NameValueCollection don't support cat[]=19&cat[]=6 { { "st", "1" } // search in title }; if (query.IsImdbQuery) { qc.Add("search", query.ImdbID); qc.Add("sd", "1"); // search in description } else { qc.Add("search", query.GetQueryString()); } // parse categories and tags var catGroups = new HashSet <string>(); // HashSet instead of List to avoid duplicates var tagGroups = new HashSet <string>(); var cats = MapTorznabCapsToTrackers(query); foreach (var cat in cats) { // "cat[]=7&tags=x264" var cSplit = cat.Split('&'); var gSplit = cSplit[0].Split('='); if (gSplit.Length > 1) { catGroups.Add(gSplit[1]); // category = 7 } if (cSplit.Length > 1) { var tSplit = cSplit[1].Split('='); if (tSplit.Length > 1) { tagGroups.Add(tSplit[1]); // tag = x264 } } } // add categories foreach (var cat in catGroups) { qc.Add("cat[]", cat); } // do not include too many tags as it'll mess with their servers if (tagGroups.Count < 7) { qc.Add("tags", string.Join(",", tagGroups)); // if tags are specified match any // if no tags are specified match all, with any we get random results qc.Add("tf", tagGroups.Any() ? "any" : "all"); } var searchUrl = SearchUrl + "?" + qc.GetQueryString(); var response = await RequestWithCookiesAndRetryAsync(searchUrl); if (response.IsRedirect) // re-login { await ApplyConfiguration(null); response = await RequestWithCookiesAndRetryAsync(searchUrl); } try { var parser = new HtmlParser(); var dom = parser.ParseDocument(response.ContentString); var rows = dom.QuerySelectorAll("table > tbody > tr.browse"); foreach (var row in rows) { var qLink = row.Children[1].QuerySelector("a"); var title = qLink.GetAttribute("title"); if (qLink.QuerySelectorAll("span").Length == 1 && title.StartsWith("NEW! |")) { title = title.Substring(6).Trim(); } if (!query.MatchQueryStringAND(title)) { continue; // we have to skip bad titles due to tags + any word search } var comments = new Uri(SiteLink + qLink.GetAttribute("href")); var link = new Uri(SiteLink + row.Children[2].QuerySelector("a").GetAttribute("href")); var dateStr = Regex.Replace(row.Children[5].InnerHtml, @"\<br[\s]{0,1}[\/]{0,1}\>", " "); var publishDate = DateTimeUtil.FromTimeAgo(dateStr); var files = ParseUtil.CoerceInt(row.Children[3].TextContent); var size = ReleaseInfo.GetBytes(row.Children[7].TextContent); var grabs = ParseUtil.CoerceInt(row.Children[8].TextContent); var seeders = ParseUtil.CoerceInt(row.Children[9].TextContent); var leechers = ParseUtil.CoerceInt(row.Children[10].TextContent); var cat = row.FirstElementChild.FirstElementChild.GetAttribute("href").Replace("browse.php?", string.Empty); var release = new ReleaseInfo { Title = title, Comments = comments, Guid = comments, Link = link, PublishDate = publishDate, Size = size, Category = MapTrackerCatToNewznab(cat), Files = files, Grabs = grabs, Seeders = seeders, Peers = leechers + seeders, MinimumRatio = 0.75, MinimumSeedTime = 216000, // 60 hours DownloadVolumeFactor = 0, // ratioless UploadVolumeFactor = 1 }; releases.Add(release); } } catch (Exception ex) { OnParseError(response.ContentString, ex); } return(releases); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString); var request = CreateHttpRequest(new Uri(episodeSearchUrl)); var response = await client.SendAsync(request); var results = await response.Content.ReadAsStringAsync(); try { CQ dom = results; var rows = dom["table.torrents > tbody > tr"]; foreach (var row in rows.Skip(1)) { var release = new ReleaseInfo(); var qRow = row.Cq(); var qTitleLink = qRow.Find("a.t_title").First(); release.Title = qTitleLink.Text().Trim(); release.Description = release.Title; release.Guid = new Uri(BaseUrl + qTitleLink.Attr("href")); release.Comments = release.Guid; DateTime pubDate; var descString = qRow.Find(".t_ctime").Text(); var dateString = descString.Split('|').Last().Trim(); dateString = dateString.Split(new string[] { " by " }, StringSplitOptions.None)[0]; var dateValue = ParseUtil.CoerceFloat(dateString.Split(' ')[0]); var dateUnit = dateString.Split(' ')[1]; if (dateUnit.Contains("minute")) pubDate = DateTime.Now - TimeSpan.FromMinutes(dateValue); else if (dateUnit.Contains("hour")) pubDate = DateTime.Now - TimeSpan.FromHours(dateValue); else if (dateUnit.Contains("day")) pubDate = DateTime.Now - TimeSpan.FromDays(dateValue); else if (dateUnit.Contains("week")) pubDate = DateTime.Now - TimeSpan.FromDays(7 * dateValue); else if (dateUnit.Contains("month")) pubDate = DateTime.Now - TimeSpan.FromDays(30 * dateValue); else if (dateUnit.Contains("year")) pubDate = DateTime.Now - TimeSpan.FromDays(365 * dateValue); else pubDate = DateTime.MinValue; release.PublishDate = pubDate; var qLink = row.ChildElements.ElementAt(3).Cq().Children("a"); release.Link = new Uri(BaseUrl + qLink.Attr("href")); var sizeStr = row.ChildElements.ElementAt(5).Cq().Text().Trim(); var sizeVal = ParseUtil.CoerceFloat(sizeStr.Split(' ')[0]); var sizeUnit = sizeStr.Split(' ')[1]; release.Size = ReleaseInfo.GetBytes(sizeUnit, sizeVal); release.Seeders = ParseUtil.CoerceInt(qRow.Find(".t_seeders").Text().Trim()); release.Peers = ParseUtil.CoerceInt(qRow.Find(".t_leechers").Text().Trim()) + release.Seeders; releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString)); var results = await client.GetStringAsync(episodeSearchUrl); try { CQ dom = results; var rows = dom["table.torrenttable > tbody > tr.browse_color"]; foreach (var row in rows) { var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; var qRow = row.Cq(); var qLink = row.ChildElements.ElementAt(2).FirstChild.Cq(); release.Link = new Uri(BaseUrl + "/" + qLink.Attr("href")); var torrentID = qLink.Attr("href").Split('=').Last(); var descCol = row.ChildElements.ElementAt(3); var qCommentLink = descCol.FirstChild.Cq(); release.Title = qCommentLink.Text(); release.Description = release.Title; release.Comments = new Uri(BaseUrl + "/" + qCommentLink.Attr("href")); release.Guid = release.Comments; var dateStr = descCol.ChildElements.Last().Cq().Text().Split('|').Last().ToLowerInvariant().Replace("ago.", "").Trim(); var dateParts = dateStr.Split(new char[] { ' ', ' ' }, StringSplitOptions.RemoveEmptyEntries); var timeSpan = TimeSpan.Zero; for (var i = 0; i < dateParts.Length / 2; i++) { var timeVal = ParseUtil.CoerceInt(dateParts[i * 2]); var timeUnit = dateParts[i * 2 + 1]; if (timeUnit.Contains("year")) timeSpan += TimeSpan.FromDays(365 * timeVal); else if (timeUnit.Contains("month")) timeSpan += TimeSpan.FromDays(30 * timeVal); else if (timeUnit.Contains("day")) timeSpan += TimeSpan.FromDays(timeVal); else if (timeUnit.Contains("hour")) timeSpan += TimeSpan.FromHours(timeVal); else if (timeUnit.Contains("min")) timeSpan += TimeSpan.FromMinutes(timeVal); } release.PublishDate = DateTime.SpecifyKind(DateTime.Now - timeSpan, DateTimeKind.Local); var sizeEl = row.ChildElements.ElementAt(7); var sizeVal = ParseUtil.CoerceFloat(sizeEl.ChildNodes.First().NodeValue); var sizeUnit = sizeEl.ChildNodes.Last().NodeValue; release.Size = ReleaseInfo.GetBytes(sizeUnit, sizeVal); release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(9).Cq().Text()); release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(10).Cq().Text()) + release.Seeders; releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink) { throw new NotImplementedException(); }
public bool IsReleaseInstalled(ReleaseInfo info) { return _packages .Any(x => x.InstallInfo != null && x.InstallInfo.ReleaseInfo != null && x.InstallInfo.ReleaseInfo.Id == info.Id && x.InstallInfo.ReleaseInfo.VersionCode == info.VersionCode); }
public 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 = "a1"; if (cats.Count == 1) { cat = cats[0]; } searchUrl += string.Format("?search={0}¶m_val=0&complex_search=0&incldead={1}&orderby=added&sort=desc", HttpUtility.UrlEncode(searchString), cat); var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl); var results = response.Content; try { CQ dom = results; var rows = dom["table#torrenttable > tbody > tr:has(td.tablea), table#torrents_table > tbody > tr#torrent-row"]; // selector for old and new style foreach (var row in rows) { var release = new ReleaseInfo(); var qRow = row.Cq(); var qTitleLink = qRow.Find("a[href^=\"details\"]").First(); if (qTitleLink.HasAttr("title")) { release.Title = qTitleLink.Attr("title"); } else { release.Title = qTitleLink.Text(); } release.Description = qRow.Find("small > i").Text(); release.Guid = new Uri(SiteLink + qTitleLink.Attr("href")); release.Comments = release.Guid; // date is only available with Complex listing var dateStr = qRow.Find("table > tbody > tr:nth-child(2) > td:nth-child(5)").Html().Replace(" ", " "); if (!string.IsNullOrEmpty(dateStr)) { release.PublishDate = DateTime.ParseExact(dateStr + " +0200", "dd.MM.yyyy HH:mm:ss zzz", CultureInfo.InvariantCulture); } var qLink = qRow.Find("a[href^=\"download/\"]"); release.Link = new Uri(SiteLink + qLink.Attr("href")); var sizeStr = qRow.Find("td[nowrap]:nth-child(3), table > tbody > tr:nth-child(2) > td:nth-child(1) > b").Text().Trim(); release.Size = ReleaseInfo.GetBytes(sizeStr.Replace(".", "").Replace(",", ".")); release.Seeders = ParseUtil.CoerceInt(qRow.Find("td > a[href*=\"&toseeders=1\"]:first-child, td:has(a[href*=\"&toseeders=1\"]) > b:nth-child(1)").Text()); release.Peers = ParseUtil.CoerceInt(qRow.Find("td > a[href*=\"&todlers=1\"]:last-child, a[href*=\"&toseeders=1\"] + b").Text().Replace("L.", "")) + release.Seeders; release.Grabs = ParseUtil.CoerceLong(qRow.Find("td[style]:has(a[href*=\"tosnatchers=1\"])").Text().Replace(" Completed", "")); release.DownloadVolumeFactor = 0; release.UploadVolumeFactor = 1; var catLink = qRow.Find("a[onclick^=\"bparam(\"][onclick*=\"cat\"]"); var catId = catLink.Attr("onclick").Split('=')[1].Replace("');", ""); if (!catId.StartsWith("scat")) { catId = "mc" + catId; } release.Category = MapTrackerCatToNewznab(catId); releases.Add(release); } } catch (Exception ex) { OnParseError(results, ex); } return(releases); }
async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query, string baseUrl) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); List<string> searchUrls = new List<string>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var queryStr = HttpUtility.UrlEncode(searchString); var episodeSearchUrl = baseUrl + string.Format(SearchUrl, queryStr); var episodeSearchUrl2 = baseUrl + string.Format(SearchUrl2, queryStr); searchUrls.Add(episodeSearchUrl); searchUrls.Add(episodeSearchUrl2); } foreach (var episodeSearchUrl in searchUrls) { var message = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri(baseUrl + SwitchSingleViewUrl) }; message.Headers.Referrer = new Uri(episodeSearchUrl); string results; if (Program.IsWindows) { var response = await client.SendAsync(message); results = await response.Content.ReadAsStringAsync(); } else { var response = await CurlHelper.GetAsync(baseUrl + SwitchSingleViewUrl, null, episodeSearchUrl); results = Encoding.UTF8.GetString(response.Content); } try { CQ dom = results; var rows = dom["#searchResult > tbody > tr"]; foreach (var row in rows) { var release = new ReleaseInfo(); CQ qLink = row.ChildElements.ElementAt(1).Cq().Children("a").First(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; release.Title = qLink.Text().Trim(); release.Description = release.Title; release.Comments = new Uri(baseUrl + "/" + qLink.Attr("href").TrimStart('/')); release.Guid = release.Comments; var timeString = row.ChildElements.ElementAt(2).Cq().Text(); if (timeString.Contains("mins ago")) release.PublishDate = (DateTime.Now - TimeSpan.FromMinutes(int.Parse(timeString.Split(' ')[0]))); else if (timeString.Contains("Today")) release.PublishDate = (DateTime.UtcNow - TimeSpan.FromHours(2) - TimeSpan.Parse(timeString.Split(' ')[1])).ToLocalTime(); else if (timeString.Contains("Y-day")) release.PublishDate = (DateTime.UtcNow - TimeSpan.FromHours(26) - TimeSpan.Parse(timeString.Split(' ')[1])).ToLocalTime(); else if (timeString.Contains(':')) { var utc = DateTime.ParseExact(timeString, "MM-dd HH:mm", CultureInfo.InvariantCulture) - TimeSpan.FromHours(2); release.PublishDate = DateTime.SpecifyKind(utc, DateTimeKind.Utc).ToLocalTime(); } else { var utc = DateTime.ParseExact(timeString, "MM-dd yyyy", CultureInfo.InvariantCulture) - TimeSpan.FromHours(2); release.PublishDate = DateTime.SpecifyKind(utc, DateTimeKind.Utc).ToLocalTime(); } var downloadCol = row.ChildElements.ElementAt(3).Cq().Find("a"); release.MagnetUri = new Uri(downloadCol.Attr("href")); release.InfoHash = release.MagnetUri.ToString().Split(':')[3].Split('&')[0]; var sizeString = row.ChildElements.ElementAt(4).Cq().Text().Split(' '); var sizeVal = float.Parse(sizeString[0], CultureInfo.InvariantCulture); var sizeUnit = sizeString[1]; release.Size = ReleaseInfo.GetBytes(sizeUnit, sizeVal); release.Seeders = int.Parse(row.ChildElements.ElementAt(5).Cq().Text()); release.Peers = int.Parse(row.ChildElements.ElementAt(6).Cq().Text()) + release.Seeders; releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
protected override 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); }
async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query, string baseUrl) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); string token = await GetToken(baseUrl); string searchUrl; if (query.RageID != 0) searchUrl = string.Format(baseUrl + SearchTVRageUrl, query.RageID, token); else searchUrl = string.Format(baseUrl + SearchQueryUrl, query.SearchTerm, token); var request = CreateHttpRequest(searchUrl); var response = await client.SendAsync(request); var results = await response.Content.ReadAsStringAsync(); try { var jItems = JArray.Parse(results); foreach (JObject item in jItems) { var release = new ReleaseInfo(); release.Title = (string)item["f"]; release.MagnetUri = new Uri((string)item["d"]); release.Guid = release.MagnetUri; release.PublishDate = new DateTime(1970, 1, 1); release.Size = 0; release.Seeders = 1; release.Peers = 1; release.MinimumRatio = 1; release.MinimumSeedTime = 172800; releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); } return releases.ToArray(); }
private static Func <PendingRelease, bool> MatchingReleasePredicate(ReleaseInfo release) { return(p => p.Title == release.Title && p.Release.PublishDate == release.PublishDate && p.Release.Indexer == release.Indexer); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString)); var results = await client.GetStringAsync(episodeSearchUrl); try { CQ dom = results; 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(BaseUrl + qLink.Attr("href")); release.Comments = release.Guid; release.Title = qLink.Text(); release.Description = release.Title; release.Link = new Uri(BaseUrl + qRow.Find(".quickdownload > a").Attr("href")); var dateString = qRow.Find(".name").First()[0].ChildNodes[4].NodeValue.Replace(" on", "").Trim(); //"2015-04-25 23:38:12" //"yyyy-MMM-dd hh:mm:ss" release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); var sizeStringParts = qRow.Children().ElementAt(4).InnerText.Split(' '); release.Size = ReleaseInfo.GetBytes(sizeStringParts[1], ParseUtil.CoerceFloat(sizeStringParts[0])); release.Seeders = ParseUtil.CoerceInt(qRow.Find(".seeders").Text()); release.Peers = release.Seeders + ParseUtil.CoerceInt(qRow.Find(".leechers").Text()); releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
public void Setup() { _series = Builder <Series> .CreateNew() .Build(); _episode = Builder <Episode> .CreateNew() .Build(); _profile = new Profile { Name = "Test", Cutoff = Quality.HDTV720p, Items = new List <ProfileQualityItem> { new ProfileQualityItem { Allowed = true, Quality = Quality.HDTV720p }, new ProfileQualityItem { Allowed = true, Quality = Quality.WEBDL720p }, new ProfileQualityItem { Allowed = true, Quality = Quality.Bluray720p } }, }; _series.Profile = new LazyLoaded <Profile>(_profile); _release = Builder <ReleaseInfo> .CreateNew().Build(); _parsedEpisodeInfo = Builder <ParsedEpisodeInfo> .CreateNew().Build(); _parsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p); _remoteEpisode = new RemoteEpisode(); _remoteEpisode.Episodes = new List <Episode> { _episode }; _remoteEpisode.Series = _series; _remoteEpisode.ParsedEpisodeInfo = _parsedEpisodeInfo; _remoteEpisode.Release = _release; _temporarilyRejected = new DownloadDecision(_remoteEpisode, new Rejection("Temp Rejected", RejectionType.Temporary)); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.All()) .Returns(new List <PendingRelease>()); Mocker.GetMock <ISeriesService>() .Setup(s => s.GetSeries(It.IsAny <Int32>())) .Returns(_series); Mocker.GetMock <IParsingService>() .Setup(s => s.GetEpisodes(It.IsAny <ParsedEpisodeInfo>(), _series, true, null)) .Returns(new List <Episode> { _episode }); Mocker.GetMock <IPrioritizeDownloadDecision>() .Setup(s => s.PrioritizeDecisions(It.IsAny <List <DownloadDecision> >())) .Returns((List <DownloadDecision> d) => d); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString); string results; if (Program.IsWindows) { var request = CreateHttpRequest(new Uri(episodeSearchUrl)); request.Method = HttpMethod.Get; var response = await client.SendAsync(request); results = await response.Content.ReadAsStringAsync(); } else { var response = await CurlHelper.GetAsync(episodeSearchUrl, cookieHeader); results = Encoding.UTF8.GetString(response.Content); } try { var json = JObject.Parse(results); foreach (JObject r in json["response"]["results"]) { DateTime pubDate = DateTime.MinValue; double dateNum; if (double.TryParse((string)r["groupTime"], out dateNum)) pubDate = UnixTimestampToDateTime(dateNum); var groupName = (string)r["groupName"]; if (r["torrents"] is JArray) { foreach (JObject t in r["torrents"]) { var release = new ReleaseInfo(); release.PublishDate = pubDate; release.Title = groupName; release.Description = groupName; FillReleaseInfoFromJson(release, t); releases.Add(release); } } else { var release = new ReleaseInfo(); release.PublishDate = pubDate; release.Title = groupName; release.Description = groupName; FillReleaseInfoFromJson(release, r); releases.Add(release); } } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var searchString = query.GetQueryString(); if (!string.IsNullOrWhiteSpace(searchString) && searchString.Length < 3) { return(releases); // search needs at least 3 characters } var qc = new NameValueCollection { { "size", "100" } }; if (!string.IsNullOrWhiteSpace(searchString)) { qc.Add("q", searchString); } var searchUrl = (string.IsNullOrWhiteSpace(searchString) ? NewEndpoint : SearchEndpoint) + "?" + qc.GetQueryString(); var response = await RequestWithCookiesAndRetryAsync(searchUrl); try { var jsonStart = response.ContentString; var jsonContent = JArray.Parse(jsonStart); foreach (var torrent in jsonContent) { if (torrent == null) { throw new Exception("Error: No data returned!"); } var title = torrent.Value <string>("name"); var size = torrent.Value <long>("size_bytes"); var seeders = torrent.Value <int>("seeders"); var leechers = torrent.Value <int>("leechers"); var grabs = ParseUtil.CoerceInt(torrent.Value <string>("completed") ?? "0"); var infohash = torrent.Value <JToken>("infohash").ToString(); // convert unix timestamp to human readable date var publishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0); publishDate = publishDate.AddSeconds(torrent.Value <long>("created_unix")); // construct magnet link from infohash with public trackers // TODO move trackers to List for reuse elsewhere // TODO dynamically generate list periodically from online tracker repositories like // https://github.com/ngosang/trackerslist var magnet = new Uri("magnet:?xt=urn:btih:" + infohash + "&tr=udp://tracker.coppersurfer.tk:6969/announce" + "&tr=udp://tracker.leechers-paradise.org:6969/announce" + "&tr=udp://tracker.internetwarriors.net:1337/announce" + "&tr=udp://tracker.opentrackr.org:1337/announce" + "&tr=udp://9.rarbg.to:2710/announce" + "&tr=udp://exodus.desync.com:6969/announce" + "&tr=udp://explodie.org:6969/announce" + "&tr=udp://tracker2.itzmx.com:6961/announce" + "&tr=udp://tracker1.itzmx.com:8080/announce" + "&tr=udp://tracker.torrent.eu.org:451/announce" + "&tr=udp://tracker.tiny-vps.com:6969/announce" + "&tr=udp://tracker.port443.xyz:6969/announce" + "&tr=udp://thetracker.org:80/announce" + "&tr=udp://open.stealth.si:80/announce" + "&tr=udp://open.demonii.si:1337/announce" + "&tr=udp://ipv4.tracker.harry.lu:80/announce" + "&tr=udp://denis.stalker.upeer.me:6969/announce" + "&tr=udp://tracker1.wasabii.com.tw:6969/announce" + "&tr=udp://tracker.dler.org:6969/announce" + "&tr=udp://tracker.cyberia.is:6969/announce" + "&tr=udp://tracker4.itzmx.com:2710/announce" + "&tr=udp://tracker.uw0.xyz:6969/announce" + "&tr=udp://tracker.moeking.me:6969/announce" + "&tr=udp://retracker.lanta-net.ru:2710/announce" + "&tr=udp://tracker.nyaa.uk:6969/announce" + "&tr=udp://tracker.novg.net:6969/announce" + "&tr=udp://tracker.iamhansen.xyz:2000/announce" + "&tr=udp://tracker.filepit.to:6969/announce" + "&tr=udp://tracker.dyn.im:6969/announce" + "&tr=udp://torrentclub.tech:6969/announce" + "&tr=udp://tracker.tvunderground.org.ru:3218/announce" + "&tr=udp://tracker.open-tracker.org:1337/announce" + "&tr=udp://tracker.justseed.it:1337/announce"); var release = new ReleaseInfo { Title = title, Comments = new Uri(SiteLink), // there is no comments or details link Guid = magnet, MagnetUri = magnet, InfoHash = infohash, Category = new List <int> { TorznabCatType.Other.ID }, PublishDate = publishDate, Size = size, Grabs = grabs, Seeders = seeders, Peers = leechers + seeders, DownloadVolumeFactor = 0, UploadVolumeFactor = 1, }; releases.Add(release); } } catch (Exception ex) { OnParseError(response.ContentString, ex); } return(releases); }
private static int CompareReleaseInfo(ReleaseInfo notes1, ReleaseInfo notes2) { //We do this in reverse order so that we have the latest release at the top of the list return notes2.Version.CompareTo(notes1.Version); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var queryCollection = new NameValueCollection { { "active", "0" }, { "category", string.Join(";", MapTorznabCapsToTrackers(query)) } }; if (query.IsImdbQuery) { queryCollection.Add("options", "2"); queryCollection.Add("search", query.ImdbIDShort); } else { queryCollection.Add("options", "0"); queryCollection.Add("search", query.GetQueryString()); } // remove . as not used in titles var response = await RequestWithCookiesAndRetryAsync(SearchUrl + queryCollection.GetQueryString().Replace(".", " ")); try { var resultParser = new HtmlParser(); var searchResultDocument = resultParser.ParseDocument(response.ContentString); var rows = searchResultDocument.QuerySelectorAll("table.lista > tbody > tr"); foreach (var row in rows) { // this tracker has horrible markup, find the result rows by looking for the style tag before each one var prev = row.PreviousElementSibling; if (prev == null || !string.Equals(prev.NodeName, "style", StringComparison.OrdinalIgnoreCase)) { continue; } var release = new ReleaseInfo { MinimumRatio = 1, MinimumSeedTime = 86400 // 24 hours }; var qLink = row.Children[1].FirstElementChild; release.Title = qLink.TextContent.Trim(); release.Details = new Uri(SiteLink + qLink.GetAttribute("href")); release.Guid = release.Details; var imdbLink = row.Children[1].QuerySelector("a[href*=imdb]"); if (imdbLink != null) { release.Imdb = ParseUtil.GetImdbID(imdbLink.GetAttribute("href").Split('/').Last()); } var qDownload = row.Children[3].FirstElementChild; release.Link = new Uri(SiteLink + qDownload.GetAttribute("href")); var dateStr = row.Children[4].TextContent.Trim(); //"July 11, 2015, 13:34:09", "Today|Yesterday at 20:04:23" release.PublishDate = DateTimeUtil.FromUnknown(dateStr); var sizeStr = row.Children[5].TextContent; release.Size = ReleaseInfo.GetBytes(sizeStr); release.Seeders = ParseUtil.CoerceInt(row.Children[7].TextContent); release.Peers = ParseUtil.CoerceInt(row.Children[8].TextContent) + release.Seeders; var grabs = row.QuerySelector("td:nth-child(10)").TextContent; grabs = grabs.Replace("---", "0"); release.Grabs = ParseUtil.CoerceInt(grabs); if (row.QuerySelector("img[title=\"FreeLeech\"]") != null) { release.DownloadVolumeFactor = 0; } else if (row.QuerySelector("img[src=\"images/sf.png\"]") != null) // side freeleech { release.DownloadVolumeFactor = 0; } else if (row.QuerySelector("img[title=\"Half FreeLeech\"]") != null) { release.DownloadVolumeFactor = 0.5; } else { release.DownloadVolumeFactor = 1; } release.UploadVolumeFactor = 1; var qCat = row.QuerySelector("a[href^=\"index.php?page=torrents&category=\"]"); var cat = qCat.GetAttribute("href").Split('=')[2]; release.Category = MapTrackerCatToNewznab(cat); releases.Add(release); } } catch (Exception ex) { OnParseError(response.ContentString, ex); } return(releases); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query, string baseUrl) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { "2015" }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = baseUrl + string.Format(SearchUrl, HttpUtility.UrlEncode(searchString.Trim())); var results = await client.GetStringAsync(episodeSearchUrl); try { var jResults = JObject.Parse(results); foreach (JObject result in (JArray)jResults["torrents"]) { var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; release.Title = (string)result["torrent_title"]; release.Description = release.Title; release.Seeders = (int)result["seeds"]; release.Peers = (int)result["leeches"] + release.Seeders; release.Size = (long)result["size"]; // "Apr 2, 2015", "Apr 12, 2015" (note the spacing) var dateString = string.Join(" ", ((string)result["upload_date"]).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); release.PublishDate = DateTime.ParseExact(dateString, "MMM d, yyyy", CultureInfo.InvariantCulture); release.Guid = new Uri((string)result["page"]); release.Comments = release.Guid; release.InfoHash = (string)result["torrent_hash"]; release.MagnetUri = new Uri((string)result["magnet_uri"]); release.Link = new Uri(string.Format("{0}{1}{2}", baseUrl, DownloadUrl, release.InfoHash)); releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(query.GetQueryString())); var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl); if (results.Content.Contains("No torrents found")) { return(releases); } try { CQ dom = results.Content; var rows = dom[".ctable_content_no_pad > table > tbody > tr"].ToArray(); DateTime lastDateTime = default(DateTime); for (var i = 0; i < rows.Length; i++) { var rowA = rows[i]; var rAlign = rowA.Attributes["align"]; if (rAlign == "right" || rAlign == "center") { continue; } if (rAlign == "left") { // ex: "Monday, Jun 01, 2015", "Monday, Aug 03, 2015" var dateStr = rowA.Cq().Text().Trim().Replace("Added on ", ""); if (dateStr.ToLowerInvariant().Contains("today")) { lastDateTime = DateTime.Now; } else { lastDateTime = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dddd, MMM dd, yyyy", CultureInfo.InvariantCulture), DateTimeKind.Utc).ToLocalTime(); } continue; } if (rowA.ChildElements.Count() < 2) { continue; } var rowB = rows[++i]; var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; release.PublishDate = lastDateTime; var qLink = rowA.ChildElements.ElementAt(1).FirstElementChild.Cq(); release.Title = qLink.Text().Trim(); release.Description = release.Title; release.Comments = new Uri(SiteLink + qLink.Attr("href")); release.Guid = release.Comments; var qDownload = rowB.ChildElements.ElementAt(2).ChildElements.ElementAt(1).Cq(); release.Link = new Uri(SiteLink + qDownload.Attr("href")); var sizeStr = rowB.ChildElements.ElementAt(3).Cq().Text(); release.Size = ReleaseInfo.GetBytes(sizeStr); release.Seeders = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(6).Cq().Text()); release.Peers = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(6).Cq().Text()) + release.Seeders; releases.Add(release); } } catch (Exception ex) { OnParseError(results.Content, ex); } return(releases); }
static ReleaseInfo ConvertToPublic(ReleaseInfoInternal info) { if (info == null) { // Can't return null here since unity serialization doesn't support null return new ReleaseInfo() { AssetStoreInfo = ConvertToPublic((AssetStoreInfoInternal)null), }; } var newInfo = new ReleaseInfo(); newInfo.Name = info.Name; newInfo.HasVersionCode = info.VersionCode.HasValue; if (info.VersionCode.HasValue) { newInfo.VersionCode = info.VersionCode.Value; } newInfo.HasCompressedSize = info.CompressedSize.HasValue; if (info.CompressedSize.HasValue) { newInfo.CompressedSize = info.CompressedSize.Value; } newInfo.Version = info.Version; newInfo.LocalPath = info.LocalPath; newInfo.Url = info.Url; Assert.That(!string.IsNullOrEmpty(info.Id)); newInfo.Id = info.Id; newInfo.FileModificationDate = info.FileModificationDate.HasValue ? DateTimeToString(info.FileModificationDate.Value) : null; newInfo.FileModificationDateTicks = info.FileModificationDate.HasValue ? info.FileModificationDate.Value.Ticks : 0; newInfo.AssetStoreInfo = ConvertToPublic(info.AssetStoreInfo); return newInfo; }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var searchUrl = SearchUrl + string.Join( string.Empty, MapTorznabCapsToTrackers(query).Select(cat => $"category[]={cat}&")); var queryCollection = new NameValueCollection { { "search", query.ImdbID ?? query.GetQueryString() }, { "active", "0" }, { "options", "0" } }; // manually url encode parenthesis to prevent "hacking" detection searchUrl += queryCollection.GetQueryString().Replace("(", "%28").Replace(")", "%29"); var results = await RequestWithCookiesAndRetryAsync(searchUrl); try { var parser = new HtmlParser(); var dom = parser.ParseDocument(results.ContentString); var userInfo = dom.QuerySelector("table.navus tr"); var userRank = userInfo.Children[1].TextContent.Replace("Rank:", string.Empty).Trim(); var hasFreeleech = _freeleechRanks.Contains(userRank); var rows = dom.QuerySelectorAll("table.mainblockcontenttt tr:has(td.mainblockcontent)"); foreach (var row in rows.Skip(1)) { var mainLink = row.Children[2].QuerySelector("a"); var title = mainLink.TextContent; var comments = new Uri(SiteLink + mainLink.GetAttribute("href")); var bannerMatch = _bannerRegex.Match(mainLink.GetAttribute("onmouseover")); var banner = bannerMatch.Success ? new Uri(SiteLink + bannerMatch.Groups[1].Value.Replace("\\", "/")) : null; var link = new Uri(SiteLink + row.Children[4].FirstElementChild.GetAttribute("href")); var description = row.Children[2].QuerySelector("span").TextContent; var size = ReleaseInfo.GetBytes(row.Children[7].TextContent); var dateTag = row.Children[6].FirstElementChild; var dateString = string.Join(" ", dateTag.Attributes.Select(attr => attr.Name)); var publishDate = DateTime.ParseExact(dateString, "dd MMM yyyy HH:mm:ss zz00", CultureInfo.InvariantCulture).ToLocalTime(); var catStr = row.FirstElementChild.FirstElementChild.GetAttribute("href").Split('=')[1]; var cat = MapTrackerCatToNewznab(catStr); // Sometimes the uploader column is missing, so seeders, leechers, and grabs may be at a different index. // There's room for improvement, but this works for now. var endIndex = row.Children.Length; //Maybe use row.Children.Index(Node) after searching for an element instead? if (row.Children[endIndex - 1].TextContent == "Edit") { endIndex -= 1; } // moderators get additional delete, recommend and like links else if (row.Children[endIndex - 4].TextContent == "Edit") { endIndex -= 4; } int?seeders = null; int?peers = null; if (ParseUtil.TryCoerceInt(row.Children[endIndex - 3].TextContent, out var rSeeders)) { seeders = rSeeders; if (ParseUtil.TryCoerceInt(row.Children[endIndex - 2].TextContent, out var rLeechers)) { peers = rLeechers + rSeeders; } } var grabs = ParseUtil.TryCoerceLong(row.Children[endIndex - 1].TextContent, out var rGrabs) ? (long?)rGrabs : null; var dlVolumeFactor = 1.0; var upVolumeFactor = 1.0; if (row.QuerySelector("img[src$=\"no_ratio.png\"]") != null) { dlVolumeFactor = 0; upVolumeFactor = 0; } else if (hasFreeleech || row.QuerySelector("img[src$=\"free.png\"]") != null) { dlVolumeFactor = 0; } else if (row.QuerySelector("img[src$=\"50.png\"]") != null) { dlVolumeFactor = 0.5; } else if (row.QuerySelector("img[src$=\"25.png\"]") != null) { dlVolumeFactor = 0.75; } else if (row.QuerySelector("img[src$=\"75.png\"]") != null) { dlVolumeFactor = 0.25; } var imdbLink = row.QuerySelector("a[href*=\"www.imdb.com/title/\"]")?.GetAttribute("href"); var imdb = !string.IsNullOrWhiteSpace(imdbLink) ? ParseUtil.GetLongFromString(imdbLink) : null; var release = new ReleaseInfo { Title = title, Comments = comments, Guid = comments, Link = link, PublishDate = publishDate, Category = cat, Description = description, BannerUrl = banner, Imdb = imdb, Size = size, Grabs = grabs, Seeders = seeders, Peers = peers, DownloadVolumeFactor = dlVolumeFactor, UploadVolumeFactor = upVolumeFactor, MinimumRatio = 1, MinimumSeedTime = 172800 // 48 hours }; releases.Add(release); } } catch (Exception ex) { OnParseError(results.ContentString, ex); } return(releases); }
IEnumerator<InstallReleaseUserChoices> CheckShouldInstall(ReleaseInfo releaseInfo) { return CoRoutine.Wrap<InstallReleaseUserChoices>(CheckShouldInstallInternal(releaseInfo)); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var qc = new NameValueCollection { { "incldead", "1" } }; if (query.IsImdbQuery) { qc.Add("search", query.ImdbID); qc.Add("sc", "2"); // search in description } else { qc.Add("search", query.GetQueryString()); qc.Add("sc", "1"); // search in title } foreach (var cat in MapTorznabCapsToTrackers(query)) { qc.Add("c" + cat, "1"); } var searchUrl = SearchUrl + "?" + qc.GetQueryString(); var response = await RequestStringWithCookiesAndRetry(searchUrl, referer : SearchUrl); if (response.IsRedirect) // re-login { await ApplyConfiguration(null); response = await RequestStringWithCookiesAndRetry(searchUrl, null, SearchUrl); } try { var parser = new HtmlParser(); var dom = parser.ParseDocument(response.Content); var rows = dom.QuerySelectorAll("table > tbody:has(tr > td.colhead) > tr:not(:has(td.colhead))"); foreach (var row in rows) { var release = new ReleaseInfo(); var link = row.QuerySelector("td:nth-of-type(2) a:nth-of-type(2)"); release.Guid = new Uri(SiteLink + link.GetAttribute("href")); release.Comments = release.Guid; release.Title = link.GetAttribute("title"); // There isn't a title attribute if the release name isn't truncated. if (string.IsNullOrWhiteSpace(release.Title)) { release.Title = link.FirstChild.TextContent.Trim(); } release.Description = release.Title; // If we search an get no results, we still get a table just with no info. if (string.IsNullOrWhiteSpace(release.Title)) { break; } // Check if the release has been assigned a category var qCat = row.QuerySelector("td:nth-of-type(1) a"); if (qCat != null) { var cat = qCat.GetAttribute("href").Substring(15); release.Category = MapTrackerCatToNewznab(cat); } var qLink = row.QuerySelector("td:nth-of-type(2) a"); release.Link = new Uri(SiteLink + qLink.GetAttribute("href")); var added = row.QuerySelector("td:nth-of-type(5)").TextContent.Trim(); release.PublishDate = DateTime.ParseExact(added, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture); var sizeStr = row.QuerySelector("td:nth-of-type(7)").TextContent.Trim(); release.Size = ReleaseInfo.GetBytes(sizeStr); release.Seeders = ParseUtil.CoerceInt(row.QuerySelector("td:nth-of-type(9)").TextContent.Trim()); release.Peers = ParseUtil.CoerceInt(row.QuerySelector("td:nth-of-type(10)").TextContent.Trim()) + release.Seeders; var files = row.QuerySelector("td:nth-child(3)").TextContent; release.Files = ParseUtil.CoerceInt(files); var grabs = row.QuerySelector("td:nth-child(8)").TextContent; if (grabs != "----") { release.Grabs = ParseUtil.CoerceInt(grabs); } release.DownloadVolumeFactor = row.QuerySelector("font[color=\"green\"]:contains(\"F\"):contains(\"L\")") != null ? 0 : 1; release.UploadVolumeFactor = 1; releases.Add(release); } } catch (Exception ex) { OnParseError(response.Content, ex); } return(releases); }
PackageInfo TryFindPackageInfoForRelease(ReleaseInfo releaseInfo) { foreach (var packageInfo in _model.AllPackages) { if (packageInfo.InstallInfo != null && packageInfo.InstallInfo.ReleaseInfo != null && packageInfo.InstallInfo.ReleaseInfo.Id == releaseInfo.Id) { return packageInfo; } } return null; }
private void listViewMods_ItemChecked(object sender, ItemCheckedEventArgs e) { ReleaseInfo release = (ReleaseInfo)e.Item.Tag; if (release.disabled) { e.Item.Checked = release.install; return; } else { release.install = e.Item.Checked; } if (e.Item.Checked) { if (release.dependsOn.Count > 0) { foreach (ModLink dependency in release.dependsOn) { foreach (ListViewItem lvi in listViewMods.Items) { ReleaseInfo check = (ReleaseInfo)lvi.Tag; if (check.name == dependency.name) { check.itemHandle.Checked = true; } } } } } if (e.Item.Checked) { if (release.conflictsWith.Count > 0) { foreach (ModLink dependency in release.conflictsWith) { foreach (ListViewItem lvi in listViewMods.Items) { ReleaseInfo check = (ReleaseInfo)lvi.Tag; if (check.name == dependency.name) { check.itemHandle.Checked = false; check.disabled = true; } } } } } else { if (release.conflictsWith.Count > 0) { foreach (ModLink dependency in release.conflictsWith) { foreach (ListViewItem lvi in listViewMods.Items) { ReleaseInfo check = (ReleaseInfo)lvi.Tag; if (check.name == dependency.name) { check.disabled = false; } } } } } if (finishedLoading) { ReRenderListView(); } }
async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query, string baseUrl) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString.Trim())); XmlDocument xmlDoc = new XmlDocument(); string xml = string.Empty; WebClient wc = getWebClient(); try { using (wc) { xml = wc.DownloadString(episodeSearchUrl); xmlDoc.LoadXml(xml); } ReleaseInfo release; TorrentzHelper td; string serie_title; foreach (XmlNode node in xmlDoc.GetElementsByTagName("item")) { release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; serie_title = node.SelectSingleNode("title").InnerText; release.Title = serie_title; release.Comments = new Uri(node.SelectSingleNode("link").InnerText); release.Category = node.SelectSingleNode("category").InnerText; release.Guid = new Uri(node.SelectSingleNode("guid").InnerText); release.PublishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture); td = new TorrentzHelper(node.SelectSingleNode("description").InnerText); release.Description = td.Description; release.InfoHash = td.hash; release.Size = td.Size; release.Seeders = td.Seeders; release.Peers = td.Peers + release.Seeders; release.MagnetUri = TorrentzHelper.createMagnetLink(td.hash, serie_title); releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, xml, ex); throw ex; } } return releases.ToArray(); }
private async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query, int attempts) { await CheckToken(); var releases = new List <ReleaseInfo>(); var searchString = query.GetQueryString(); var queryCollection = new NameValueCollection(); queryCollection.Add("token", token); queryCollection.Add("format", "json_extended"); queryCollection.Add("app_id", app_id); queryCollection.Add("limit", "100"); queryCollection.Add("ranked", "0"); queryCollection.Add("sort", _sort); if (query.ImdbID != null) { queryCollection.Add("mode", "search"); queryCollection.Add("search_imdb", query.ImdbID); } else if (query.RageID != null) { queryCollection.Add("mode", "search"); queryCollection.Add("search_tvrage", query.RageID.ToString()); } /*else if (query.TvdbID != null) * { * queryCollection.Add("mode", "search"); * queryCollection.Add("search_tvdb", query.TvdbID); * }*/ else if (!string.IsNullOrWhiteSpace(searchString)) { searchString = searchString.Replace("'", ""); // ignore ' (e.g. search for america's Next Top Model) queryCollection.Add("mode", "search"); queryCollection.Add("search_string", searchString); } else { queryCollection.Add("mode", "list"); queryCollection.Remove("sort"); } var querycats = MapTorznabCapsToTrackers(query); if (querycats.Count == 0) { querycats = GetAllTrackerCategories(); // default to all, without specifing it some categories are missing (e.g. games), see #4146 } var cats = string.Join(";", querycats); queryCollection.Add("category", cats); var searchUrl = ApiEndpoint + "?" + queryCollection.GetQueryString(); var response = await RequestStringWithCookiesAndRetry(searchUrl, string.Empty); try { var jsonContent = JObject.Parse(response.Content); var errorCode = jsonContent.Value <int>("error_code"); if (errorCode == 20) // no results found { return(releases.ToArray()); } // return empty results in case of invalid imdb ID, see issue #1486 if (errorCode == 10) // Cant find imdb in database. Are you sure this imdb exists? { return(releases); } if (errorCode == 2 || // Invalid token set! errorCode == 4) // Invalid token. Use get_token for a new one! { token = null; if (attempts < 3) { return(await PerformQuery(query, ++attempts)); } else { throw new Exception("error " + errorCode.ToString() + " after " + attempts.ToString() + " attempts: " + jsonContent.Value <string>("error")); } } if (errorCode > 0) // too many requests per seconds ??? { // we use the IwebClient rate limiter now, this shouldn't happen throw new Exception("error " + errorCode.ToString() + ": " + jsonContent.Value <string>("error")); } foreach (var item in jsonContent.Value <JArray>("torrent_results")) { var release = new ReleaseInfo(); release.Title = WebUtility.HtmlDecode(item.Value <string>("title")); release.Category = MapTrackerCatDescToNewznab(item.Value <string>("category")); release.MagnetUri = new Uri(item.Value <string>("download")); release.InfoHash = release.MagnetUri.ToString().Split(':')[3].Split('&')[0]; // append app_id to prevent api server returning 403 forbidden release.Comments = new Uri(item.Value <string>("info_page") + "&app_id=" + app_id); if (_provideTorrentLink) { release.Link = release.Comments; // in case of a torrent download we grab the link from the details page in Download() } release.Guid = release.MagnetUri; var episodeInfo = item.Value <JToken>("episode_info"); if (episodeInfo.HasValues) { var imdb = episodeInfo.Value <string>("imdb"); release.Imdb = ParseUtil.GetImdbID(imdb); release.TVDBId = episodeInfo.Value <long?>("tvdb"); release.RageID = episodeInfo.Value <long?>("tvrage"); release.TMDb = episodeInfo.Value <long?>("themoviedb"); } // ex: 2015-08-16 21:25:08 +0000 var dateStr = item.Value <string>("pubdate").Replace(" +0000", ""); var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); release.PublishDate = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc).ToLocalTime(); release.Seeders = item.Value <int>("seeders"); release.Peers = item.Value <int>("leechers") + release.Seeders; release.Size = item.Value <long>("size"); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; // 48 hours release.DownloadVolumeFactor = 0; release.UploadVolumeFactor = 1; releases.Add(release); } } catch (Exception ex) { OnParseError(response.Content, ex); } return(releases); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var searchContent = GetSearchFormData(searchString); var response = await client.PostAsync(SearchUrl, searchContent); var results = await response.Content.ReadAsStringAsync(); try { CQ dom = results; var rows = dom["tr.browse"]; foreach (var row in rows) { var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; var descCol = row.ChildElements.ElementAt(1); var qDescCol = descCol.Cq(); var qLink = qDescCol.Find("a"); release.Title = qLink.Text(); release.Description = release.Title; release.Comments = new Uri(BaseUrl + "/" + qLink.Attr("href")); release.Guid = release.Comments; var torrentId = qLink.Attr("href").Split('=')[1]; release.Link = new Uri(string.Format(DownloadUrl, torrentId)); var dateStr = descCol.ChildNodes.Last().NodeValue.Trim(); var euDate = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); var localDate = TimeZoneInfo.ConvertTimeToUtc(euDate, TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time")).ToLocalTime(); release.PublishDate = localDate; var sizeNodes = row.ChildElements.ElementAt(3).ChildNodes; var sizeVal = sizeNodes.First().NodeValue; var sizeUnit = sizeNodes.Last().NodeValue; release.Size = ReleaseInfo.GetBytes(sizeUnit, ParseUtil.CoerceFloat(sizeVal)); release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(4).Cq().Text().Trim()); release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(5).Cq().Text().Trim()) + release.Seeders; releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
/// <summary> /// Execute our search query /// </summary> /// <param name="query">Query</param> /// <returns>Releases</returns> protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var torrentRowList = new List <CQ>(); var exactSearchTerm = query.GetQueryString(); var searchUrl = SearchUrl; // Check login before performing a query await CheckLogin(); // Check cache first so we don't query the server (if search term used or not in dev mode) if (!DevMode && !string.IsNullOrEmpty(exactSearchTerm)) { lock (cache) { // Remove old cache items CleanCache(); // Search in cache var cachedResult = cache.FirstOrDefault(i => i.Query == exactSearchTerm); if (cachedResult != null) { return(cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray()); } } } var SearchTerms = new List <string> { exactSearchTerm }; // duplicate search without diacritics var baseSearchTerm = StringUtil.RemoveDiacritics(exactSearchTerm); if (baseSearchTerm != exactSearchTerm) { SearchTerms.Add(baseSearchTerm); } foreach (var searchTerm in SearchTerms) { // Build our query var request = BuildQuery(searchTerm, query, searchUrl); // Getting results & Store content var response = await RequestStringWithCookiesAndRetry(request, ConfigData.CookieHeader.Value); _fDom = response.Content; try { var firstPageRows = FindTorrentRows(); // Add them to torrents list torrentRowList.AddRange(firstPageRows.Select(fRow => fRow.Cq())); // If pagination available int nbResults; int pageLinkCount; nbResults = 1; pageLinkCount = 1; // Check if we have a minimum of one result if (firstPageRows.Length > 1) { // Retrieve total count on our alone page nbResults = firstPageRows.Count(); } else { // Check if no result if (torrentRowList.Count == 0) { // No results found Output("\nNo result found for your query, please try another search term ...\n", "info"); // No result found for this query break; } } Output("\nFound " + nbResults + " result(s) (+/- " + firstPageRows.Length + ") in " + pageLinkCount + " page(s) for this query !"); Output("\nThere are " + (firstPageRows.Length - 2) + " results on the first page !"); // Loop on results foreach (var tRow in torrentRowList.Skip(1).Take(torrentRowList.Count - 2)) { Output("Torrent #" + (releases.Count + 1)); // ID var idOrig = tRow.Find("td:eq(1) > a:eq(0)").Attr("href").Split('=')[1]; var id = idOrig.Substring(0, idOrig.Length - 4); Output("ID: " + id); // Release Name var name = tRow.Find("td:eq(1) > a:eq(0)").Text(); // Category string categoryID = tRow.Find("td:eq(0) > a:eq(0)").Attr("href").Split('?').Last(); var newznab = MapTrackerCatToNewznab(categoryID); Output("Category: " + MapTrackerCatToNewznab(categoryID).First().ToString() + " (" + categoryID + ")"); // Seeders int seeders = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(9)").Text(), @"\d+").Value); Output("Seeders: " + seeders); // Leechers int leechers = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(10)").Text(), @"\d+").Value); Output("Leechers: " + leechers); // Files int files = 1; files = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(4)").Text(), @"\d+").Value); Output("Files: " + files); // Completed int completed = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(8)").Text(), @"\d+").Value); Output("Completed: " + completed); // Size var humanSize = tRow.Find("td:eq(7)").Text().ToLowerInvariant(); var size = ReleaseInfo.GetBytes(humanSize); Output("Size: " + humanSize + " (" + size + " bytes)"); // Publish DateToString var dateTimeOrig = tRow.Find("td:eq(6)").Text(); var datestr = Regex.Replace(dateTimeOrig, @"<[^>]+>| ", "").Trim(); datestr = Regex.Replace(datestr, "Today", DateTime.Now.ToString("MMM dd yyyy"), RegexOptions.IgnoreCase); datestr = Regex.Replace(datestr, "Yesterday", DateTime.Now.Date.AddDays(-1).ToString("MMM dd yyyy"), RegexOptions.IgnoreCase); DateTime date = DateTimeUtil.FromUnknown(datestr, "DK"); Output("Released on: " + date); // Torrent Details URL var detailsLink = new Uri(TorrentDescriptionUrl.Replace("{id}", id.ToString())); Output("Details: " + detailsLink.AbsoluteUri); // Torrent Comments URL var commentsLink = new Uri(TorrentCommentUrl.Replace("{id}", id.ToString())); Output("Comments Link: " + commentsLink.AbsoluteUri); // Torrent Download URL var passkey = tRow.Find("td:eq(2) > a:eq(0)").Attr("href"); var key = Regex.Match(passkey, "(?<=torrent_pass\\=)([a-zA-z0-9]*)"); Uri downloadLink = new Uri(TorrentDownloadUrl.Replace("{id}", id.ToString()).Replace("{passkey}", key.ToString())); Output("Download Link: " + downloadLink.AbsoluteUri); // Building release infos var release = new ReleaseInfo { Category = MapTrackerCatToNewznab(categoryID.ToString()), Title = name, Seeders = seeders, Peers = seeders + leechers, MinimumRatio = 1, MinimumSeedTime = 172800, PublishDate = date, Size = size, Files = files, Grabs = completed, Guid = detailsLink, Comments = commentsLink, Link = downloadLink }; // IMDB var imdbLink = tRow.Find("a[href*=\"http://imdb.com/title/\"]").First().Attr("href"); release.Imdb = ParseUtil.GetLongFromString(imdbLink); if (tRow.Find("img[title=\"Free Torrent\"]").Length >= 1) { release.DownloadVolumeFactor = 0; } else if (tRow.Find("img[title=\"Halfleech\"]").Length >= 1) { release.DownloadVolumeFactor = 0.5; } else if (tRow.Find("img[title=\"90% Freeleech\"]").Length >= 1) { release.DownloadVolumeFactor = 0.1; } else { release.DownloadVolumeFactor = 1; } release.UploadVolumeFactor = 1; releases.Add(release); } } catch (Exception ex) { OnParseError("Error, unable to parse result \n" + ex.StackTrace, ex); } } // Return found releases return(releases); }
public void event_btnParseFullSceneName_Activated(object sender, EventArgs e) { var openPanel = new NSOpenPanel(); openPanel.ReleasedWhenClosed = true; openPanel.Prompt = "Select file"; openPanel.AllowedFileTypes = new string[] {"torrent"}; openPanel.AllowsMultipleSelection = false; openPanel.CanChooseDirectories = false; openPanel.CanCreateDirectories = false; var result = openPanel.RunModal(); if (result == 1) { txtFullSceneName.StringValue = openPanel.Url.Path; } else { return; } _releaseInfo = new ReleaseInfo (); string fullSceneName = Path.GetFileNameWithoutExtension(txtFullSceneName.StringValue); fullSceneName = fullSceneName.Replace ('.', ' '); fullSceneName = fullSceneName.Replace ('_', ' '); fullSceneName = fullSceneName.Replace ('-', ' '); //Multilingual? _releaseInfo.releaseIsMultilingual = fullSceneName.IndexOf ("Multilingual") == -1 && fullSceneName.IndexOf ("Bilingual") == -1 ? false : true; fullSceneName = fullSceneName.Replace ("Multilingual", ""); fullSceneName = fullSceneName.Replace ("Bilingual", ""); //Cracked, regged, retail, etc. _releaseInfo.releaseIsCracked = fullSceneName.IndexOf ("Cracked") == -1 ? false : true; _releaseInfo.releaseIsRetail = fullSceneName.IndexOf ("Retail") == -1 ? false : true; _releaseInfo.releaseIsKeygen = false; if (fullSceneName.IndexOf ("Keyfilemaker") != -1 || fullSceneName.IndexOf ("Keygen") != -1 || fullSceneName.IndexOf ("Keymaker") != -1) _releaseInfo.releaseIsKeygen = true; int whereIsMacosx = fullSceneName.ToUpper().IndexOf ("MACOSX"); _releaseInfo.releaseName = string.Empty; _releaseInfo.releaseVersion = string.Empty; bool parsingVersion = false; for (int i = 0; i < whereIsMacosx - 1; i++) { if (fullSceneName.ToUpper() [i] == 'V' && char.IsNumber(fullSceneName [i + 1])) parsingVersion = true; if (parsingVersion) { _releaseInfo.releaseVersion += fullSceneName [i]; } else { _releaseInfo.releaseName += fullSceneName [i]; } } if (string.IsNullOrEmpty (_releaseInfo.releaseVersion)) _releaseInfo.releaseVersion = "v1.0"; _releaseInfo.releaseName = _releaseInfo.releaseName.Trim (); _releaseInfo.releaseVersion = _releaseInfo.releaseVersion.Substring(1).Trim().Replace(' ','.'); string[] fullSceneNameArray = fullSceneName.Split (' '); _releaseInfo.releaseGroup = fullSceneNameArray [fullSceneNameArray.Length - 1]; txtSearchTerms.StringValue = _releaseInfo.releaseName; lblReleaseName.StringValue = _releaseInfo.releaseName; lblReleaseVersion.StringValue = _releaseInfo.releaseVersion; lblReleaseGroup.StringValue = _releaseInfo.releaseGroup; lblReleaseMulti.StringValue = "Multi: " + _releaseInfo.releaseIsMultilingual.ToString (); lblReleaseRegType.StringValue = "Reg. Type: "; if (_releaseInfo.releaseIsCracked) lblReleaseRegType.StringValue += "Cracked "; if (_releaseInfo.releaseIsRetail) lblReleaseRegType.StringValue += "Retail "; if (_releaseInfo.releaseIsKeygen) lblReleaseRegType.StringValue += "Keygen "; string crackType = string.Empty; if (_releaseInfo.releaseIsCracked) crackType = "Crack"; else if (_releaseInfo.releaseIsKeygen) crackType = "Keygen"; else crackType = "Retail"; txtTitleCode.StringValue = _releaseInfo.releaseName + " [Intel:"+ crackType +"] ["+ _releaseInfo.releaseVersion +"]"; }
public void Setup() { _artist = Builder <Artist> .CreateNew() .Build(); _album = Builder <Album> .CreateNew() .Build(); _profile = new QualityProfile { Name = "Test", Cutoff = Quality.MP3_256.Id, Items = new List <QualityProfileQualityItem> { new QualityProfileQualityItem { Allowed = true, Quality = Quality.MP3_256 }, new QualityProfileQualityItem { Allowed = true, Quality = Quality.MP3_320 }, new QualityProfileQualityItem { Allowed = true, Quality = Quality.FLAC } }, }; _artist.QualityProfile = new LazyLoaded <QualityProfile>(_profile); _release = Builder <ReleaseInfo> .CreateNew().Build(); _parsedAlbumInfo = Builder <ParsedAlbumInfo> .CreateNew().Build(); _parsedAlbumInfo.Quality = new QualityModel(Quality.MP3_256); _remoteAlbum = new RemoteAlbum(); _remoteAlbum.Albums = new List <Album> { _album }; _remoteAlbum.Artist = _artist; _remoteAlbum.ParsedAlbumInfo = _parsedAlbumInfo; _remoteAlbum.Release = _release; _temporarilyRejected = new DownloadDecision(_remoteAlbum, new Rejection("Temp Rejected", RejectionType.Temporary)); _heldReleases = new List <PendingRelease>(); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.All()) .Returns(_heldReleases); Mocker.GetMock <IPendingReleaseRepository>() .Setup(s => s.AllByArtistId(It.IsAny <int>())) .Returns <int>(i => _heldReleases.Where(v => v.ArtistId == i).ToList()); Mocker.GetMock <IArtistService>() .Setup(s => s.GetArtist(It.IsAny <int>())) .Returns(_artist); Mocker.GetMock <IArtistService>() .Setup(s => s.GetArtists(It.IsAny <IEnumerable <int> >())) .Returns(new List <Artist> { _artist }); Mocker.GetMock <IParsingService>() .Setup(s => s.GetAlbums(It.IsAny <ParsedAlbumInfo>(), _artist, null)) .Returns(new List <Album> { _album }); Mocker.GetMock <IPrioritizeDownloadDecision>() .Setup(s => s.PrioritizeDecisions(It.IsAny <List <DownloadDecision> >())) .Returns((List <DownloadDecision> d) => d); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString)); var message = new HttpRequestMessage(); message.Method = HttpMethod.Get; message.RequestUri = new Uri(episodeSearchUrl); var response = await client.SendAsync(message); var results = await response.Content.ReadAsStringAsync(); try { CQ dom = results; var rows = dom[".results_index ul"]; foreach (var row in rows) { var release = new ReleaseInfo(); CQ qRow = row.Cq(); CQ qLink = qRow.Find("li.torrents_name > .torrents_name_link").First(); CQ qDlLink = qRow.Find("li.torrents_download > a").First(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; release.Title = qLink.Text().Trim(); release.Description = release.Title; release.Comments = new Uri(BaseUrl + "/" + qLink.Attr("href").TrimStart('/')); release.Guid = release.Comments; release.Link = new Uri(BaseUrl + "/" + qDlLink.Attr("href").TrimStart('/')); release.PublishDate = DateTime.Now; release.Seeders = ParseUtil.CoerceInt(qRow.Find("li.torrents_seeders").Text()); release.Peers = ParseUtil.CoerceInt(qRow.Find("li.torrents_leechers").Text()) + release.Seeders; var sizeParts = qRow.Find("li.torrents_size").Text().Split(' '); var sizeVal = ParseUtil.CoerceFloat(sizeParts[0]); var sizeUnit = sizeParts[1]; release.Size = ReleaseInfo.GetBytes(sizeUnit, sizeVal); releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var searchUrl = BrowsePage; if (!string.IsNullOrWhiteSpace(query.GetQueryString())) { searchUrl += string.Format(QueryString, WebUtility.UrlEncode(query.GetQueryString())); } var results = await RequestStringWithCookiesAndRetry(searchUrl); // Occasionally the cookies become invalid, login again if that happens if (results.Content.Contains("You do not have permission to access this page.")) { await ApplyConfiguration(null); results = await RequestStringWithCookiesAndRetry(searchUrl); } try { CQ dom = results.Content; var rows = dom["#sortabletable tr:has(a[href*=\"details.php?id=\"])"]; foreach (var row in rows) { var release = new ReleaseInfo(); var qRow = row.Cq(); var qDetails = qRow.Find("div > a[href*=\"details.php?id=\"]"); // details link, release name get's shortened if it's to long var qTitle = qRow.Find("td:eq(1) .tooltip-content div:eq(0)"); // use Title from tooltip if (!qTitle.Any()) // fallback to Details link if there's no tooltip { qTitle = qDetails; } release.Title = qTitle.Text(); var qDesciption = qRow.Find(".tooltip-content > div"); if (qDesciption.Any()) { release.Description = qDesciption.Get(1).InnerText.Trim(); } var qLink = row.Cq().Find("td:eq(2) a:eq(1)"); release.Link = new Uri(qLink.Attr("href")); release.Guid = release.Link; release.Comments = new Uri(qDetails.Attr("href")); // 07-22-2015 11:08 AM var dateString = qRow.Find("td:eq(1) div").Last().Get(0).LastChild.ToString().Trim(); release.PublishDate = DateTime.ParseExact(dateString, "MM-dd-yyyy hh:mm tt", CultureInfo.InvariantCulture); var sizeStr = qRow.Find("td:eq(4)").Text().Trim(); release.Size = ReleaseInfo.GetBytes(sizeStr); release.Seeders = ParseUtil.CoerceInt(qRow.Find("td:eq(6)").Text().Trim()); release.Peers = ParseUtil.CoerceInt(qRow.Find("td:eq(7)").Text().Trim()) + release.Seeders; var catLink = row.Cq().Find("td:eq(0) a").First().Attr("href"); var catSplit = catLink.IndexOf("category="); if (catSplit > -1) { catLink = catLink.Substring(catSplit + 9); } release.Category = MapTrackerCatToNewznab(catLink); var grabs = qRow.Find("td:nth-child(6)").Text(); release.Grabs = ParseUtil.CoerceInt(grabs); if (qRow.Find("img[title^=\"Free Torrent\"]").Length >= 1) { release.DownloadVolumeFactor = 0; } else if (qRow.Find("img[title^=\"Silver Torrent\"]").Length >= 1) { release.DownloadVolumeFactor = 0.5; } else { release.DownloadVolumeFactor = 1; } release.UploadVolumeFactor = 1; releases.Add(release); } } catch (Exception ex) { OnParseError(results.Content, ex); } return(releases); }
private void bgwCheckUpdates_DoWork(object sender, DoWorkEventArgs e) { Exception error = null; string result = null; WebResponse response = null; try { string json; HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api.github.com/repos/mlocati/MediaData/releases"); request.UserAgent = string.Format("{0} v{1}", Application.ProductName, Application.ProductVersion); request.Credentials = CredentialCache.DefaultCredentials; try { response = request.GetResponse(); } catch (WebException x) { response = x.Response; if (response == null) { throw x; } } HttpWebResponse httpResponse = response as HttpWebResponse; if (httpResponse == null) { throw new Exception(i18n.No_server_response); } if ((int)httpResponse.StatusCode < 200 || (int)httpResponse.StatusCode >= 300) { throw new Exception(httpResponse.StatusDescription); } Encoding encoding = null; try { encoding = Encoding.GetEncoding(httpResponse.CharacterSet); } catch { } if (encoding == null) { encoding = Encoding.UTF8; } using (Stream dataStream = response.GetResponseStream()) { using (StreamReader sr = new StreamReader(dataStream, encoding)) { json = sr.ReadToEnd(); } } Version installedVersion = new Version(Application.ProductVersion); JsonData data = JsonMapper.ToObject(json); if (!data.IsArray) { throw new Exception("Bad JSON: expecting an array..."); } ReleaseInfo currentRelease = null; List<ReleaseInfo> nextReleases = new List<ReleaseInfo>(); foreach (JsonData jsonRelease in data) { ReleaseInfo ri = new ReleaseInfo(jsonRelease); int cmp = installedVersion.CompareTo(ri.Version); if (cmp == 0) { currentRelease = ri; } else if (cmp < 0) { nextReleases.Add(ri); } } if (nextReleases.Count == 0) { result = ""; } else { StringBuilder sb = new StringBuilder(); if (currentRelease != null) { sb.AppendLine(string.Format(i18n.Current_version_X, currentRelease.Version.ToString())); sb.AppendLine(string.Format(i18n.Released_on_X, currentRelease.Date.ToString())); sb.AppendLine(); } nextReleases.Sort(delegate (ReleaseInfo a, ReleaseInfo b) { return b.Version.CompareTo(b.Version); }); foreach (ReleaseInfo ri in nextReleases) { sb.AppendLine(string.Format(i18n.Version_X, ri.Version.ToString())); sb.AppendLine(string.Format(i18n.Released_on_X, ri.Date.ToString())); if (ri.ReleaseNotes.Length > 0) { sb.AppendLine(i18n.Release_notes_).AppendLine("\t" + ri.ReleaseNotes.Replace(Environment.NewLine, Environment.NewLine + "\t")); } sb.AppendLine(); } result = sb.ToString().TrimEnd(); } } catch (Exception x) { error = x; } finally { if (response != null) { try { response.Close(); } catch { } } } if (error == null) { e.Result = result; } else { e.Result = error; } }
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.SupportsImdbMovieSearch) && !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); }
async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query, string baseUrl) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = string.Format(searchAllUrl); XmlDocument xmlDoc = new XmlDocument(); string xml = string.Empty; WebClient wc = getWebClient(); try { using (wc) { xml = wc.DownloadString(episodeSearchUrl); xmlDoc.LoadXml(xml); } 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("title").InnerText; release.Title = serie_title; release.Comments = new Uri(node.SelectSingleNode("link").InnerText); release.Category = node.SelectSingleNode("title").InnerText; 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.MagnetUri = new Uri(node.SelectSingleNode("link").InnerText); releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, xml, ex); throw ex; } } return releases.ToArray(); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); // TODO: IMDB search is available but it requires to parse the details page var qc = new NameValueCollection { { "order_by", "time" }, { "order_way", "desc" }, { "action", "basic" }, { "searchsubmit", "1" }, { "searchstr", query.IsImdbQuery ? query.ImdbID : query.GetQueryString() } }; var catList = MapTorznabCapsToTrackers(query); foreach (var cat in catList) { qc.Add($"filter_cat[{cat}]", "1"); } var searchUrl = BrowseUrl + "?" + qc.GetQueryString(); var results = await RequestStringWithCookies(searchUrl); try { var parser = new HtmlParser(); var doc = parser.ParseDocument(results.Content); var rows = doc.QuerySelectorAll("table.torrent_table > tbody > tr.torrent"); foreach (var row in rows) { var qDetailsLink = row.QuerySelector("a.torrent_name"); var year = qDetailsLink.NextSibling.TextContent.Replace("[", "").Replace("]", "").Trim(); var tags = row.QuerySelector("div.torrent_info").FirstChild.TextContent.Replace(" / ", " ").Trim(); var title = $"{qDetailsLink.TextContent} {year} {tags}"; var description = row.QuerySelector("div.tags").TextContent.Trim(); var comments = new Uri(SiteLink + qDetailsLink.GetAttribute("href")); var torrentId = qDetailsLink.GetAttribute("href").Split('=').Last(); var link = new Uri(SiteLink + "torrents.php?action=download&id=" + torrentId); var bannerStr = qDetailsLink.GetAttribute("data-cover"); var banner = !string.IsNullOrWhiteSpace(bannerStr) ? new Uri(qDetailsLink.GetAttribute("data-cover")) : null; var files = ParseUtil.CoerceLong(row.QuerySelector("td:nth-child(3)").TextContent); var publishDate = DateTimeUtil.FromTimeAgo(row.QuerySelector("td:nth-child(4)").TextContent); var size = ReleaseInfo.GetBytes(row.QuerySelector("td:nth-child(5)").FirstChild.TextContent); var grabs = ParseUtil.CoerceLong(row.QuerySelector("td:nth-child(6)").TextContent); var seeders = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(7)").TextContent); var leechers = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(8)").TextContent); var dlVolumeFactor = row.QuerySelector("strong.tl_free") != null ? 0 : 1; var cat = row.QuerySelector("td.cats_col > div").GetAttribute("class").Replace("tooltip cats_", ""); var category = new List <int> { cat switch { "featurefilm" => TorznabCatType.Movies.ID, "shortfilm" => TorznabCatType.Movies.ID, "miniseries" => TorznabCatType.TV.ID, "other" => TorznabCatType.Other.ID, _ => throw new Exception($"Unknown category: {cat}") } }; // TODO: TMDb is also available var qImdb = row.QuerySelector("a[href^=\"https://www.imdb.com\"]"); var imdb = qImdb != null?ParseUtil.GetImdbID(qImdb.GetAttribute("href").Split('/').Last()) : null; var release = new ReleaseInfo { MinimumRatio = 1, MinimumSeedTime = 0, Description = description, Title = title, PublishDate = publishDate, Category = category, Link = link, Comments = comments, Guid = link, Imdb = imdb, BannerUrl = banner, Seeders = seeders, Peers = leechers + seeders, Size = size, Grabs = grabs, Files = files, DownloadVolumeFactor = dlVolumeFactor, UploadVolumeFactor = 1 }; releases.Add(release); } } catch (Exception ex) { OnParseError(results.Content, ex); } return(releases); }
object GetReleaseSortField(ReleaseInfo info) { switch ((ReleasesSortMethod)_view.GetList(DragListTypes.Release).SortMethod) { case ReleasesSortMethod.Name: { return info.Name; } case ReleasesSortMethod.FileModificationDate: { return info.FileModificationDateTicks; } case ReleasesSortMethod.Size: { return info.CompressedSize; } case ReleasesSortMethod.ReleaseDate: { return info.AssetStoreInfo.PublishDateTicks; } } Assert.Throw(); return null; }
public SubDbSubtitleProvider(ReleaseInfo clientVersion) { ClientVersion = clientVersion; }
void FillReleaseInfoFromJson(ReleaseInfo release, JObject r) { var id = r["torrentId"]; release.Size = (long)r["size"]; release.Seeders = (int)r["seeders"]; release.Peers = (int)r["leechers"] + release.Seeders; release.Guid = new Uri(GuidUrl + id); release.Comments = release.Guid; release.Link = new Uri(DownloadUrl + id); }
private IEnumerable <ReleaseInfo> ParseResult(string response) { const string rowSelector = "div#content table > tbody > tr"; try { var resultParser = new HtmlParser(); var resultDocument = resultParser.ParseDocument(response); IEnumerable <IElement> rows = resultDocument.QuerySelectorAll(rowSelector); var releases = new List <ReleaseInfo>(); foreach (var r in rows) { try { var release = new ReleaseInfo(); release.Category = ParseValueFromRow(r, nameof(release.Category), "td:nth-child(1) a", (e) => MapTrackerCatToNewznab(e.Attributes["href"].Value.Substring(5))); release.Title = ParseStringValueFromRow(r, nameof(release.Title), "td:nth-child(3) span"); release.Link = ParseValueFromRow(r, nameof(release.Link), "a[href^=\"/dl/\"]", (e) => GetAbsoluteUrl(e.Attributes["href"].Value)); release.MagnetUri = ParseValueFromRow(r, nameof(release.MagnetUri), "a[href^=\"magnet:?\"]", (e) => new Uri(e.Attributes["href"].Value)); release.Size = ParseValueFromRow(r, nameof(release.Size), "td:nth-child(7)", (e) => ReleaseInfo.GetBytes(e.Text())); release.PublishDate = ParseValueFromRow(r, nameof(release.PublishDate), "td:nth-child(8)", (e) => DateTime.ParseExact(e.Attributes["title"].Value, "yyyy-MM-dd HH:mm:ss UTC", CultureInfo.InvariantCulture)); release.Seeders = ParseIntValueFromRow(r, nameof(release.Seeders), "td:nth-child(9)"); release.Peers = ParseIntValueFromRow(r, nameof(release.Peers), "td:nth-child(10)") + release.Seeders; release.Grabs = ParseIntValueFromRow(r, nameof(release.Grabs), "td:nth-child(11)"); release.Comments = ParseValueFromRow(r, nameof(release.Comments), "td:nth-child(3) a", (e) => GetAbsoluteUrl(e.Attributes["href"].Value)); release.Guid = release.Comments; release.MinimumRatio = 1; release.MinimumSeedTime = 172800; // 48 hours release.DownloadVolumeFactor = 0; release.UploadVolumeFactor = 1; releases.Add(release); } catch (Exception ex) { logger.Error($"Anidex: Error parsing search result row '{r.ToHtmlPretty()}':\n\n{ex}"); } } return(releases); } catch (Exception ex) { throw new IOException($"Error parsing search result page: {ex}"); } }
IEnumerator OpenMoreInfoPopup(ReleaseInfo info) { bool isDone = false; var skin = _pmSettings.ReleaseMoreInfoDialog; Vector2 scrollPos = Vector2.zero; var popupId = _view.AddPopup(delegate(Rect fullRect) { var popupRect = ImguiUtil.CenterRectInRect(fullRect, skin.PopupSize); _view.DrawPopupCommon(fullRect, popupRect); var contentRect = ImguiUtil.CreateContentRectWithPadding( popupRect, skin.PanelPadding); GUILayout.BeginArea(contentRect); { GUILayout.Label("Release Info", skin.HeadingStyle); GUILayout.Space(skin.HeadingBottomPadding); scrollPos = GUILayout.BeginScrollView(scrollPos, false, true, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, skin.ScrollViewStyle, GUILayout.Height(skin.ListHeight)); { GUILayout.Space(skin.ListPaddingTop); PmViewHandlerCommon.AddReleaseInfoMoreInfoRows(info, skin); } GUI.EndScrollView(); } GUILayout.EndArea(); var okButtonRect = new Rect( contentRect.xMin + 0.5f * contentRect.width - 0.5f * skin.OkButtonWidth, contentRect.yMax - skin.MarginBottom - skin.OkButtonHeight, skin.OkButtonWidth, skin.OkButtonHeight); if (GUI.Button(okButtonRect, "Ok") || Event.current.keyCode == KeyCode.Escape) { isDone = true; } }); while (!isDone) { yield return null; } _view.RemovePopup(popupId); }
public async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var searchString = query.GetQueryString(); var queryUrl = SearchUrl; var queryCollection = new NameValueCollection(); if (!string.IsNullOrWhiteSpace(query.ImdbID) && query.ImdbID.ToLower().StartsWith("tt")) { queryCollection.Add("search", query.ImdbID); } else { if (!string.IsNullOrWhiteSpace(searchString)) { queryCollection.Add("search", searchString); } } foreach (var cat in MapTorznabCapsToTrackers(query)) { queryCollection.Add("c" + cat, "1"); } if (queryCollection.Count > 0) { queryUrl += "?" + queryCollection.GetQueryString(); } var results = await RequestStringWithCookiesAndRetry(queryUrl); // Check for being logged out if (results.IsRedirect) { 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 { CQ dom = results.Content; var rows = dom["#torrentTable > tbody > tr.browse"]; foreach (var row in rows) { CQ qRow = row.Cq(); var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; release.Title = qRow.Find(".torrentName").Text(); if ((query.ImdbID == null || !TorznabCaps.SupportsImdbSearch) && !query.MatchQueryStringAND(release.Title)) { continue; } release.Guid = new Uri(SiteLink + qRow.Find(".torrentName").Attr("href")); release.Comments = release.Guid; release.Link = new Uri(SiteLink + qRow.Find(".dlLinksInfo > a").Attr("href")); var sizeStr = qRow.Find(".sizeInfo").Text(); release.Size = ReleaseInfo.GetBytes(sizeStr); var dateStr = qRow.Find(".ulInfo").Text().Split('|').Last().Trim(); var agoIdx = dateStr.IndexOf("ago"); if (agoIdx > -1) { dateStr = dateStr.Substring(0, agoIdx); } release.PublishDate = DateTimeUtil.FromTimeAgo(dateStr); release.Seeders = ParseUtil.CoerceInt(qRow.Find(".seedersInfo").Text()); release.Peers = ParseUtil.CoerceInt(qRow.Find(".leechersInfo").Text()) + release.Seeders; var cat = qRow.Find("td:eq(0) a").First().Attr("href").Split('#')[0].Substring(15);//browse.php?cat=24 release.Category = MapTrackerCatToNewznab(cat); if (qRow.Find("span.flTags").Length >= 1) { release.DownloadVolumeFactor = 0; } else { release.DownloadVolumeFactor = 1; } release.UploadVolumeFactor = 1; releases.Add(release); } } catch (Exception ex) { OnParseError(results.Content, ex); } return(releases); }
public async Task<ReleaseInfo[]> PerformQuery(TorznabQuery query) { List<ReleaseInfo> releases = new List<ReleaseInfo>(); foreach (var title in query.ShowTitles ?? new string[] { string.Empty }) { var searchString = title + " " + query.GetEpisodeSearchString(); var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString)); var results = await client.GetStringAsync(episodeSearchUrl); try { CQ dom = results; var rows = dom["#torrentTable > tbody > tr.browse"]; foreach (var row in rows) { CQ qRow = row.Cq(); var release = new ReleaseInfo(); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; release.Title = qRow.Find(".torrentName").Text(); release.Description = release.Title; release.Guid = new Uri(BaseUrl + "/" + qRow.Find(".torrentName").Attr("href")); release.Comments = release.Guid; release.Link = new Uri(BaseUrl + "/" + qRow.Find(".dlLinksInfo > a").Attr("href")); var sizeStr = qRow.Find(".sizeInfo").Text().Trim(); var sizeParts = sizeStr.Split(' '); release.Size = ReleaseInfo.GetBytes(sizeParts[1], ParseUtil.CoerceFloat(sizeParts[0])); var dateStr = qRow.Find(".ulInfo").Text().Split('|').Last().Trim(); var dateParts = dateStr.Split(' '); var dateValue = ParseUtil.CoerceInt(dateParts[0]); TimeSpan ts = TimeSpan.Zero; if (dateStr.Contains("sec")) ts = TimeSpan.FromSeconds(dateValue); else if (dateStr.Contains("min")) ts = TimeSpan.FromMinutes(dateValue); else if (dateStr.Contains("hour")) ts = TimeSpan.FromHours(dateValue); else if (dateStr.Contains("day")) ts = TimeSpan.FromDays(dateValue); else if (dateStr.Contains("week")) ts = TimeSpan.FromDays(dateValue * 7); else if (dateStr.Contains("month")) ts = TimeSpan.FromDays(dateValue * 30); else if (dateStr.Contains("year")) ts = TimeSpan.FromDays(dateValue * 365); release.PublishDate = DateTime.Now - ts; release.Seeders = ParseUtil.CoerceInt(qRow.Find(".seedersInfo").Text()); release.Peers = ParseUtil.CoerceInt(qRow.Find(".leechersInfo").Text()) + release.Seeders; releases.Add(release); } } catch (Exception ex) { OnResultParsingError(this, results, ex); throw ex; } } return releases.ToArray(); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); var searchString = "--"; var maxPages = 2; // we scrape only 2 pages for recent torrents if (!string.IsNullOrWhiteSpace(query.GetQueryString())) { searchString = Uri.EscapeUriString(query.GetQueryString()); maxPages = MaxSearchPageLimit; } var lastPublishDate = DateTime.Now; for (var page = 0; page < maxPages; page++) { var searchUrl = string.Format(SearchUrl, page * MaxItemsPerPage, searchString); var result = await RequestWithCookiesAsync(searchUrl, headers : _apiHeaders); try { var json = JsonConvert.DeserializeObject <dynamic>(result.ContentString); var parser = new HtmlParser(); var doc = parser.ParseDocument((string)json["contenido"]); var rows = doc.QuerySelectorAll("div.span2"); foreach (var row in rows) { var title = row.QuerySelector("h2").TextContent + " - " + row.QuerySelector("h1").TextContent; if (!CheckTitleMatchWords(query.GetQueryString(), title)) { continue; // skip if it doesn't contain all words } var poster = new Uri(row.QuerySelector("img[id=catalog]").GetAttribute("src")); var qLink = row.QuerySelector("a"); var details = new Uri(qLink.GetAttribute("href")); var qTooltip = parser.ParseDocument(qLink.GetAttribute("data-content")); // we get the language from the last class tag => class="pull-right sprite idioma_5" var languageId = qTooltip.QuerySelector("div.pull-right").GetAttribute("class").Split('_')[1]; title += $" [{_languages[languageId]}] [epub]"; var qDesc = qTooltip.QuerySelectorAll("div.row-fluid > div"); var description = $"Rev: {qDesc[0].TextContent} Páginas: {qDesc[1].TextContent} Puntación: {qDesc[2].TextContent} Likes: {qDesc[3].TextContent}"; // publish date is not available in the torrent list, but we add a relative date so we can sort lastPublishDate = lastPublishDate.AddMinutes(-1); var release = new ReleaseInfo { Title = title, Details = details, Link = details, Guid = details, PublishDate = lastPublishDate, Poster = poster, Description = description, Category = new List <int> { TorznabCatType.BooksEBook.ID }, Size = 5242880, // 5 MB Seeders = 1, Peers = 2, DownloadVolumeFactor = 0, UploadVolumeFactor = 1 }; releases.Add(release); } if (rows.Length < MaxItemsPerPage) { break; // this is the last page } } catch (Exception ex) { OnParseError(result.ContentString, ex); } } return(releases); }
void OnGUI() { if (validUpdateData) { } else { if (GUILayout.Button("Refresh", GUILayout.MaxWidth(100))) { try { errorMessage = ""; errorState = false; XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(updateInfoUrl); validUpdateData = false; System.Xml.XmlNodeList releaseNodes = xmlDocument.SelectNodes("/updateinfo/release"); releases = new ReleaseInfo[releaseNodes.Count]; int currentReleaseNode = 0; foreach (XmlNode node in releaseNodes) { ReleaseInfo releaseInfo = new ReleaseInfo(); releaseInfo.id = int.Parse(node.Attributes["id"].Value, System.Globalization.NumberFormatInfo.InvariantInfo); releaseInfo.sortId = GetSortId(releaseInfo.id); releaseInfo.version = double.Parse(node.Attributes["version"].Value, System.Globalization.NumberFormatInfo.InvariantInfo); releaseInfo.url = node.Attributes["url"].Value; releaseInfo.changelog = node.Attributes["changelog"].Value; releases[currentReleaseNode] = releaseInfo; ++currentReleaseNode; } // sort releases, newest first System.Array.Sort(releases, (ReleaseInfo a, ReleaseInfo b) => { if (a.version == b.version) { return a.sortId.CompareTo(b.sortId); } else { return b.version.CompareTo(a.version); } }); } catch { errorMessage = "Unable to check for updates.\nPlease contact support if this condition persists."; errorState = true; releases = null; } } if (errorMessage != "") { GUILayout.Label(errorMessage); if (errorState) { GUILayout.Label("You can also download releases from the website."); if (GUILayout.Button("All Releases", GUILayout.MaxWidth(100))) { Application.OpenURL(allUpdatesUrl); } } } else { EditorGUILayout.Separator(); showBetaReleases = EditorGUILayout.Toggle("Beta releases", showBetaReleases); showOlderVersions = EditorGUILayout.Toggle("Older versions", showOlderVersions); EditorGUILayout.Separator(); int installedSortId = GetSortId(tk2dEditorUtility.releaseId); if (releases != null && releases.Length > 0) { scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); EditorGUILayout.BeginVertical(); foreach (ReleaseInfo release in releases) { if (showOlderVersions == false && (release.version < tk2dEditorUtility.version || (release.version == tk2dEditorUtility.version && release.sortId < installedSortId)) ) { // stop displaying releases break; } if (!showBetaReleases && release.id < 0) { // dont display beta releases continue; } string label = ""; label += tk2dEditorUtility.ReleaseStringIdentifier(release.version, release.id); if (release.version == tk2dEditorUtility.version && release.id == tk2dEditorUtility.releaseId) { label += " [INSTALLED]"; } GUILayout.BeginHorizontal(); GUILayout.Label(label, GUILayout.ExpandWidth(true)); if (GUILayout.Button("Download", GUILayout.MaxWidth(100))) { Application.OpenURL(release.url); } if (GUILayout.Button("Changelog", GUILayout.MaxWidth(100))) { Application.OpenURL(release.changelog); } GUILayout.EndHorizontal(); } if (GUILayout.Button("More...", GUILayout.MaxWidth(100))) { Application.OpenURL(allUpdatesUrl); } EditorGUILayout.EndVertical(); EditorGUILayout.EndScrollView(); } } } }
public DownloadClientRejectedReleaseException(ReleaseInfo release, string message, Exception innerException) : base(release, message, innerException) { }