/// <summary> /// Searches for a tutorial or the FAQ /// </summary> /// <param name="searchSeries">What series to search</param> /// <param name="searchTerm">What term to search</param> /// <param name="isPrivate">Was this invoked from a DM?</param> /// <returns>Returns a 2D list of strings</returns> public async Task <List <List <string> > > Search(string searchSeries, string searchTerm, bool isPrivate) { var foundData = new ImmutableArray <SearchDataResult>(); List <List <string> > listResults = new List <List <string> >(); //Let's us search on multiple terms at a time string[] searchTermArray = searchTerm.Split(' '); //Did we search FAQ? if (searchSeries.ToLower() == "faq" || searchSeries.ToLower() == "f" || searchSeries.ToLower() == "7") { return(SearchFaq(searchTerm, isPrivate)); } switch (searchSeries) { case "v2series": case "v2": case "1": foundData = await DataBaseUtil.GetTutorialsAsync(searchTermArray, "v2"); break; case "csgobootcamp": case "bc": case "2": foundData = await DataBaseUtil.GetTutorialsAsync(searchTermArray, "bc"); break; case "3dsmax": case "3ds": case "3": foundData = await DataBaseUtil.GetTutorialsAsync(searchTermArray, "3ds"); break; case "writtentutorials": case "written": case "4": foundData = await DataBaseUtil.GetTutorialsAsync(searchTermArray, "written"); break; case "legacyseries": case "v1": case "lg": case "5": foundData = await DataBaseUtil.GetTutorialsAsync(searchTermArray, "lg"); break; case "hammertroubleshooting": case "ht": case "6": case "misc": foundData = await DataBaseUtil.GetTutorialsAsync(searchTermArray, "ht"); break; case "all": foundData = await DataBaseUtil.GetTutorialsAsync(searchTermArray, "all"); break; default: //do nothing break; } //Process each result that was located foreach (var result in foundData) { List <string> singleResult = new List <string>(); //Limit to 3 FAQ results. //Then let's add another one with a direct link to the page. Only limit for non-DM if (listResults.Count >= 2 && searchSeries == "all" && !isPrivate) { singleResult.Clear(); singleResult.Add(@"View All Tutorials"); singleResult.Add("https://www.tophattwaffle.com/tutorials/"); singleResult.Add(@"There are more results than I can display without flooding chat. [Consider viewing all tutorials](https://www.tophattwaffle.com/tutorials/), or do a search without `all`. If you DM me your search the results won't be limited."); singleResult.Add(null); listResults.Add(singleResult); break; } //Create a HTML client so we can get info about the link HtmlWeb htmlWeb = new HtmlWeb(); HtmlDocument htmlDocument = htmlWeb.Load(result.url); string title = null; //Processing for non-YouTube URLs if (!result.url.Contains("youtube")) { //Get the page title title = (from x in htmlDocument.DocumentNode.Descendants() where x.Name.ToLower() == "title" select x.InnerText).FirstOrDefault(); } //Processing for YouTube URLs else if (result.url.ToLower().Contains("youtube")) { title = GetYouTubeTitle(result.url); } string description = null; //Get article content, this is by ID. Only works for my site. if (result.url.ToLower().Contains("tophattwaffle")) { description = htmlDocument.GetElementbyId("content-area").InnerText; } else if (result.url.ToLower().Contains("youtube")) { description = result.url; } //Only if not Null - Fix the bad characters that get pulled from the web page. description = description?.Replace(@"–", "-").Replace("\n", "").Replace(@"“", "\"").Replace(@"”", "\"").Replace(@"’", "'"); title = title?.Replace(@"–", "-").Replace("\n", "").Replace(" | TopHATTwaffle", "").Replace(@"“", "\"").Replace(@"”", "\"").Replace(@"’", "'"); //Limit length if needed if (description != null && description.Length >= 250) { description = description.Substring(0, 250) + "..."; } //Get images on the page List <string> imgs = null; if (!result.url.ToLower().Contains("youtube")) { imgs = (from x in htmlDocument.DocumentNode.Descendants() where x.Name.ToLower() == "img" select x.Attributes["src"].Value).ToList <string>(); } //Set image to the first non-header image if it exists. string finalImg = "https://www.tophattwaffle.com/wp-content/uploads/2017/11/1024_png-300x300.png"; if (imgs != null && imgs.Count > 1) { finalImg = imgs[_random.Next(0, imgs.Count)]; } if (result.url.Contains("youtube")) { finalImg = GetYouTubeImage(result.url); } //Add results to list singleResult.Add(title); singleResult.Add(result.url); singleResult.Add(description); singleResult.Add(finalImg); listResults.Add(singleResult); } return(listResults); }