public UploadData GetUniqueUploadData(UploadData u) { if (u == null) return null; int k = u.GetHashCode(); UploadData v; if (_uploadCache.TryGetValue(k, out v) && v.Equals(u)) { return v; } _uploadCache.TryAdd(k, u); return u; }
private String BuildUploadTitle(UploadData upload) { return upload.Format + ", " + upload.Uploader + "\n" + upload.Size + ", " + upload.Runtime + ", " + upload.Language; }
public void ApplyFilter(bool reset, bool notifications = true) { if (AllDownloads == null || !AllDownloads.Any()) { Fetch(); return; } _mutexFilter.WaitOne(); FavSeasonData currentFavSeason = null; SeasonData currentSeasonData = null; int seasonNr = -1; ObservableCollection <FavSeasonData> newSeasons = new ObservableCollection <FavSeasonData>(); ObservableCollection <DownloadData> newNonSeasons = new ObservableCollection <DownloadData>(); bool setNewEpisodes = false; bool setNewUpdates = false; if (_isNewShow) { notifications = false; } reset = reset || _isNewShow; if (!reset) { newSeasons = Seasons; newNonSeasons = NonSeasons; } UploadData currentUpload = null; bool ignoreCurrentUpload = false; foreach (var download in AllDownloads) { //upload stuff -------------------------------------------------------------------- if (currentUpload == null || currentUpload != download.Upload) { currentUpload = download.Upload; ignoreCurrentUpload = true; do { UploadLanguage language = currentUpload.Language; if (!Settings.Instance.MarkSubbedAsGerman && currentUpload.Subbed) //dont mark german-subbed as german { language &= ~UploadLanguage.German; //remove german } if ((language & FilterLanguage) == 0) //Filter: Language { break; } if (!String.IsNullOrWhiteSpace(FilterRuntime) && //Filter: Runtime !(new Regex(FilterRuntime).Match(currentUpload.Runtime).Success)) { break; } if (!String.IsNullOrWhiteSpace(FilterSize) && //Filter: Size !(new Regex(FilterSize).Match(currentUpload.Size).Success)) { break; } if (!String.IsNullOrWhiteSpace(FilterUploader) && //Filter: Uploader !(new Regex(FilterUploader).Match(currentUpload.Uploader).Success)) { break; } if (!String.IsNullOrWhiteSpace(FilterFormat) && //Filter: Format !(new Regex(FilterFormat).Match(currentUpload.Format).Success)) { break; } ignoreCurrentUpload = false; } while (false); } if (ignoreCurrentUpload) //Filter: All upload stuff { continue; } //episode stuff --------------------- if (!String.IsNullOrWhiteSpace(FilterName) && //Filter: Name !(new Regex(FilterName).Match(download.Title).Success)) { continue; } if (!String.IsNullOrWhiteSpace(FilterHoster)) { var r = new Regex(FilterHoster); var dls = download.Links.Keys.Where(hoster => r.Match(hoster).Success).ToList(); //all keys that match the regex if (!dls.Any()) //Filter: Hoster { continue; } for (int i = download.Links.Keys.Count - 1; i >= 0; i--) { string key = download.Links.Keys.ElementAt(i); if (!dls.Contains(key)) { download.Links.Remove(key); } } } //------------------------------------------ //Season stuff ------------------------------------------------------------------------------------ if (currentSeasonData == null || currentSeasonData != download.Upload.Season) { currentSeasonData = download.Upload.Season; seasonNr = -1; Match m2 = new Regex("(?:season|staffel)\\s*(\\d+)", RegexOptions.IgnoreCase).Match(currentSeasonData.Title); if (m2.Success) { int.TryParse(m2.Groups[1].Value, out seasonNr); } } if (seasonNr == -1) { if (newNonSeasons.All(d => d.Title != download.Title)) { newNonSeasons.Add(download); } continue; } if (currentFavSeason == null || currentFavSeason.Number != seasonNr) { currentFavSeason = newSeasons.FirstOrDefault(favSeasonData => favSeasonData.Number == seasonNr) ?? new FavSeasonData() { Number = seasonNr, Show = this }; if (!newSeasons.Contains(currentFavSeason)) //season not yet added? { newSeasons.Add(currentFavSeason); } } int episodeNr = -1; MatchCollection mts = new Regex("S0{0,4}" + seasonNr + "\\.?E(\\d+)", RegexOptions.IgnoreCase).Matches(download.Title); MatchCollection mts_ep = new Regex("[^A-Z]E(\\d+)", RegexOptions.IgnoreCase).Matches(download.Title); MatchCollection mts_alt = new Regex("\\bE(\\d+)\\b", RegexOptions.IgnoreCase).Matches(download.Title); if (mts.Count == 1 && mts_ep.Count == 1) //if there is exactly one match for "S<xx>E<yy>" and there is no second "E<zz>" (e.g. S01E01-E12) { int.TryParse(mts[0].Groups[1].Value, out episodeNr); } else if (mts_alt.Count == 1) //if there's exactly one match for the alternative regex { int.TryParse(mts_alt[0].Groups[1].Value, out episodeNr); } if (episodeNr == -1) { if (currentFavSeason.NonEpisodes.All(d => d.Title != download.Title)) { currentFavSeason.NonEpisodes.Add(download); } continue; } FavEpisodeData currentFavEpisode = currentFavSeason.Episodes.FirstOrDefault(episodeData => episodeData.Number == episodeNr); if (currentFavEpisode == null) { currentFavEpisode = new FavEpisodeData(); currentFavEpisode.Season = currentFavSeason; currentFavEpisode.Number = episodeNr; bool existed = false; var oldSeason = Seasons.FirstOrDefault(s => s.Number == currentFavSeason.Number); if (oldSeason != null) { var oldEpisode = oldSeason.Episodes.FirstOrDefault(e => e.Number == currentFavEpisode.Number); if (oldEpisode != null) //we can copy old data to current episode { currentFavEpisode.Watched = oldEpisode.Watched; currentFavEpisode.Downloaded = oldEpisode.Downloaded; currentFavEpisode.EpisodeInformation = oldEpisode.EpisodeInformation; existed = true; } } if (notifications && !existed) { currentFavEpisode.NewEpisode = true; setNewEpisodes = true; } currentFavSeason.Episodes.Add(currentFavEpisode); currentFavEpisode.Downloads.Add(download); if (ProviderData != null && (currentFavEpisode.EpisodeInformation == null || reset)) { StaticInstance.ThreadPool.QueueWorkItem(() => { //currentFavEpisode.ReviewInfoReview = SjInfo.ParseSjDeSite(InfoUrl, currentFavEpisode.Season.Number, currentFavEpisode.Number); currentFavEpisode.EpisodeInformation = ProviderManager.GetProvider().GetEpisodeInformation(ProviderData, currentFavEpisode.Season.Number, currentFavEpisode.Number); }); } } else { FavEpisodeData oldEpisode = null; var oldSeason = Seasons.FirstOrDefault(s => s.Number == currentFavSeason.Number); if (oldSeason != null) { oldEpisode = oldSeason.Episodes.FirstOrDefault(e => e.Number == currentFavEpisode.Number); } if (currentFavEpisode.Downloads.All(d => d.Title != download.Title)) { if (notifications && (oldEpisode == null || (!oldEpisode.NewEpisode && oldEpisode.Downloads.All(d => d.Title != download.Title)))) { currentFavEpisode.NewUpdate = true; setNewUpdates = true; } currentFavEpisode.Downloads.Add(download); } } } if (reset) { Seasons.Clear(); foreach (var season in newSeasons) { Seasons.Add(season); } NonSeasons.Clear(); foreach (var nonSeason in newNonSeasons) { NonSeasons.Add(nonSeason); } } if (setNewEpisodes) { Notified = false; NewEpisodes = true; } if (setNewUpdates) { NewUpdates = true; } RecalcNumbers(); _mutexFilter.ReleaseMutex(); }
private static List<DownloadData> ParseSite(ShowData showData, string url, out string nextpageurl, out string firstcover, UploadCache uploadCache) { nextpageurl = ""; firstcover = ""; WebResponse resp = null; for (int i = 0; i <= 7; i++) { try { HttpWebRequest req = WebRequest.CreateHttp(url); req.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; req.KeepAlive = false; resp = req.GetResponse(); break; } catch (WebException ex) { if (ex.Status != WebExceptionStatus.Timeout) throw; } } if (resp == null) { throw new TimeoutException(); } HtmlDocument doc = new HtmlDocument(); doc.OptionDefaultStreamEncoding=Encoding.UTF8; doc.Load(resp.GetResponseStream()); resp.Dispose(); List<DownloadData> list = new List<DownloadData>(); HtmlNode content = doc.GetElementbyId("content"); HtmlNode nextLink = content.SelectSingleNode("//div[@class='navigation']//a[@href][@class='next']"); if (nextLink != null) { nextpageurl = nextLink.GetAttributeValue("href", null); } var posts = content.SelectNodes("div[@class='post']"); if (posts == null) return list; foreach (var post in posts) { //--------------Season Title----------------------------------- var title = post.SelectSingleNode("h2/a[@href]"); if (title == null) { Console.WriteLine("SjInfo Parser: No Title"); continue; } var seasonData = new SeasonData(); seasonData.Show = showData; seasonData.Url = title.GetAttributeValue("href", null); seasonData.Title = WebUtility.HtmlDecode(title.InnerText); var postContent = post.SelectSingleNode("div[@class='post-content']"); if(postContent == null) { Console.WriteLine("SjInfo Parser: No Post content"); continue; } //----------------Season Cover------------------------------------------------ var cover = postContent.SelectSingleNode(".//p/img[@src]"); if (cover != null) { seasonData.CoverUrl = cover.GetAttributeValue("src", null); if (String.IsNullOrEmpty(firstcover)) { firstcover = seasonData.CoverUrl; } } //----------------Season description----------------------------------------- var desc = postContent.SelectSingleNode(".//p[count(node())=1][not(@class='post-info-co')]/text()"); if (desc != null) { seasonData.Description = WebUtility.HtmlDecode(desc.InnerText); } UploadData uploadData = null; var ps = postContent.SelectNodes(".//node()[self::p|self::div][count(strong)>=2]"); if (ps == null) { Console.WriteLine("SjInfo Parser: no uploads/headers"); continue; } foreach (var p in ps) { //--------------- Upload Header ------------------------------ if (p.SelectSingleNode("self::node()[not(./a[@target])]") != null) { uploadData = new UploadData(); uploadData.Season = seasonData; String c = WebUtility.HtmlDecode(p.InnerHtml); MatchCollection mc = new Regex("<strong>\\s*(.+?)\\s*</strong>\\s*(.+?)\\s*(?:\\||$)").Matches(c); foreach (Match match in mc) { String key = match.Groups[1].Value.ToLower(); String value = match.Groups[2].Value; if (key.Contains("dauer") || key.Contains("runtime") || key.Contains("duration")) { uploadData.Runtime = value; } else if (key.Contains("grösse") || key.Contains("größe") || key.Contains("size")) { uploadData.Size = value; } else if (key.Contains("uploader")) { uploadData.Uploader = value; } else if (key.Contains("format")) { uploadData.Format = value; } else if (key.Contains("sprache") || key.Contains("language")) { value = value.ToLower(); if (value.Contains("deutsch") || value.Contains("german")) { uploadData.Language |= UploadLanguage.German; } if (value.Contains("englisch") || value.Contains("english")) { uploadData.Language |= UploadLanguage.English; } if (value.Contains("subbed")) { uploadData.Subbed = true; } } } } else if (uploadData != null) { // ------------------ Links ------------------------- var ulTitle = p.SelectSingleNode("strong[position()=1][count(node())=1]/text()"); if (ulTitle == null) { Console.WriteLine("SjInfo Parser: No title for link? " + p.InnerHtml); continue; } string titleStr = WebUtility.HtmlDecode(ulTitle.InnerText).Trim(); var links = p.SelectNodes("a[@href][following-sibling::text()]"); if (links == null) continue; var downloads = new Dictionary<string, string>(); foreach (var link in links) { string ur = link.GetAttributeValue("href", null); string keyOrg = WebUtility.HtmlDecode(link.NextSibling.InnerText.Trim()); if(keyOrg.StartsWith("|")) keyOrg = keyOrg.Substring(1).Trim(); String key = keyOrg; int i = 1; while (downloads.ContainsKey(key)) { key = keyOrg + "(" + i++ + ")"; } downloads.Add(key, ur); } if (titleStr.Contains("720p")) { uploadData.Format = "720p"; } else if (titleStr.Contains("1080p")) { uploadData.Format = "1080p"; } else if (titleStr.Contains("720i")) { uploadData.Format = "720i"; } else if (titleStr.Contains("1080i")) { uploadData.Format = "1080i"; } DownloadData dd = new DownloadData(); dd.Upload = uploadCache == null ? uploadData : uploadCache.GetUniqueUploadData(uploadData); dd.Title = titleStr; if (titleStr.ToLower().Contains("subbed")) { dd.Upload.Subbed = true; } foreach (var download in downloads) { dd.Links.Add(download.Key, download.Value); } list.Add(dd); } else { Console.WriteLine("SjInfo Parser: UploadData was null"); } } } return list; }