/* * is there a way to move this to the superclass ... * */ public static void LoadAll() { string[] providers = getFiles(location); string status = "Providers found:"; foreach (string file in providers) { Logger.Instance.LogMessage("Provider: " + file, LogLevel.DEBUG); try { RelationProvider rel = new RelationProvider(file); if (String.IsNullOrEmpty(rel.Name)) { Logger.Instance.LogMessage("Invalid provider file: " + file, LogLevel.ERROR); rel.delete(); continue; } status += " " + rel.Name + ","; } catch (Exception ex) { Logger.Instance.LogMessage("Invalid provider file: " + file + " Error: " + ex.Message, LogLevel.ERROR); } } status = status.TrimEnd(new char[] { ',' }); Logger.Instance.LogMessage(status, LogLevel.INFO); }
public static string CleanSearchResultName(string SearchResult, RelationProvider provider) { foreach (string pattern in provider.SearchRemove) { SearchResult = Regex.Replace(SearchResult, pattern, ""); } return SearchResult.Trim(); }
public static ParsedSearch Search(RelationProvider provider, string SearchString, string Showname) { ParsedSearch ps = new ParsedSearch(); ps.provider = provider; ps.SearchString = SearchString; ps.Showname = Showname; //once for (int a = 0; a < 1; a++) { // request if (provider == null) { Logger.Instance.LogMessage("No relation provider found/selected", LogLevel.ERROR); return ps; } /* //get rid of old relations RelationManager.Instance.RemoveRelationCollection(Showname); foreach (InfoEntry ie in InfoEntryManager.Instance) { if (ie.Showname == Showname && ie.ProcessingRequested) { ie.Name = ""; ie.NewFileName = ""; ie.Language = provider.Language; } }*/ string url = provider.SearchUrl; Logger.Instance.LogMessage("Search URL: " + url, LogLevel.DEBUG); if (url == null || url == "") { Logger.Instance.LogMessage("Can't search because no search URL is specified for this provider", LogLevel.ERROR); break; } url = url.Replace("%T", SearchString); url = System.Web.HttpUtility.UrlPathEncode(url); Logger.Instance.LogMessage("Encoded Search URL: " + url, LogLevel.DEBUG); HttpWebRequest requestHtml = null; try { requestHtml = (HttpWebRequest)(HttpWebRequest.Create(url)); } catch (Exception ex) { Logger.Instance.LogMessage(ex.Message, LogLevel.ERROR); if (requestHtml != null) requestHtml.Abort(); break; } //SetProxy(requestHtml, url); Logger.Instance.LogMessage("Searching at " + url.Replace(" ", "%20"), LogLevel.INFO); requestHtml.Timeout = Convert.ToInt32(Helper.ReadProperty(Config.Timeout)); // get response HttpWebResponse responseHtml = null; try { responseHtml = (HttpWebResponse)(requestHtml.GetResponse()); } catch (Exception ex) { Logger.Instance.LogMessage(ex.Message, LogLevel.ERROR); if (responseHtml != null) responseHtml.Close(); if (requestHtml != null) requestHtml.Abort(); break; } Logger.Instance.LogMessage("Search Results URL: " + responseHtml.ResponseUri.AbsoluteUri, LogLevel.DEBUG); //if search engine directs us straight to the result page, skip parsing search results string seriesURL = provider.SeriesUrl; if (responseHtml.ResponseUri.AbsoluteUri.Contains(seriesURL)) { Logger.Instance.LogMessage("Search Results URL contains Series URL: " + seriesURL, LogLevel.DEBUG); ps.Results = new Hashtable(); string CleanedName=CleanSearchResultName(Showname,provider); if(provider.SearchResultsBlacklist=="" || !Regex.Match(CleanedName,provider.SearchResultsBlacklist).Success){ ps.Results.Add(CleanedName, responseHtml.ResponseUri.AbsoluteUri + provider.EpisodesUrl); Logger.Instance.LogMessage("Search engine forwarded directly to single result: " + responseHtml.ResponseUri.AbsoluteUri.Replace(" ", "%20") + provider.EpisodesUrl.Replace(" ", "%20"), LogLevel.INFO); } return ps; } else { Logger.Instance.LogMessage("Search Results URL doesn't contain Series URL: " + seriesURL + ", this is a proper search results page", LogLevel.DEBUG); // and download StreamReader r = null; try { r = new StreamReader(responseHtml.GetResponseStream()); } catch (Exception ex) { if (r != null) r.Close(); if (responseHtml != null) { responseHtml.Close(); } if (requestHtml != null) { requestHtml.Abort(); } Logger.Instance.LogMessage(ex.Message, LogLevel.ERROR); break; } string source = r.ReadToEnd(); r.Close(); //Source cropping source = source.Substring(Math.Max(source.IndexOf(provider.SearchStart), 0)); source = source.Substring(0, Math.Max(source.LastIndexOf(provider.SearchEnd), source.Length - 1)); ps = ParseSearch(ref source, responseHtml.ResponseUri.AbsoluteUri, Showname, SearchString, provider); } responseHtml.Close(); } return ps; }
/// <summary> /// Parses search results from a series search /// </summary> /// <param name="source">Source code of the search results page</param> /// <param name="Showname">Showname</param> /// <param name="SourceURL">URL of the page source</param> public static ParsedSearch ParseSearch(ref string source, string SourceURL, string Showname, string SearchString, RelationProvider provider) { ParsedSearch ps = new ParsedSearch(); ps.Showname = Showname; ps.SearchString = SearchString; ps.provider = provider; if (String.IsNullOrEmpty(source)){ return ps; } if (provider == null) { Logger.Instance.LogMessage("No relation provider found/selected", LogLevel.ERROR); return ps; } Logger.Instance.LogMessage("Trying to match source at " + SourceURL + " with " + provider.SearchRegExp, LogLevel.DEBUG); RegexOptions ro = RegexOptions.IgnoreCase | RegexOptions.Singleline; if (provider.SearchRightToLeft){ ro |= RegexOptions.RightToLeft; } MatchCollection mc = Regex.Matches(source, provider.SearchRegExp, ro); if (mc.Count == 0) { Logger.Instance.LogMessage("No results found", LogLevel.INFO); return ps; } /*else if (mc.Count == 1) { string url = provider.RelationsPage; Logger.Instance.LogMessage("One result found on search page, going to " + url.Replace(" ", "%20") + " with %L=" + mc[0].Groups["link"].Value, LogLevel.DEBUG); url = url.Replace("%L", mc[0].Groups["link"].Value); url = System.Web.HttpUtility.HtmlDecode(url); ps.Results = new Hashtable(); string CleanedName=CleanSearchResultName(Showname,provider); if(!Regex.Match(CleanedName, provider.SearchResultsBlacklist).Success){ ps.Results.Add(CleanedName, url); Logger.Instance.LogMessage("Search engine found one result: " + url.Replace(" ", "%20"), LogLevel.INFO); } return ps; //GetRelations(url, Showname); }*/ else { Logger.Instance.LogMessage("Search engine found multiple results at " + SourceURL.Replace(" ", "%20"), LogLevel.INFO); ps.Results = new Hashtable(); foreach (Match m in mc) { string url = provider.RelationsPage; url = url.Replace("%L", m.Groups["link"].Value); url = System.Web.HttpUtility.HtmlDecode(url); string name=System.Web.HttpUtility.HtmlDecode(m.Groups["name"].Value + " " + m.Groups["year"].Value); //temporary fix, this should be externalized in the provider configs if(name.ToLower().Contains("poster")) continue; string CleanedName = CleanSearchResultName(name, provider); try { ps.Results.Add(CleanedName, url); } catch (Exception) { Logger.Instance.LogMessage("Can't add " + CleanedName + " to search results because an entry of same name already exists", LogLevel.ERROR); } } return ps; /* SelectResult sr = new SelectResult(mc, provider, false); if (sr.ShowDialog() == DialogResult.Cancel || sr.url == "") return; //Apply language of selected result to matching episodes if (provider.Language == Helper.Languages.None) { foreach (InfoEntry ie in InfoEntryManager.Instance) { if (ie.Showname == Showname && ie.ProcessingRequested) { ie.Language = sr.Language; } } } string url = provider.RelationsPage; Logger.Instance.LogMessage("User selected " + provider.RelationsPage + "with %L=" + sr.url, LogLevel.DEBUG); url = url.Replace("%L", sr.url); url = System.Web.HttpUtility.HtmlDecode(url); GetRelations(url, Showname);*/ } }
//parse page(s) containing relations /// <summary> /// Parses page containing the relation data /// </summary> /// <param name="url">URL of the page to parse</param> /// <param name="Showname">Showname</param> public static void GetRelations(string url, string Showname, RelationProvider provider,BackgroundWorker worker, DoWorkEventArgs dwea) { if (provider == null) { Logger.Instance.LogMessage("GetRelations: No relation provider found/selected", LogLevel.ERROR); return; } if (String.IsNullOrEmpty(url)) { Logger.Instance.LogMessage("GetRelations: URL is null or empty", LogLevel.ERROR); return; } if (String.IsNullOrEmpty(Showname)) { Logger.Instance.LogMessage("GetRelations: Showname is null or empty", LogLevel.ERROR); return; } Logger.Instance.LogMessage("Trying to get relations from " + url, LogLevel.DEBUG); //if episode infos are stored on a new page for each season, this should be marked with %S in url, so we can iterate through all those pages int season = 1; string url2 = url; //Create new RelationCollection RelationCollection rc = new RelationCollection(Showname); while (true) { if (url2.Contains("%S")) { url = url2.Replace("%S", season.ToString()); } if (url == null || url == "") return; // request url = System.Web.HttpUtility.UrlPathEncode(url); Logger.Instance.LogMessage("Trying to get relations for season " + season + " from " + url, LogLevel.DEBUG); HttpWebRequest requestHtml = null; try { requestHtml = (HttpWebRequest)(HttpWebRequest.Create(url)); } catch (Exception ex) { Logger.Instance.LogMessage(ex.Message, LogLevel.ERROR); requestHtml.Abort(); return; } requestHtml.Timeout = Helper.ReadInt(Config.Timeout); // get response HttpWebResponse responseHtml = null; try { responseHtml = (HttpWebResponse)(requestHtml.GetResponse()); } catch (WebException ex) { //Serienjunkies returns "(300) Mehrdeutige Umleitung" when an inexistant season is requested if (ex.Message.Contains("(300)")) break; Logger.Instance.LogMessage(ex.Message, LogLevel.ERROR); if (responseHtml != null) { responseHtml.Close(); } return; } Logger.Instance.LogMessage("Response URL: " + responseHtml.ResponseUri.AbsoluteUri, LogLevel.DEBUG); //if we get redirected, lets assume this page does not exist if (responseHtml.ResponseUri.AbsoluteUri != url) { Logger.Instance.LogMessage("Response URL doesn't match request URL, page doesn't seem to exist", LogLevel.DEBUG); responseHtml.Close(); requestHtml.Abort(); break; } // and download //Logger.Instance.LogMessage("charset=" + responseHtml.CharacterSet, LogLevel.INFO); Encoding enc; if (provider.Encoding != null && provider.Encoding != "") { try { enc = Encoding.GetEncoding(provider.Encoding); } catch (Exception ex) { Logger.Instance.LogMessage("Invalid encoding in config file: " + ex.Message, LogLevel.ERROR); enc = Encoding.GetEncoding(responseHtml.CharacterSet); } } else { enc = Encoding.GetEncoding(responseHtml.CharacterSet); } StreamReader r = new StreamReader(responseHtml.GetResponseStream(), enc); string source = r.ReadToEnd(); r.Close(); responseHtml.Close(); //Source cropping source = source.Substring(Math.Max(source.IndexOf(provider.RelationsStart), 0)); source = source.Substring(0, Math.Max(source.LastIndexOf(provider.RelationsEnd), 0)); string pattern = provider.RelationsRegExp; //for some reason, responseHtml.ResponseUri is null for some providers when running on mono if(!Settings.Instance.IsMonoCompatibilityMode){ Logger.Instance.LogMessage("Trying to match source from " + responseHtml.ResponseUri.AbsoluteUri + " with " + pattern, LogLevel.DEBUG); } RegexOptions ro = RegexOptions.IgnoreCase | RegexOptions.Singleline; if (provider.RelationsRightToLeft) ro |= RegexOptions.RightToLeft; MatchCollection mc = Regex.Matches(source, pattern, ro); string CleanupRegex = provider.RelationsRemove; for (int i = 0; i < mc.Count; i++) { Match m = mc[i]; string result = Regex.Replace(System.Web.HttpUtility.HtmlDecode(m.Groups["Title"].Value), CleanupRegex, ""); //RelationsRemove may be used to filter out results completely, for example if they are a html tag if (result != "") { //parse season and episode numbers int s, e; Int32.TryParse(m.Groups["Season"].Value, out s); Int32.TryParse(m.Groups["Episode"].Value, out e); //if we are iterating through season pages, take season from page url directly if (url != url2) { rc.AddRelation(new Relation(season, e, result)); Logger.Instance.LogMessage("Found Relation: " + "S" + s.ToString() + "E" + e.ToString() + " - " + result, LogLevel.DEBUG); } else { rc.AddRelation(new Relation(s, e, result)); Logger.Instance.LogMessage("Found Relation: " + "S" + s.ToString() + "E" + e.ToString() + " - " + result, LogLevel.DEBUG); } } } RelationManager.Instance.AddRelationCollection(rc); // THOU SHALL NOT FORGET THE BREAK if (!url2.Contains("%S")) break; season++; } Logger.Instance.LogMessage("" + (season - 1) + " Seasons, " + rc.Count + " relations found", LogLevel.DEBUG); }