private static string GetEpisodeXml(SeriesBase series, Episode episode, IEnumerable <string> bannerImages) { var metadata = new EpisodeMetadata(); var m = new Movie { Title = episode.EpisodeName, Season = episode.SeasonNumber.Value, Episode = episode.EpisodeNumber.Value, Year = episode.FirstAired.Year, Rating = episode.Rating, Plot = series.Overview, EpisodePlot = episode.Overview, MPAA = series.ContentRating, Runtime = series.Runtime.Value, genres = SeriesIOHelper.ToArray(series.Genre), Director = episode.Director, Credits = episode.Writer }; var cast = series.Actors.Length > 0 ? series.Actors : episode.GuestStars; m.cast = SeriesIOHelper.ToArray(cast); m.image = bannerImages.ToArray(); metadata.Movie = m; return(metadata.AsXml()); }
/// <summary> /// Take the raw episode data row and create a nicely typed struct. /// </summary> private EpisodeMetadata ExtractEpisodeMetadata(DataRow episodeData, int episodeId) { EpisodeMetadata metadata = new EpisodeMetadata(); metadata.Title = (string)episodeData["TV_Episode_Title"]; metadata.Summary = (string)episodeData["TV_Episode_Description"]; metadata.GalleryImagePath = (string)episodeData["TV_Episode_Gallery_Image"]; metadata.DetailImagePath = (string)episodeData["TV_Episode_Detail_Image"]; metadata.Length = (int)episodeData["TV_Episode_Length"]; metadata.Season = (int)episodeData["TV_Episode_Season"]; metadata.ReleaseDate = (DateTime)episodeData["TV_Episode_Release_Date"]; metadata.Id = (int)episodeData["TV_Episode_ID"]; metadata.ShowId = (int)episodeData["TV_Show_ID"]; // // Rating // DataRow rating = Z.DataSetHelpers.GetIDMappedDataRow(episodeData, "TV_Rating_ID", dataSet.Tables["tbl_TV_Rating"], "TV_Rating_ID"); metadata.Rating = (string)rating["TV_Rating"]; return(metadata); }
protected override async Task SaveInternal() { Title.Save(); SeasonNumber.Save(); EpisodeNumber.Save(); EpisodeMetadata metadata = CreateMetadata(); await _metadataService.Save(Path, metadata); }
public Tuple <EpisodeMetadata, int> GetFallbackMetadata(Episode episode) { string path = episode.MediaVersions.Head().MediaFiles.Head().Path; string fileName = Path.GetFileName(path); var metadata = new EpisodeMetadata { MetadataKind = MetadataKind.Fallback, Title = fileName ?? path, DateAdded = DateTime.UtcNow }; return(fileName != null?GetEpisodeMetadata(fileName, metadata) : Tuple(metadata, 0)); }
private async Task <Either <BaseError, PlexEpisode> > UpdateArtwork(PlexEpisode existing, PlexEpisode incoming) { EpisodeMetadata existingMetadata = existing.EpisodeMetadata.Head(); EpisodeMetadata incomingMetadata = incoming.EpisodeMetadata.Head(); if (incomingMetadata.DateUpdated > existingMetadata.DateUpdated) { await UpdateArtworkIfNeeded(existingMetadata, incomingMetadata, ArtworkKind.Thumbnail); } return(existing); }
/// <summary> /// Create a details page for an episode. /// NOTE: This is public to enable debug markup access. /// </summary> public DetailsPage CreateEpisodeDetailsPage(int episodeId) { DetailsPage page = new DetailsPage(); // // Get the full metadata on the episode. // DataRow episodeData = GetEpisodeData(episodeId); EpisodeMetadata episodeMetadata = ExtractEpisodeMetadata(episodeData, episodeId); // // Get the full metadata on the show. // DataRow showData = GetShowData(episodeMetadata.ShowId); ShowMetadata showMetadata = ExtractShowMetadata(showData, episodeMetadata.ShowId); // // Fill in the page's easy properties. // page.Title = episodeMetadata.Title; page.Summary = episodeMetadata.Summary; page.Background = LoadImage(episodeMetadata.DetailImagePath); // // Metadata // // Now that we have all the little pieces, we can put together our // final metadata string. // page.Metadata = String.Format(Z.Resources.TV_Details_Metadata, showMetadata.Provider, episodeMetadata.Season, showMetadata.Genre, episodeMetadata.Length, showMetadata.CountryShortName, episodeMetadata.ReleaseDate.Year); // // Actions // CreateEpisodeDetailsCommands(page, episodeData, episodeId); return(page); }
public async Task Refresh_Always_RefreshesTvShowProperties() { // Arrange EpisodeMetadata metadata = CreateEpisodeMetadata(); _metadataService.Get(_path) .Returns(Task.FromResult(metadata)); // Act await _viewModel.Refresh(); // Assert AssertMetadataEqualsViewModel(metadata); }
public async Task Update_WhenMetadataAlreadyExists_DoesNothing() { // Arrange EpisodeMetadata metadata = CreateEpisodeMetadata(); _metadataService.Get(_path) .Returns(Task.FromResult(metadata)); _tvShowMetadata.Id .Returns("123"); // Act await _viewModel.Update(); // Assert _metadataService.DidNotReceiveWithAnyArgs() .Update(_path, "123").Async(); }
private async Task <Either <BaseError, Episode> > UpdateThumbnail(Episode episode) { try { await LocateThumbnail(episode).IfSomeAsync( async posterFile => { EpisodeMetadata metadata = episode.EpisodeMetadata.Head(); await RefreshArtwork(posterFile, metadata, ArtworkKind.Thumbnail); }); return(episode); } catch (Exception ex) { return(BaseError.New(ex.ToString())); } }
private bool AssertMetadataEqualsViewModel(EpisodeMetadata metadata) { Assert.Equal(metadata.AiredDate, _viewModel.AiredDate); Assert.Equal(metadata.Credits, _viewModel.Credits.Collection); Assert.Equal(metadata.Director, _viewModel.Directors.Collection); Assert.Equal(metadata.DisplayEpisode, _viewModel.DisplayEpisode); Assert.Equal(metadata.DisplaySeason, _viewModel.DisplaySeason); Assert.Equal(metadata.EpisodeBookmarks, _viewModel.EpisodeBookmarks); Assert.Equal(metadata.EpisodeNumber, _viewModel.EpisodeNumber.Value); Assert.Equal(metadata.ImageUrl, _viewModel.ImageUrl); Assert.Equal(metadata.LastPlayed, _viewModel.LastPlayed); Assert.Equal(metadata.PlayCount, _viewModel.PlayCount); Assert.Equal(metadata.Plot, _viewModel.Plot); Assert.Equal(metadata.Rating, _viewModel.Rating); Assert.Equal(metadata.SeasonNumber, _viewModel.SeasonNumber.Value); Assert.Equal(metadata.Title, _viewModel.Title.Value); return(true); }
private Tuple <EpisodeMetadata, int> GetEpisodeMetadata(string fileName, EpisodeMetadata metadata) { try { const string PATTERN = @"^(.*?)[.\s-]+[sS](\d+)[eE](\d+).*\.\w+$"; Match match = Regex.Match(fileName, PATTERN); if (match.Success) { metadata.Title = match.Groups[1].Value; metadata.DateUpdated = DateTime.UtcNow; return(Tuple(metadata, int.Parse(match.Groups[3].Value))); } } catch (Exception) { // ignored } return(Tuple(metadata, 0)); }
private async Task <Either <BaseError, MediaItemScanResult <PlexEpisode> > > UpdateArtwork( MediaItemScanResult <PlexEpisode> result, PlexEpisode incoming) { PlexEpisode existing = result.Item; foreach (EpisodeMetadata incomingMetadata in incoming.EpisodeMetadata) { Option <EpisodeMetadata> maybeExistingMetadata = existing.EpisodeMetadata .Find(em => em.EpisodeNumber == incomingMetadata.EpisodeNumber); if (maybeExistingMetadata.IsSome) { EpisodeMetadata existingMetadata = maybeExistingMetadata.ValueUnsafe(); await UpdateArtworkIfNeeded(existingMetadata, incomingMetadata, ArtworkKind.Thumbnail); await _metadataRepository.MarkAsUpdated(existingMetadata, incomingMetadata.DateUpdated); } } return(result); }
public async Task Update_WhenNoMetadataAlreadyExists_RetrievesFreshMetadata() { // Arrange EpisodeMetadata metadata = CreateEpisodeMetadata(); _metadataService.Get(_path) .Returns(new EpisodeMetadata().ToTask(), metadata.ToTask()); _tvShowMetadata.Id .Returns("123"); // Act IEnumerable <ProgressItem> items = await _viewModel.Update(); ProgressItem item = items.First(); await item.Execute(); // Assert _metadataService.Received() .Update(_path, "123").Async(); AssertMetadataEqualsViewModel(metadata); }
private void RefreshFromMetadata(EpisodeMetadata metadata) { Title.Value = metadata.Title; Title.Save(); Rating = metadata.Rating; SeasonNumber.Value = metadata.SeasonNumber; SeasonNumber.Save(); EpisodeNumber.Value = metadata.EpisodeNumber; EpisodeNumber.Save(); Plot = metadata.Plot; ImagePath.RefreshImage(metadata.ImagePath); ImageUrl = metadata.ImageUrl; PlayCount = metadata.PlayCount; LastPlayed = metadata.LastPlayed; AiredDate = metadata.AiredDate; DisplaySeason = metadata.DisplaySeason; DisplayEpisode = metadata.DisplayEpisode; EpisodeBookmarks = metadata.EpisodeBookmarks; Credits.ReplaceWith(metadata.Credits); Directors.ReplaceWith(metadata.Director); _localMetadataExists = metadata.FileInformation != null; }
public Task <Unit> RemoveMetadata(Episode episode, EpisodeMetadata metadata) => throw new NotSupportedException();
public Task <bool> AddActor(EpisodeMetadata metadata, Actor actor) => throw new NotSupportedException();
/// <summary> /// Called when one of the custom actions on a details page is clicked. /// </summary> private void OnEpisodeDetailsActionInvoked(DetailsCommand command) { TVEpisodeDetailsActionType actionType = (TVEpisodeDetailsActionType)command.Type; string value = command.Value; int episodeId = command.ItemId; // // Interpret the action. // switch (actionType) { case TVEpisodeDetailsActionType.WatchNow: { // Placeholder... break; } case TVEpisodeDetailsActionType.Record: { // // TODO: Grab the xml from the database // // As is this code schedules a manual 30 minute recording to // occur 1 hour from now on channel 4. // string xmlRecordingInfoFormat = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<clickToRecord xmlns=\"urn:schemas-microsoft-com:ehome:clicktorecord\">\n\t<body>\n\t\t<programRecord programDuration=\"30\">\n\t\t\t<service>\n\t\t\t\t<key field=\"urn:schemas-microsoft-com:ehome:epg:service#mappedChannelNumber\" match=\"exact\">{0}</key>\n\t\t\t</service>\n\t\t\t<airing>\n\t\t\t\t<key field=\"urn:schemas-microsoft-com:ehome:epg:airing#starttime\">{1}</key>\n\t\t\t</airing>\n\t\t</programRecord>\n\t</body>\n</clickToRecord>"; int channelNumber = 4; DateTime time = DateTime.UtcNow.AddHours(1); string xmlRecordingInfo = String.Format(xmlRecordingInfoFormat, channelNumber, time.ToString("o")); XmlReader reader = XmlReader.Create(new StringReader(xmlRecordingInfo)); CreateScheduleRequestResult scheduleResult = CreateScheduleRequestResult.NoConfiguredResource; try { // // Create EventSchedule object and create ScheduleRequest from XML. // EventSchedule scheduler = new EventSchedule(); ScheduleRequest request = null; scheduleResult = scheduler.CreateScheduleRequest(reader, ConflictResolutionPolicy.AllowConflict, "example", out request); Debug.WriteLine("DetailsAction: Record: " + scheduleResult); } catch (EventScheduleException) { // TV may not be configured - handle that exception. Application.Current.MessageBox(Z.Resources.TV_NotSetUpDialog_Text, Z.Resources.TV_NotSetUpDialog_Caption); } // // Display a dialog to notify the user. // if ((scheduleResult != CreateScheduleRequestResult.NoConfiguredResource) && (Application.Current.MediaCenterEnvironment != null)) { EpisodeMetadata metadata = ExtractEpisodeMetadata(GetEpisodeData(episodeId), episodeId); // Two options: "View Scheduled" or "OK" IEnumerable buttons = new object[] { Z.Resources.TV_RecordDialog_ViewScheduled, (int)DialogButtons.Ok }; // Use the gallery image in the dialog. // Note that the Dialog API requires a standard Uri, so we // need to specificy the system drive letter. string systemDrive = Environment.GetEnvironmentVariable("SystemDrive"); string imagePath = "file://" + systemDrive + ImagesDirectory + metadata.GalleryImagePath; Application.Current.MediaCenterEnvironment.Dialog( Z.Resources.TV_RecordDialog_Text, metadata.Title, buttons, 0, true, imagePath, delegate(DialogResult dialogResult) { // Custom button #1 = 100 = "View Scheduled" // Navigate to the scheduled recordings page if ((int)dialogResult == 100) { Application.Current.MediaCenterEnvironment.NavigateToPage(PageId.ScheduledTVRecordings, null); } Debug.WriteLine("Dialog closed:" + dialogResult); } ); } break; } case TVEpisodeDetailsActionType.Related: { // // Go to this episode's show gallery. // EpisodeMetadata metadata = ExtractEpisodeMetadata(GetEpisodeData(episodeId), episodeId); GalleryPage page = CreateEpisodeGalleryPage(metadata.ShowId); Application.Current.GoToGallery(page); break; } default: Debug.WriteLine(String.Format("DetailsAction: {0}({1}): NOT YET IMPLEMENTED", actionType, value)); break; } }
public string GetEpisodeMetadata() { var metadata = new EpisodeMetadata(); return(metadata.AsXml()); }
public Task <bool> AddDirector(EpisodeMetadata metadata, Director director) => throw new NotSupportedException();
public Task <bool> AddWriter(EpisodeMetadata metadata, Writer writer) => throw new NotSupportedException();
protected override async Task RefreshInternal() { EpisodeMetadata metadata = await _metadataService.Get(Path); RefreshFromMetadata(metadata); }