/// <summary> /// Converts a MW URL from arcanewonders.com into a ConverterDeck which is populated with all cards and deck name. /// </summary> /// <param name="url">The URL of the Deck</param> /// <param name="deckSectionNames">List of the name of each section for the deck being converted.</param> /// <param name="convertGenericFileFunc"> /// Function to convert a collection of lines from a deck file into a ConverterDeck. /// Used when downloading a Deck File from a webpage instead of scraping. /// </param> /// <returns>A ConverterDeck which is populated with all cards and deck name</returns> public override ConverterDeck Convert( string url, IEnumerable <string> deckSectionNames, Func <IEnumerable <string>, IEnumerable <string>, ConverterDeck> convertGenericFileFunc) { object htmlWebInstance = HtmlAgilityPackWrapper.HtmlWeb_CreateInstance(); object htmlDocumentInstance = HtmlAgilityPackWrapper.HtmlWeb_InvokeMethod_Load(htmlWebInstance, url); object htmlDocument_DocumentNode = HtmlAgilityPackWrapper.HtmlDocument_GetProperty_DocumentNode(htmlDocumentInstance); ConverterDeck converterDeck = new ConverterDeck(deckSectionNames); // Find the div with id 'spellbook' because all deck data is contained inside it object spellbookDiv = HtmlAgilityPackWrapper.HtmlNode_InvokeMethod_SelectSingleNode(htmlDocument_DocumentNode, "//div[@id='spellbook']"); if (spellbookDiv == null) { throw new InvalidOperationException("Could not find the html div 'spellbook', are you sure this webpage has a deck?"); } // Insert the Deck Name if available object spellbooknameSpan = HtmlAgilityPackWrapper.HtmlNode_InvokeMethod_SelectSingleNode(spellbookDiv, "//span[@id='spellbookname']"); if (spellbooknameSpan != null) { converterDeck.DeckName = HtmlAgilityPackWrapper.HtmlNode_GetProperty_InnerText(spellbooknameSpan); } // Convert the Mage card object firstMageSpan = HtmlAgilityPackWrapper.HtmlNode_InvokeMethod_SelectNodes(spellbookDiv, "//span[@id='mage']").FirstOrDefault(); if (firstMageSpan != null) { ConverterSection mageSection = converterDeck.ConverterSections.First(cs => cs.SectionName.Equals("Mage", StringComparison.InvariantCultureIgnoreCase)); mageSection.AddConverterMapping(new ConverterMapping( HtmlAgilityPackWrapper.HtmlNode_GetProperty_InnerText(firstMageSpan), string.Empty, 1)); } // The div 'spells' contains all the cards, grouped by spell class object spellsDiv = HtmlAgilityPackWrapper.HtmlNode_InvokeMethod_SelectSingleNode(spellbookDiv, "//div[@id='spells']"); // Get a collection of all the span nodes inside the 'spells' div IEnumerable <object> cardAndSectionSpans = HtmlAgilityPackWrapper.HtmlNode_InvokeMethod_SelectNodes(spellsDiv, "span"); ConverterSection currentConverterSection = null; foreach (object cardOrSectionSpan in cardAndSectionSpans) { // get the class name of the span IEnumerable <object> attributes = HtmlAgilityPackWrapper.HtmlNode_GetProperty_Attributes(cardOrSectionSpan); string className = string.Empty; foreach (object attribute in attributes) { if (HtmlAgilityPackWrapper.HtmlAttribute_GetProperty_Name(attribute).Equals("class", StringComparison.InvariantCultureIgnoreCase)) { className = HtmlAgilityPackWrapper.HtmlAttribute_GetProperty_Value(attribute); break; } } // If the class name of the span is 'spellClass', then it denotes a Deck Section. Find the corresponding ConverterSection if (className.Equals("spellClass", StringComparison.InvariantCultureIgnoreCase)) { string currentSpellClass = HtmlAgilityPackWrapper.HtmlNode_GetProperty_InnerText(cardOrSectionSpan); currentConverterSection = converterDeck.ConverterSections.First(cs => cs.SectionName.Equals(currentSpellClass, StringComparison.InvariantCultureIgnoreCase)); } else { // This span contains a card and quantity, so parse it string quantityAndCardString = HtmlAgilityPackWrapper.HtmlNode_GetProperty_InnerText(cardOrSectionSpan); ConverterMapping converterMapping = TextConverter.RegexMatch_RegularCard(quantityAndCardString); currentConverterSection.AddConverterMapping(converterMapping); } } return(converterDeck); }
/// <summary> /// Converts a URL from mtgvault.com into a ConverterDeck which is populated with all cards and deck name. /// </summary> /// <param name="url">The URL of the Deck</param> /// <param name="deckSectionNames">List of the name of each section for the deck being converted.</param> /// <param name="convertGenericFileFunc"> /// Function to convert a collection of lines from a deck file into a ConverterDeck. /// Used when downloading a Deck File from a webpage instead of scraping. /// </param> /// <returns>A ConverterDeck which is populated with all cards and deck name</returns> public override ConverterDeck Convert( string url, IEnumerable <string> deckSectionNames, Func <IEnumerable <string>, IEnumerable <string>, ConverterDeck> convertGenericFileFunc) { object htmlWebInstance = HtmlAgilityPackWrapper.HtmlWeb_CreateInstance(); object htmlDocumentInstance = HtmlAgilityPackWrapper.HtmlWeb_InvokeMethod_Load(htmlWebInstance, url); object htmlDocument_DocumentNode = HtmlAgilityPackWrapper.HtmlDocument_GetProperty_DocumentNode(htmlDocumentInstance); // Extract the '__VIEWSTATE' and '__EVENTVALIDATION' input values string viewstateValue = null; string eventValidationValue = null; // Get a collection of all the input nodes IEnumerable <object> aspnetFormInputNodes = HtmlAgilityPackWrapper.HtmlNode_InvokeMethod_SelectNodes(htmlDocument_DocumentNode, "//input"); foreach (object inputNode in aspnetFormInputNodes) { // get the name of the input IEnumerable <object> attributes = HtmlAgilityPackWrapper.HtmlNode_GetProperty_Attributes(inputNode); string name = string.Empty; foreach (object attribute in attributes) { if (HtmlAgilityPackWrapper.HtmlAttribute_GetProperty_Name(attribute).Equals("name", StringComparison.InvariantCultureIgnoreCase)) { name = HtmlAgilityPackWrapper.HtmlAttribute_GetProperty_Value(attribute); break; } } if (name.Equals(@"__VIEWSTATE", StringComparison.InvariantCultureIgnoreCase)) { foreach (object attribute in attributes) { if (HtmlAgilityPackWrapper.HtmlAttribute_GetProperty_Name(attribute).Equals("value", StringComparison.InvariantCultureIgnoreCase)) { viewstateValue = HtmlAgilityPackWrapper.HtmlAttribute_GetProperty_Value(attribute); break; } } } else if (name.Equals(@"__EVENTVALIDATION", StringComparison.InvariantCultureIgnoreCase)) { foreach (object attribute in attributes) { if (HtmlAgilityPackWrapper.HtmlAttribute_GetProperty_Name(attribute).Equals("value", StringComparison.InvariantCultureIgnoreCase)) { eventValidationValue = HtmlAgilityPackWrapper.HtmlAttribute_GetProperty_Value(attribute); break; } } } } System.Collections.Specialized.NameValueCollection outgoingQueryString = System.Web.HttpUtility.ParseQueryString(String.Empty); outgoingQueryString.Add(@"__EVENTTARGET", @"ctl00$ContentPlaceHolder1$LinkButton1"); outgoingQueryString.Add(@"__EVENTARGUMENT", string.Empty); outgoingQueryString.Add(@"__VIEWSTATE", viewstateValue); outgoingQueryString.Add(@"__EVENTVALIDATION", eventValidationValue); outgoingQueryString.Add(@"ctl00$ContentPlaceHolder1$TextBox_AutoCompleteSideBoard", string.Empty); outgoingQueryString.Add(@"ctl00$ContentPlaceHolder1$TextBox_QuantitySideBoard", string.Empty); outgoingQueryString.Add(@"ctl00$ContentPlaceHolder1$TextBox_BulkImportSideBoard", string.Empty); outgoingQueryString.Add(@"ctl00$Login1$TextBox_Username", string.Empty); outgoingQueryString.Add(@"ctl00$Login1$TextBox_Password", string.Empty); string postData = outgoingQueryString.ToString(); ASCIIEncoding ascii = new ASCIIEncoding(); byte[] postBytes = ascii.GetBytes(postData.ToString()); System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url); request.Method = "POST"; request.Accept = "text/html,application/xhtml+xml,application/xml"; request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = postBytes.Length; request.Host = "www.mtgvault.com"; request.Referer = url; request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0"; // add post data to request System.IO.Stream postStream = request.GetRequestStream(); postStream.Write(postBytes, 0, postBytes.Length); postStream.Flush(); postStream.Close(); System.Net.WebResponse response = request.GetResponse(); string filename = response.Headers["content-disposition"]; System.IO.Stream dataStream = response.GetResponseStream(); System.IO.StreamReader reader = new System.IO.StreamReader(dataStream); string responseFromServer = System.Web.HttpUtility.HtmlDecode(reader.ReadToEnd()); reader.Close(); response.Close(); filename = filename.Replace(@"attachment;", string.Empty); filename = filename.Replace(@".txt", string.Empty); ConverterDeck converterDeck = convertGenericFileFunc(TextConverter.SplitLines(responseFromServer), deckSectionNames); converterDeck.DeckName = filename; return(converterDeck); }