/* Search is possible only based by Series ID. * All known series ID is on main page, with their attributes. (ID, EngName, HunName, imdbid) */ /// <summary> /// Get all series info known by site /// These are: /// - Series ID /// - Hungarian name /// - English name /// - IMDB ID /// </summary> /// <returns>The series info.</returns> protected async Task <Boolean> GetSeriesInfo() { var result = (await RequestStringWithCookiesAndRetry(BrowseUrl)).Content; CQ dom = result; var scripts = dom["script"]; foreach (var script in scripts) { if (script.TextContent.Contains("catsh=Array")) { string[] seriesknowbysite = Regex.Split(script.TextContent, "catl"); for (int i = 1; i < seriesknowbysite.Length; i++) { try { var id = seriesknowbysite[i]; string[] serieselement = id.Split(';'); SeriesDetail sd = new SeriesDetail(); sd.HunName = serieselement[1].Split('=')[1].Trim('\'').ToLower(); sd.EngName = serieselement[2].Split('=')[1].Trim('\'').ToLower(); sd.id = serieselement[0].Split('=')[1].Trim('\''); sd.imdbid = serieselement[7].Split('=')[1].Trim('\''); series.Add(sd); } catch (IndexOutOfRangeException e) { } } } } return(true); }
/// <summary> /// Parses the torrents from the content /// </summary> /// <returns>The parsed torrents.</returns> /// <param name="results">The result of the query</param> /// <param name="query">Query.</param> /// <param name="already_found">Number of the already found torrents.(used for limit)</param> /// <param name="limit">The limit to the number of torrents to download </param> async Task <List <ReleaseInfo> > ParseTorrents(WebClientStringResult results, TorznabQuery query, int already_found, int limit) { var releases = new List <ReleaseInfo>(); try { String content = results.Content; /* Content Looks like this * 2\15\2\1\1727\207244\1x08 \[WebDL-720p - Eng - AJP69]\gb\2018-03-09 08:11:53\akció, kaland, sci-fi \0\0\1\191170047\1\0\Anonymous\50\0\0\\0\4\0\174\0\ * 1\ 0\0\1\1727\207243\1x08 \[WebDL-1080p - Eng - AJP69]\gb\2018-03-09 08:11:49\akció, kaland, sci-fi \0\0\1\305729738\1\0\Anonymous\50\0\0\\0\8\0\102\0\0\0\0\1\\\ */ var splits = content.Split('\\'); int i = 0; ReleaseInfo release = new ReleaseInfo(); /* Split the releases by '\' and go through them. * 26 element belongs to one torrent */ foreach (var s in splits) { switch (i) { case 4: //ID of the series //Get IMDB id form site series database SeriesDetail seriesinfo = series.Find(x => x.id.Contains(s)); if (seriesinfo != null && !s.Equals("")) { release.Imdb = long.Parse(seriesinfo.imdbid); } goto default; case 5: //ID of the torrent Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; string fileinfoURL = SearchUrl + "?func=getToggle&id=" + s + "&w=F&pg=0&now=" + unixTimestamp; string fileinfo = (await RequestStringWithCookiesAndRetry(fileinfoURL)).Content; release.Link = new Uri(DownloadUrl + "?id=" + s); release.Guid = release.Link; release.Comments = release.Link; string[] fileinf = fileinfo.Split(new string[] { "\\\\" }, StringSplitOptions.None); if (fileinf.Length > 1) { release.Title = fileinf[1]; } goto default; /*case 6: * Console.WriteLine("Series season/ep =" + s); --> 9x10 * goto default;*/ /*case 7: * Console.WriteLine("Releaseinfo =" + s); --->Releaseinfo =[HDTV - Rip - Eng - SVA] * goto default;*/ case 9: release.PublishDate = DateTime.Parse(s, CultureInfo.InvariantCulture); goto default; case 13: release.Files = int.Parse(s); goto default; case 14: release.Size = long.Parse(s); goto default; case 23: release.Seeders = int.Parse(s); goto default; case 24: release.Peers = (int.Parse(s) + release.Seeders); goto default; case 25: release.Grabs = int.Parse(s); goto default; case 26: /* This is the last element for the torrent. So add it to releases and start parsing to new torrent */ i = 0; release.Category = new List <int> { TvCategoryParser.ParseTvShowQuality(release.Title) }; //todo Added some basic configuration need to improve it release.MinimumRatio = 1; release.MinimumSeedTime = 172800; release.DownloadVolumeFactor = 1; release.UploadVolumeFactor = 1; if ((already_found + releases.Count) < limit) { releases.Add(release); } else { return(releases); } release = new ReleaseInfo(); break; default: i++; break; } } } catch (Exception ex) { OnParseError(results.Content, ex); } return(releases); }
protected override async Task <IEnumerable <ReleaseInfo> > PerformQuery(TorznabQuery query) { var releases = new List <ReleaseInfo>(); /* If series from sites are indexed than we dont need to reindex them. */ if (series == null || series.IsEmpty()) { await GetSeriesInfo(); } var unixTimestamp = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; WebClientStringResult results; var searchString = ""; var exactSearchURL = ""; var page = 1; SeriesDetail seriesinfo = null; var base64coded = ""; var noimdbmatch = false; var limit = query.Limit; if (limit == 0) { limit = 100; } if (query.IsImdbQuery) { seriesinfo = series.Find(x => x.imdbid.Equals(query.ImdbIDShort)); if (seriesinfo != null && !query.ImdbIDShort.Equals("")) { var querrySeason = ""; if (query.Season != 0) { querrySeason = query.Season.ToString(); } exactSearchURL = SearchUrl + "?s=" + querrySeason + "&e=" + query.Episode + "&g=" + seriesinfo.id + "&now=" + unixTimestamp.ToString(); } else { // IMDB_ID was not founded in site database. return(releases); } } if (!query.IsImdbQuery || noimdbmatch) { /* SearchString format is the following: Seriesname 1X09 */ if (query.SearchTerm != null && !query.SearchTerm.Equals("")) { searchString += query.SanitizedSearchTerm; // convert SnnEnn to nnxnn for dashboard searches if (query.Season == 0 && (query.Episode == null || query.Episode.Equals(""))) { var searchMatch = _searchStringRegex.Match(searchString); if (searchMatch.Success) { query.Season = int.Parse(searchMatch.Groups[2].Value); query.Episode = searchMatch.Groups[4].Success ? string.Format("{0:00}", (int?)int.Parse(searchMatch.Groups[4].Value)) : null; searchString = searchMatch.Groups[1].Value; // strip SnnEnn } } if (query.Season != 0) { searchString += " " + query.Season.ToString(); } if (query.Episode != null && !query.Episode.Equals("")) { searchString += string.Format("x{0:00}", int.Parse(query.Episode)); } } else { // if searchquery is empty this is a test, so shorten the response time limit = 20; } /* Search string must be converted to Base64 */ var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(searchString); base64coded = System.Convert.ToBase64String(plainTextBytes); exactSearchURL = SearchUrl + "?gyors=" + base64coded + "&p=" + page + "&now=" + unixTimestamp.ToString(); } /*Start search*/ results = await RequestStringWithCookiesAndRetry(exactSearchURL); /* Parse page Information from result */ var content = results.Content; var splits = content.Split('\\'); var max_found = int.Parse(splits[0]); var torrent_per_page = int.Parse(splits[1]); if (torrent_per_page == 0) { return(releases); } var start_page = (query.Offset / torrent_per_page) + 1; var previously_parsed_on_page = query.Offset - (start_page * torrent_per_page) + 1; //+1 because indexing start from 0 if (previously_parsed_on_page <= 0) { previously_parsed_on_page = query.Offset; } var pages = Math.Ceiling(max_found / (double)torrent_per_page); /* First page content is already ready */ if (start_page == 1) { releases.AddRange(await ParseTorrents(results, query, releases.Count, limit, previously_parsed_on_page)); previously_parsed_on_page = 0; start_page++; } for (page = start_page; (page <= pages && releases.Count < limit); page++) { if (query.IsImdbQuery && seriesinfo != null) { exactSearchURL = SearchUrl + "?s=" + query.Season + "&e=" + query.Episode + "&g=" + seriesinfo.id + "&p=" + page + "&now=" + unixTimestamp.ToString(); } else { exactSearchURL = SearchUrl + "?gyors=" + base64coded + "&p=" + page + "&now=" + unixTimestamp.ToString(); } results = await RequestStringWithCookiesAndRetry(exactSearchURL); releases.AddRange(await ParseTorrents(results, query, releases.Count, limit, previously_parsed_on_page)); previously_parsed_on_page = 0; } return(releases); }
/// <summary> /// Parses the torrents from the content /// </summary> /// <returns>The parsed torrents.</returns> /// <param name="results">The result of the query</param> /// <param name="query">Query.</param> /// <param name="already_found">Number of the already found torrents.(used for limit)</param> /// <param name="limit">The limit to the number of torrents to download </param> async Task <List <ReleaseInfo> > ParseTorrents(WebClientStringResult results, TorznabQuery query, int already_found, int limit, int previously_parsed_on_page) { var releases = new List <ReleaseInfo>(); try { String content = results.Content; /* Content Looks like this * 2\15\2\1\1727\207244\1x08 \[WebDL-720p - Eng - AJP69]\gb\2018-03-09 08:11:53\akció, kaland, sci-fi \0\0\1\191170047\1\0\Anonymous\50\0\0\\0\4\0\174\0\ * 1\ 0\0\1\1727\207243\1x08 \[WebDL-1080p - Eng - AJP69]\gb\2018-03-09 08:11:49\akció, kaland, sci-fi \0\0\1\305729738\1\0\Anonymous\50\0\0\\0\8\0\102\0\0\0\0\1\\\ */ string[] parameters = content.Split(new string[] { "\\" }, StringSplitOptions.None); string type = "normal"; /* * Split the releases by '\' and go through them. * 27 element belongs to one torrent */ for (int j = previously_parsed_on_page * 27; (j + 27 < parameters.Length && ((already_found + releases.Count) < limit)); j = j + 27) { ReleaseInfo release = new ReleaseInfo(); int imdb_id = 4 + j; int torrent_id = 5 + j; int is_season_id = 6 + j; int publish_date_id = 9 + j; int files_id = 13 + j; int size_id = 14 + j; int seeders_id = 23; int peers_id = 24 + j; int grabs_id = 25 + j; type = "normal"; //IMDB id of the series SeriesDetail seriesinfo = series.Find(x => x.id.Contains(parameters[imdb_id])); if (seriesinfo != null && !parameters[imdb_id].Equals("")) { release.Imdb = long.Parse(seriesinfo.imdbid); } //ID of the torrent Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; string fileinfoURL = SearchUrl + "?func=getToggle&id=" + parameters[torrent_id] + "&w=F&pg=0&now=" + unixTimestamp; string fileinfo = (await RequestStringWithCookiesAndRetry(fileinfoURL)).Content; release.Link = new Uri(DownloadUrl + "?id=" + parameters[torrent_id]); release.Guid = release.Link; release.Comments = release.Link; string[] fileinf = fileinfo.Split(new string[] { "\\\\" }, StringSplitOptions.None); if (fileinf.Length > 1) { release.Title = fileinf[1]; if (fileinf[1].Length > 5 && fileinf[1].Substring(fileinf[1].Length - 4).Contains(".")) { release.Title = fileinf[1].Substring(0, fileinf[1].Length - 4); } } // SeasonPack check if (parameters[is_season_id].Contains("évad/")) { type = "season"; // If this is a seasonpack, remove episode nunmber from title. release.Title = Regex.Replace(release.Title, "s0?(\\d+)(e0?(\\d+))", "S$1", RegexOptions.IgnoreCase); } release.PublishDate = DateTime.Parse(parameters[publish_date_id], CultureInfo.InvariantCulture); release.Files = int.Parse(parameters[files_id]); release.Size = long.Parse(parameters[size_id]); release.Seeders = int.Parse(parameters[seeders_id]); release.Peers = (int.Parse(parameters[peers_id]) + release.Seeders); release.Grabs = int.Parse(parameters[grabs_id]); release.MinimumRatio = 1; release.MinimumSeedTime = 172800; // 48 hours release.DownloadVolumeFactor = 1; release.UploadVolumeFactor = UploadFactorCalculator(release.PublishDate, type); release.Category = new List <int> { TvCategoryParser.ParseTvShowQuality(release.Title) }; if ((already_found + releases.Count) < limit) { releases.Add(release); } else { return(releases); } } } catch (Exception ex) { OnParseError(results.Content, ex); } return(releases); }