private static async Task <IEnumerable <IGrouping <string, ShowTime> > > InnerReadShowTimesFromWebAsync(Theater theaterFromDb) { HtmlDocument marketsDocument = await InternetHelpers.GetPageHtmlDocumentAsync(theaterFromDb.CalendarUrl); HtmlNode showTimeControllerNode = marketsDocument.DocumentNode.SelectSingleNode("//div[@ng-controller='ShowtimeController']"); Regex showTimesRegex = new Regex(@"initCalendar\('([^']+)','([^']+)'\)"); Match showTimesMatch = showTimesRegex.Match(showTimeControllerNode.Attributes["ng-init"].Value); if (!showTimesMatch.Success) { _logger.Error("Show times did not have expected format {ShowTimeController}", showTimeControllerNode.OuterHtml); throw new Exception("Show times did not have expected format"); } string showTimesUrlBase = showTimesMatch.Groups[1].Value; string showTimesUrlCode = showTimesMatch.Groups[2].Value; string ajaxUrl = $"{showTimesUrlBase}calendar/{showTimesUrlCode}"; string jsonContent = await InternetHelpers.GetPageContentAsync(ajaxUrl); JToken json = JToken.Parse(jsonContent, new JsonLoadSettings()); // https://drafthouse.com/austin/tickets/showtime/0002/29212 //IEnumerable<IGrouping<string, ShowTime>> movies = if (json["Calendar"]["Cinemas"] == null) { _logger.Warn("No show time cinemas for {Theater}", theaterFromDb.Name); return(Enumerable.Empty <IGrouping <string, ShowTime> >()); } IEnumerable <IGrouping <string, ShowTime> > showTimesByMovie = from cinemaToken in json["Calendar"]["Cinemas"] from monthsNode in cinemaToken["Months"] from weeksNode in monthsNode["Weeks"] from daysNode in weeksNode["Days"] where daysNode["Films"] != null from filmsNode in daysNode["Films"] from seriesNode in filmsNode["Series"] from formatsNode in seriesNode["Formats"] from sessionsNode in formatsNode["Sessions"] let cinemaSlug = cinemaToken["MarketSlug"]?.Value <string>() let cinemaId = cinemaToken["CinemaId"]?.Value <string>() let title = filmsNode["FilmName"]?.Value <string>() let movieTitle = title let showTimeDateTime = sessionsNode["SessionDateTime"]?.Value <DateTime>() let showTimeId = sessionsNode["SessionId"]?.Value <string>() let showTimeStatus = sessionsNode["SessionStatus"]?.Value <string>() let seatsLeft = sessionsNode["SeatsLeft"]?.Value <int>() let showTimeUrl = $"https://drafthouse.com/{cinemaSlug}/tickets/showtime/{cinemaId}/{showTimeId}" let showTime = new ShowTime(theaterFromDb, showTimeUrl, showTimeDateTime, showTimeStatus, seatsLeft) group showTime by movieTitle into movieGroup select movieGroup; return(showTimesByMovie); }
private static async Task <IEnumerable <Theater> > InnerReadTheatersFromWebAsync(Market marketFromDb) { _logger.Info("Reading theaters for {Market} from web", marketFromDb.Name); HtmlDocument marketDocument = await InternetHelpers.GetPageHtmlDocumentAsync(marketFromDb.Url); var theatersFromWeb = from node in marketDocument.DocumentNode.Descendants("a") where node.Attributes["class"] != null && node.Attributes["class"].Value == "button small secondary Showtimes-time" let theaterUrl = node.Attributes["href"].Value select new Theater(marketFromDb, theaterUrl, node.InnerText); return(theatersFromWeb); }
private void GetDateTimeButton_Click(object sender, EventArgs e) { var current = InternetHelpers.LocalTime(); if (current.HasValue) { dateTimePicker1.Value = current.Value.Date; TimeTextBox.Text = $"{current.Value:T}"; } else { MessageBox.Show("Failed"); } }
private static async Task <IEnumerable <Market> > ReadMarketsFromWebAsync() { _logger.Info("Reading markets from web"); try { HtmlDocument marketsDocument = await InternetHelpers.GetPageHtmlDocumentAsync("https://drafthouse.com/markets"); var marketsFromWeb = from node in marketsDocument.DocumentNode.Descendants("a") where node.Attributes["id"]?.Value == "markets-page" let url = node.Attributes["href"].Value select new Market(url, node.InnerText); return(marketsFromWeb); } catch (Exception ex) { _logger.Error(ex, "Retry limit exceeded when reading markets"); return(Enumerable.Empty <Market>()); } }