public ChannelItemResult GetPlaylistItems(VodPlaylist playlist, CancellationToken cancellationToken) { var mediaItems = playlist.RecursiveChildren.OfType <VodMovie>().ToList(); var items = (from media in mediaItems let image = media.GetImages(ImageType.Primary).FirstOrDefault() select new ChannelItemInfo() { Id = media.IdentifierId.ToString(), Name = media.Name, ImageUrl = image?.Path, Type = ChannelItemType.Media, MediaType = ChannelMediaType.Video, ContentType = ChannelMediaContentType.Movie, MediaSources = media.ChannelMediaSources, Tags = media.Tags, CommunityRating = media.CommunityRating, Studios = media.Studios, DateCreated = media.DateCreated, ProductionYear = media.ProductionYear, ProviderIds = media.ProviderIds, Overview = media.Overview, Genres = media.Genres, HomePageUrl = media.HomePageUrl, OfficialRating = media.OfficialRating, PremiereDate = media.PremiereDate, RunTimeTicks = media.RunTimeTicks, }).ToList(); return(new ChannelItemResult() { Items = items.OrderBy(i => i.Name).ToList() }); }
public async Task <List <Media> > GetMediaItems(VodPlaylist playlist, CancellationToken cancellationToken) { var items = new List <Media>(); _logger.Debug("{0}: Starting to parse: {1}", playlist.Name, playlist.PlaylistUrl); using (Stream stream = await _httpClient.Get(playlist.PlaylistUrl.ToString(), CancellationToken.None).ConfigureAwait(false)) { using (var reader = new StreamReader(stream)) { while (!reader.EndOfStream) { var line = reader.ReadLine(); if (line.IndexOf("#EXTINF", StringComparison.CurrentCulture) != 0) { _logger.Debug("{0}: Non-valid line, skipping", playlist.Name); continue; } _logger.Debug("Found line with #EXTINF meta information"); var attributes = ParseAttributes(line); Uri streamUrl = null; Uri imgUri = null; if (attributes.Count == 0 || !attributes.ContainsKey("tvg-name") || !Uri.TryCreate(reader.ReadLine(), UriKind.Absolute, out streamUrl)) { continue; } // Fetch logo if (attributes.ContainsKey("tvg-logo")) { _logger.Debug("Found tvg-logo: {0}", attributes["tvg-logo"]); Uri.TryCreate(attributes["tvg-logo"], UriKind.Absolute, out imgUri); } var imageUrl = (imgUri != null) ? imgUri.ToString() : null; _logger.Debug("Adding: {0}, stream playlistUrl: {0}, image: {0}", attributes["tvg-name"], streamUrl, imageUrl); var media = new Media() { Name = attributes["tvg-name"].Trim(), Url = streamUrl.ToString(), PlaylistId = playlist.Id, Image = (imageUrl != null) ? imageUrl : null }; items.Add(media); } } } return(items); }
public void ConcatParts(Action <string> log, Action <string> setStatus, Action <double> setProgress, VodPlaylist vodPlaylist, string concatFile, bool removeFiles = true) { setStatus("Merging files"); setProgress(0); log(Environment.NewLine + Environment.NewLine + "Merging all VOD parts into '" + concatFile + "'..."); using (FileStream outputStream = new FileStream(concatFile, FileMode.OpenOrCreate, FileAccess.Write)) { int partsCount = vodPlaylist.Count; for (int i = 0; i < partsCount; i++) { VodPlaylistPart part = vodPlaylist[i]; using (FileStream partStream = new FileStream(part.LocalFile, FileMode.Open, FileAccess.Read)) { int maxBytes; byte[] buffer = new byte[4096]; while ((maxBytes = partStream.Read(buffer, 0, buffer.Length)) > 0) { outputStream.Write(buffer, 0, maxBytes); } } if (removeFiles) { FileSystem.DeleteFile(part.LocalFile); } setProgress(i * 100 / partsCount); } } setProgress(100); }
private async Task SyncMedia(VodPlaylist playlist, IProgress <double> progress, CancellationToken cancellationToken) { _logger.Info("{0}: parsing remote playlist: {1}", playlist.Name, playlist.PlaylistUrl); List <Media> mediaItems = await _m3UParser.GetMediaItems(playlist, cancellationToken); var existingMediaItems = _libraryManager.GetUserRootFolder() .RecursiveChildren.OfType <VodMovie>() .Where(p1 => mediaItems.FirstOrDefault(p2 => p2.IdentifierId == p1.IdentifierId) != null) .ToList(); if (playlist.Config.StrictSync) { // Remove local items that no longer exist on remote playlist var deleteLocally = playlist.RecursiveChildren.OfType <VodMovie>() .Where(m => mediaItems.Select(m1 => m1.IdentifierId).Contains(m.IdentifierId) == false).ToList(); foreach (var item in deleteLocally) { await item.Delete(new DeleteOptions() { DeleteFileLocation = true }); } } var i = 1; foreach (var media in mediaItems) { progress.Report((i / mediaItems.Count) * 100); var vodItem = (VodMovie)media.ToVodItem(); try { var existingMediaItem = existingMediaItems.FirstOrDefault(m => m.IdentifierId == vodItem.IdentifierId); if (existingMediaItem != null) { // UPDATE _logger.Debug("{0}: found item with id {1} and identifier {2}, updating...", playlist.Name, existingMediaItem.Id, existingMediaItem.IdentifierId); await existingMediaItem.Merge(vodItem); await RefreshMetaData(vodItem, cancellationToken).ConfigureAwait(false); } else { // CREATE _logger.Debug("{0}: media {1} with identifier {2} not found, adding...", playlist.Name, vodItem.Name, vodItem.IdentifierId); vodItem.Id = _libraryManager.GetNewItemId(vodItem.IdentifierId.ToString(), typeof(VodMovie)); await playlist.AddChild(vodItem, cancellationToken).ConfigureAwait(false); await RefreshMetaData(vodItem, cancellationToken).ConfigureAwait(false); await vodItem.RefreshMetadata(cancellationToken).ConfigureAwait(false); } } catch (Exception e) { _logger.ErrorException(e.Message, e); } i++; } progress.Report(100); }