/// <summary> /// This method basically does what it can to possibly sanitise the input. /// Tries to match a program, extract a series and episode number, extract attributes like S for subtitles etc. /// It should be specific to each feed probably. The regexes are quite specific thouogh. /// </summary> /// <param name="tag"></param> /// <param name="handler"></param> /// <param name="channelUriLookup"></param> /// <param name="results"></param> private void AddPrograms(TvProgramBroadCastListingImport tag, AddTvBroadCastListingInfoHandler handler, Dictionary<string, TvChannelListingSource> channelUriLookup, tvProgramme[] results) { foreach (var program in results) { // the xmltv sometimes have missing end times but these are recognised by start == stop var start = BlebXmltvProvider.ParseDateStringToUtc(program.start); DateTime? end = BlebXmltvProvider.ParseDateStringToUtc(program.stop); // we use a null in the DB if we don't know the end time if (start == end) { end = null; } // try and clean up the program titles etc. var programTitle = program.title.Value; var episodeTitle = program.subtitle?.Value; var episodeDescription = program.desc?.Value; // and see if we can extract any of this metadata int? seriesNumber = null; int? episodeNumber = null; BroadCastListingAttributes attribs = 0; // try and clean up the program titles etc. if (episodeDescription != null) { // the bleb import feed titles sometimes run into the descriptions using ...s if (programTitle.EndsWith("...") && episodeDescription.StartsWith("...")) { // find when the runon ends, ignoring the start ... var endOfRunOn = episodeDescription.IndexOf('.', 3); if (endOfRunOn != -1) { // trim out the ...s and append the episode description programTitle = programTitle.Substring(0, programTitle.Length - 3) + ' ' + episodeDescription.Substring(3, endOfRunOn - 3); // then trim off title from the start of the description, and the full stop and any spaces episodeDescription = episodeDescription.Substring(endOfRunOn + 1).Trim(' '); } } // do a bit of basic sanitisation (necessary for the runons above! but shouldn't be harmful here) programTitle = programTitle.Trim(' ', '.'); // AlsoInHdRegex try { var match = AlsoInHdRegex.Match(episodeDescription); if (match.Success) { attribs = attribs | BroadCastListingAttributes.AvailableInHD; episodeDescription = match.Groups["pre"].Value + match.Groups["post"].Value; } } catch { } // BBCAttribsRegex try { // then try and pull out BBC style attribs like HD, subtitles, audio descriptions like [S, AD] var match = BBCAttribsRegex.Match(episodeDescription); if (match.Success) { if (match.Groups["attribs"].Success) { var strings = match.Groups["attribs"].Value.Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries); if (strings.Contains("S")) attribs = attribs | BroadCastListingAttributes.Subtitles; if (strings.Contains("AD")) attribs = attribs | BroadCastListingAttributes.AudioDescription; } episodeDescription = match.Groups["pre"].Value + match.Groups["post"].Value; } } catch { } try { // then try and pull out some episode information with the N/N format var match = BBCEpisodeRegex.Match(episodeDescription); if (match.Success) { episodeNumber = int.Parse(match.Groups["episode"].Value); episodeDescription = match.Groups["post"].Value; } else { // and then try SN, EN format match = OtherEpisodeRegex.Match(episodeDescription); if (match.Success) { seriesNumber = int.Parse(match.Groups["series"].Value); episodeNumber = int.Parse(match.Groups["episode"].Value); episodeDescription = match.Groups["pre"].Value + match.Groups["post"].Value; } } } // ignore any metadata that fails extraction but still save the rest catch (ArgumentNullException) { } catch (FormatException) { } } // and remove any double spaces we might have introduced episodeDescription = episodeDescription?.Replace(" ", " ").Trim(); try { handler( tag, channelUriLookup[program.channel], new AddBroadcastListingInfo { StartAt = start, EndAt = end, ProgramTitle = programTitle, EpisodeTitle = episodeTitle, EpisodeDescription = episodeDescription, SeriesNumber = seriesNumber, EpisodeNumber = episodeNumber, Attributes = (int)attribs } ); } catch (TvBroadCastListingAlreadyExistsException) { // the feed just violated the PK for this entry, carry on with the next one continue; } } }
/// <summary> /// Performs an update for the specified channels for the specified days! /// </summary> /// <param name="tag"></param> /// <param name="channels"></param> /// <param name="days"></param> /// <param name="handler"></param> /// <returns></returns> public void ImportPrograms(TvProgramBroadCastListingImport tag, IEnumerable<TvChannelListingSource> channels, IEnumerable<int> days, AddTvBroadCastListingInfoHandler handler) { var importer = new BlebXmltvProvider(); // get a list of the source names to pass to the importer var blebChannelNames = channels.Select(x => x.SourceChannelName); var results = importer.GetFeedResults(blebChannelNames, days).Result; // create a dictionary of channel URI -> TvChannel for the importer to find the TvChannelId from the URI var channelUriLookup = channels.ToDictionary(x => x.SourceChannelUri, x => x); // add each program if (results.programme != null) { AddPrograms(tag, handler, channelUriLookup, results.programme); } }