private async Task<ChannelItemResult> GetChannelItemsInternal(string userId, CancellationToken cancellationToken) { var items = new List<ChannelItemInfo>(); foreach (var s in Plugin.Instance.Configuration.Bookmarks .Where(i => string.Equals(i.UserId, userId, StringComparison.OrdinalIgnoreCase))) { var item = new ChannelItemInfo { Name = s.Name, ImageUrl = s.Image, Id = s.Name, Type = ChannelItemType.Media, ContentType = ChannelMediaContentType.Clip, MediaType = ChannelMediaType.Video, MediaSources = new List<ChannelMediaInfo> { new ChannelMediaInfo { Path = s.Path, Protocol = s.Protocol } } }; items.Add(item); } return new ChannelItemResult { Items = items.ToList() }; }
public static ChannelItemInfo CreateFolderItem(string title, string id, string url, ChannelItemInfo child) { var folder = new ChannelItemInfo(); folder.FolderType = MediaBrowser.Model.Channels.ChannelFolderType.Container; folder.Type = ChannelItemType.Folder; folder.Name = title; folder.Id = string.Format("{0}_{1}", id, url); if (child != null) folder.ImageUrl = child.ImageUrl; return folder; }
private DateTime GetDateCreatedForSorting(ChannelItemInfo item) { var date = item.DateCreated; if (date.HasValue) { // Strip out the time portion in case they were all added at the same time // This will allow premiere date to take over return date.Value.Date; } return DateTime.MinValue; }
private async Task<ChannelItemResult> GetChannelItemsInternal(string userId, CancellationToken cancellationToken) { var user = string.IsNullOrEmpty(userId) ? null : _user.GetUserById(userId); var items = new List<ChannelItemInfo>(); foreach (var s in Plugin.Instance.Configuration.Bookmarks) { // Until we have user configuration in the UI, we have to disable this. //if (!string.Equals(s.UserId, userId, StringComparison.OrdinalIgnoreCase)) //{ // continue; //} if ( (user.Policy.MaxParentalRating.HasValue && user.Policy.MaxParentalRating >= s.ParentalRating) || (!user.Policy.MaxParentalRating.HasValue) ) { var item = new ChannelItemInfo { Name = s.Name, ImageUrl = s.Image, Id = s.Name, Type = ChannelItemType.Media, ContentType = ChannelMediaContentType.Clip, MediaType = ChannelMediaType.Video, MediaSources = new List<ChannelMediaInfo> { new ChannelMediaInfo { Path = s.Path, Protocol = s.Protocol } } }; items.Add(item); } } return new ChannelItemResult { Items = items.ToList() }; }
private async Task<ChannelItemResult> GetChannels(CancellationToken cancellationToken) { var items = new List<ChannelItemInfo>(); if (!Plugin.Instance.Registration.IsValid) { Plugin.Logger.Warn("PodCasts trial has expired."); return new ChannelItemResult { Items = items.ToList() }; } foreach (var feedUrl in Plugin.Instance.Configuration.Feeds) { var feed = await new RssFeed().GetFeed(_providerManager, _httpClient, feedUrl, cancellationToken).ConfigureAwait(false); _logger.Debug(feedUrl); var item = new ChannelItemInfo { Name = feed.Title == null ? null : feed.Title.Text, Overview = feed.Description == null ? null : feed.Description.Text, Id = feedUrl, Type = ChannelItemType.Folder }; if (feed.ImageUrl != null) { item.ImageUrl = feed.ImageUrl.AbsoluteUri; } items.Add(item); } return new ChannelItemResult { Items = items.ToList() }; }
private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info) { BaseItem item; Guid id; if (info.Type == ChannelItemType.Category) { id = info.Id.GetMBId(typeof(ChannelCategoryItem)); item = new ChannelCategoryItem(); } else if (info.MediaType == ChannelMediaType.Audio) { id = info.Id.GetMBId(typeof(ChannelCategoryItem)); item = new ChannelAudioItem(); } else { id = info.Id.GetMBId(typeof(ChannelVideoItem)); item = new ChannelVideoItem(); } item.Id = id; item.Name = info.Name; item.Genres = info.Genres; item.CommunityRating = info.CommunityRating; item.OfficialRating = info.OfficialRating; item.Overview = info.Overview; item.People = info.People; item.PremiereDate = info.PremiereDate; item.ProductionYear = info.ProductionYear; item.RunTimeTicks = info.RunTimeTicks; item.ProviderIds = info.ProviderIds; return item; }
private async Task<ChannelItemResult> GetChannels(CancellationToken cancellationToken) { var items = new List<ChannelItemInfo>(); if (!Plugin.Instance.Registration.IsValid) { Plugin.Logger.Warn("PodCasts trial has expired."); await _notificationManager.SendNotification(new NotificationRequest { Description = "PodCasts trial has expired.", Date = DateTime.Now, Level = NotificationLevel.Warning, SendToUserMode = SendToUserType.Admins }, cancellationToken); return new ChannelItemResult { Items = items.ToList() }; } foreach (var feedUrl in Plugin.Instance.Configuration.Feeds) { try { var options = new HttpRequestOptions { Url = feedUrl, CancellationToken = cancellationToken, // Seeing some deflate stream errors EnableHttpCompression = false }; using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) { using (var reader = new StreamReader(stream)) { XDocument document = XDocument.Parse(reader.ReadToEnd()); var root = document.Root.Element("channel"); var item = new ChannelItemInfo { Name = GetValue(root, "title"), Overview = GetValue(root, "description"), Id = feedUrl, Type = ChannelItemType.Folder }; if (!string.IsNullOrWhiteSpace(item.Name)) { _logger.Debug("Found rss channel: {0}", item.Name); var imageElement = root.Element("image"); if (imageElement != null) { item.ImageUrl = GetValue(imageElement, "url"); } items.Add(item); } } } } catch (Exception ex) { _logger.ErrorException("Error getting feed", ex); } } return new ChannelItemResult { Items = items.ToList() }; }
private async Task TestItem(ChannelItemInfo item, ListingResults results, CancellationToken cancellationToken) { foreach (var media in (item.MediaSources ?? new List<ChannelMediaInfo>())) { try { await TestMediaInfo(media, results, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.ErrorException("Error testing media info", ex); } } }
private async Task<IEnumerable<ChannelItemInfo>> GetChannelItemsInternal(string feedUrl, CancellationToken cancellationToken) { var items = new List<ChannelItemInfo>(); var rssItems = await new RssFeed().Refresh(_providerManager, _httpClient, feedUrl, cancellationToken).ConfigureAwait(false); foreach (var child in rssItems) { var podcast = (IHasRemoteImage)child; var item = new ChannelItemInfo { Name = child.Name, Overview = child.Overview, ImageUrl = podcast.RemoteImagePath ?? "https://raw.githubusercontent.com/MediaBrowser/MediaBrowser.Channels/master/Podcasts/Images/thumb.png", Id = child.Id.ToString("N"), Type = ChannelItemType.Media, ContentType = ChannelMediaContentType.Podcast, MediaType = child is Video ? ChannelMediaType.Video : ChannelMediaType.Audio, MediaSources = new List<ChannelMediaInfo> { new ChannelMediaInfo { Path = child.Path } }, DateCreated = child.DateCreated, PremiereDate = child.PremiereDate, RunTimeTicks = child.RunTimeTicks, OfficialRating = child.OfficialRating }; items.Add(item); } return items; }
public async Task<IEnumerable<ChannelItemInfo>> GetChannelItems(CancellationToken cancellationToken) { var hdTrailers = await TrailerListingDownloader.GetTrailerList(_logger, true, cancellationToken) .ConfigureAwait(false); var sdTrailers = await TrailerListingDownloader.GetTrailerList(_logger, false, cancellationToken) .ConfigureAwait(false); var list = new List<ChannelItemInfo>(); foreach (var i in hdTrailers) { // Avoid duplicates if (list.Any(l => string.Equals(i.Name, l.Name, StringComparison.OrdinalIgnoreCase))) { continue; } var channelItem = new ChannelItemInfo { CommunityRating = i.CommunityRating, ContentType = ChannelMediaContentType.Trailer, Genres = i.Genres, ImageUrl = i.HdImageUrl ?? i.ImageUrl, IsInfiniteStream = false, MediaType = ChannelMediaType.Video, Name = i.Name, OfficialRating = i.OfficialRating, Overview = i.Overview, People = i.People, Type = ChannelItemType.Media, Id = i.TrailerUrl.GetMD5().ToString("N"), PremiereDate = i.PremiereDate, ProductionYear = i.ProductionYear, Studios = i.Studios, RunTimeTicks = i.RunTimeTicks, DateCreated = i.PostDate, MediaSources = new List<ChannelMediaInfo> { GetMediaInfo(i, true) } }; var sdVersion = sdTrailers .FirstOrDefault(l => string.Equals(i.Name, l.Name, StringComparison.OrdinalIgnoreCase)); if (sdVersion != null) { channelItem.MediaSources.Add(GetMediaInfo(sdVersion, false)); } list.Add(channelItem); } return list; }
private async Task<ChannelItemInfo> GetTrailerFromUrl(string url, TrailerType type, CancellationToken cancellationToken) { var html = await EntryPoint.Instance.GetAndCacheResponse(url, TimeSpan.FromDays(14), cancellationToken) .ConfigureAwait(false); var document = new HtmlDocument(); document.LoadHtml(html); var titleElement = document.DocumentNode.SelectSingleNode("//title"); var name = titleElement == null ? string.Empty : (titleElement.InnerText ?? string.Empty); name = name.Replace("Movie Trailer", string.Empty, StringComparison.OrdinalIgnoreCase) .Replace("Movie-List.com", string.Empty, StringComparison.OrdinalIgnoreCase) .Replace("Movie-List", string.Empty, StringComparison.OrdinalIgnoreCase) .Replace("|", string.Empty, StringComparison.OrdinalIgnoreCase) .Trim(); var posterElement = document.DocumentNode.SelectSingleNode("//a[@rel='prettyPhoto[posters]']//img"); if (posterElement == null) { posterElement = document.DocumentNode.SelectSingleNode("//section[@class='content-box']//img"); } var imageSrc = posterElement == null ? null : posterElement.GetAttributeValue("src", null); var links = document.DocumentNode.SelectNodes("//a"); var linksList = links == null ? new List<HtmlNode>() : links.ToList(); var info = new ChannelItemInfo { ContentType = ChannelMediaContentType.MovieExtra, ExtraType = ExtraType.Trailer, TrailerTypes = new List<TrailerType> { type }, Id = url, MediaType = ChannelMediaType.Video, Type = ChannelItemType.Media, Name = name, ImageUrl = string.IsNullOrWhiteSpace(imageSrc) ? null : (BaseUrl + imageSrc.TrimStart('/')), MediaSources = GetMediaInfo(linksList, html), DateCreated = DateTime.UtcNow }; // For older trailers just rely on core image providers if (TrailerType != TrailerType.ComingSoonToTheaters) { info.ImageUrl = null; } var metadataElements = document.DocumentNode.SelectNodes("//*[contains(@class,'cast-meta')]"); if (metadataElements != null) { foreach (var elem in metadataElements) { FillMetadataFromElement(elem, info); } } var imdbId = GetImdbId(linksList); if (!string.IsNullOrWhiteSpace(imdbId)) { info.SetProviderId(MetadataProviders.Imdb, imdbId); } return info; }
private void FillMetadataFromElement(HtmlNode node, ChannelItemInfo info) { var text = node.InnerText ?? string.Empty; if (text.StartsWith("(", StringComparison.OrdinalIgnoreCase) && text.EndsWith(")", StringComparison.OrdinalIgnoreCase)) { //var studio = text.Trim('(').Trim(')'); //if (!string.IsNullOrWhiteSpace(studio)) //{ // info.Studios.Add(studio); //} } else if (text.StartsWith("Director:", StringComparison.OrdinalIgnoreCase)) { //info.People.AddRange(GetTextFromSubNodes(node, "span").Select(i => new PersonInfo //{ // Name = i, // Type = PersonType.Director //})); } else if (text.StartsWith("Writer:", StringComparison.OrdinalIgnoreCase)) { //info.People.AddRange(GetTextFromSubNodes(node, "span").Select(i => new PersonInfo //{ // Name = i, // Type = PersonType.Writer //})); } else if (text.StartsWith("Genre:", StringComparison.OrdinalIgnoreCase)) { //info.Genres.AddRange(GetTextFromSubNodes(node, "span")); } else if (text.StartsWith("Plot:", StringComparison.OrdinalIgnoreCase)) { //info.Overview = GetTextFromSubNodes(node, "span").FirstOrDefault(); } else if (text.StartsWith("Cast:", StringComparison.OrdinalIgnoreCase)) { //info.People.AddRange(GetTextFromSubNodes(node, "a").Select(i => new PersonInfo //{ // Name = i, // Type = PersonType.Actor //})); } else { text = GetTextFromSubNodes(node, "span") .FirstOrDefault() ?? string.Empty; DateTime dateAdded; if (DateTime.TryParse(text, out dateAdded)) { info.DateCreated = DateTime.SpecifyKind(dateAdded, DateTimeKind.Utc); } } }
private static ChannelItemInfo ParsePlayableArticle(HtmlNode node, bool abroadOnly) { var mobile = node.Attributes["data-mobile"] != null ? node.Attributes["data-mobile"].Value == "true" : false; if (!mobile) return null; var abroad = node.Attributes["data-abroad"] != null ? node.Attributes["data-abroad"].Value == "true" : false; if (abroadOnly && !abroad) return null; var info = new ChannelItemInfo(); info.Type = ChannelItemType.Media; info.MediaType = MediaBrowser.Model.Channels.ChannelMediaType.Video; info.IsInfiniteStream = false; info.Name = node.Attributes["data-title"] != null ? node.Attributes["data-title"].Value : ""; info.Overview = node.Attributes["data-description"] != null ? node.Attributes["data-description"].Value : ""; if (node.Attributes["data-length"] != null) { try { //Time is not supplied in proper format int total = 0; var lenght = node.Attributes["data-length"].Value; var split = lenght.Split(new[] { "h", "min" }, 3, StringSplitOptions.RemoveEmptyEntries); if (split.Length > 1) { total += int.Parse(split[0]) * 60; total += int.Parse(split[1]); } else { total += int.Parse(split[0]); } info.RunTimeTicks = TimeSpan.FromMinutes(total).Ticks; } catch { } } var a = node.SelectSingleNode(".//a[contains(@class, 'play_videolist-element__link')]"); if (a == null || a.Attributes["href"] == null) return null; info.Id = a.Attributes["href"].Value; info.MediaSources = new List<ChannelMediaInfo>(); info.MediaSources.Add(new ChannelMediaInfo { Path = a.Attributes["href"].Value }); var img = node.SelectSingleNode(".//img[contains(@class, 'play_videolist__thumbnail')]"); if (img != null && img.Attributes["src"] != null) { var imagesource = img.Attributes["src"].Value; if (imagesource.Contains("ALTERNATES/extralarge_imax/")) { info.ImageUrl = imagesource.Replace("extralarge_imax/", "medium/"); } else { info.ImageUrl = imagesource; } } //info.MediaSources = (await GetChannelItemMediaInfo(info.Id, CancellationToken.None)).ToList(); return info; }
private static ChannelItemInfo ParseFolderArticle(HtmlNode node) { var info = new ChannelItemInfo(); info.FolderType = MediaBrowser.Model.Channels.ChannelFolderType.Container; info.Type = ChannelItemType.Folder; var nameNode = node.SelectSingleNode(".//h2[contains(@class, 'play_h4')]"); info.Name = nameNode != null ? nameNode.InnerText : ""; var a = node.SelectSingleNode(".//a[contains(@class, 'play_videolist-element__link')]"); if (a == null || a.Attributes["href"] == null) return null; info.Id = a.Attributes["href"].Value; var img = node.SelectSingleNode(".//img"); if (img != null && img.Attributes["src"] != null) { var imgsource = img.Attributes["src"].Value; if (!imgsource.StartsWith("http://")) info.ImageUrl = "http://www.svtplay.se" + imgsource; else info.ImageUrl = imgsource; } return info; }
private async Task FillMetadata(ChannelItemInfo item, List<TrailerMetadata> metadataList, CancellationToken cancellationToken) { var imdbId = item.GetProviderId(MetadataProviders.Imdb); TrailerMetadata metadata = null; if (!string.IsNullOrWhiteSpace(imdbId)) { metadata = metadataList.FirstOrDefault(i => string.Equals(imdbId, i.GetProviderId(MetadataProviders.Imdb), StringComparison.OrdinalIgnoreCase)); } if (metadata == null) { var tmdbId = item.GetProviderId(MetadataProviders.Tmdb); if (!string.IsNullOrWhiteSpace(tmdbId)) { metadata = metadataList.FirstOrDefault(i => string.Equals(tmdbId, i.GetProviderId(MetadataProviders.Tmdb), StringComparison.OrdinalIgnoreCase)); } } if (metadata == null) { var searchResults = await _providerManager.GetRemoteSearchResults<Movie, MovieInfo>(new RemoteSearchQuery<MovieInfo> { IncludeDisabledProviders = true, SearchInfo = new MovieInfo { Name = item.Name, Year = item.ProductionYear, ProviderIds = item.ProviderIds } }, cancellationToken).ConfigureAwait(false); var result = searchResults.FirstOrDefault(); if (result != null) { metadata = new TrailerMetadata { Name = result.Name, PremiereDate = result.PremiereDate, ProductionYear = result.ProductionYear, ProviderIds = result.ProviderIds }; metadataList.Add(metadata); } } if (metadata != null) { item.Name = metadata.Name ?? item.Name; item.ProductionYear = metadata.ProductionYear ?? item.ProductionYear; item.PremiereDate = metadata.PremiereDate ?? item.PremiereDate; // Merge provider id's foreach (var id in metadata.ProviderIds) { item.SetProviderId(id.Key, id.Value); } } }
private async Task<IEnumerable<ChannelItemInfo>> GetVideoListing(String type, String request, String genre, InternalChannelItemQuery query, CancellationToken cancellationToken) { var offset = query.StartIndex.GetValueOrDefault(); var items = new List<ChannelItemInfo>(); var url = ""; Info.VideoList info; if (type == "video") { url = String.Format( "http://api.vevo.com/mobile/v1/video/list.json?max={0}&offset={1}&extended=true", query.Limit, offset); if (genre != "nogenre") url = url + "&genre=" + genre; if (request != "norequest") url = url + "&order=" + request; } else { url = String.Format( "http://api.vevo.com/mobile/v1/artist/{0}/videos.json?max={1}&extended=true", request, query.Limit); } using (var site = await _httpClient.Get(url, CancellationToken.None).ConfigureAwait(false)) { info = _jsonSerializer.DeserializeFromStream<Info.VideoList>(site); foreach (var i in info.result) { var artists = i.artists_main; var featuredArtists = i.artists_featured; var item = new ChannelItemInfo { Name = i.title, ImageUrl = i.image_url, RunTimeTicks = TimeSpan.FromSeconds(i.duration_in_seconds).Ticks, Id = i.isrc, Type = ChannelItemType.Media, ContentType = ChannelMediaContentType.Clip, MediaType = ChannelMediaType.Video, DateCreated = DateTime.Parse(i.created_at) }; var overview = ""; if (artists.Count == 1) { overview = "Artist: " + artists[0].name; } else if (artists.Count > 1) { overview = "Artists: "; foreach (var a in artists) { overview = overview + a.name + ", "; } // Strip last , } if (featuredArtists.Count > 0) { overview = "\nFeaturing: "; foreach (var a in featuredArtists) { overview = overview + a.name + ", "; } // Strip last , } if (overview != "") item.Overview = overview; items.Add(item); } if (request == "MostRecent") { items = items.OrderByDescending(i => i.DateCreated).ToList(); } } return items; }
private bool Filter(ChannelItemInfo item, ListingResults results) { item.MediaSources = item.MediaSources .Where(i => Filter(i, results)) .ToList(); return item.MediaSources.Count > 0; }
private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, CancellationToken cancellationToken) { BaseItem item; Guid id; var isNew = false; var idToHash = GetIdToHash(info.Id, channelProvider); if (info.Type == ChannelItemType.Folder) { id = idToHash.GetMBId(typeof(ChannelFolderItem)); item = _libraryManager.GetItemById(id) as ChannelFolderItem; if (item == null) { isNew = true; item = new ChannelFolderItem(); } } else if (info.MediaType == ChannelMediaType.Audio) { id = idToHash.GetMBId(typeof(ChannelAudioItem)); item = _libraryManager.GetItemById(id) as ChannelAudioItem; if (item == null) { isNew = true; item = new ChannelAudioItem(); } } else { id = idToHash.GetMBId(typeof(ChannelVideoItem)); item = _libraryManager.GetItemById(id) as ChannelVideoItem; if (item == null) { isNew = true; item = new ChannelVideoItem(); } } item.Id = id; item.RunTimeTicks = info.RunTimeTicks; if (isNew) { item.Name = info.Name; item.Genres = info.Genres; item.Studios = info.Studios; item.CommunityRating = info.CommunityRating; item.OfficialRating = info.OfficialRating; item.Overview = info.Overview; item.IndexNumber = info.IndexNumber; item.ParentIndexNumber = info.ParentIndexNumber; item.People = info.People; item.PremiereDate = info.PremiereDate; item.ProductionYear = info.ProductionYear; item.ProviderIds = info.ProviderIds; item.DateCreated = info.DateCreated.HasValue ? info.DateCreated.Value : DateTime.UtcNow; } var channelItem = (IChannelItem)item; channelItem.OriginalImageUrl = info.ImageUrl; channelItem.ExternalId = info.Id; channelItem.ChannelId = internalChannelId.ToString("N"); channelItem.ChannelItemType = info.Type; if (isNew) { channelItem.Tags = info.Tags; } var channelMediaItem = item as IChannelMediaItem; if (channelMediaItem != null) { channelMediaItem.ContentType = info.ContentType; channelMediaItem.ChannelMediaSources = info.MediaSources; var mediaSource = info.MediaSources.FirstOrDefault(); item.Path = mediaSource == null ? null : mediaSource.Path; item.DisplayMediaType = channelMediaItem.ContentType.ToString(); } if (isNew) { await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); _libraryManager.RegisterItem(item); } return item; }
private async Task<ChannelItemInfo> GetTrailerFromUrl(string url, TrailerType type, CancellationToken cancellationToken) { var html = await EntryPoint.Instance.GetAndCacheResponse(url, TimeSpan.FromDays(14), cancellationToken) .ConfigureAwait(false); var document = new HtmlDocument(); document.LoadHtml(html); var titleElement = document.DocumentNode.SelectSingleNode("//h1"); var links = document.DocumentNode.SelectNodes("//a"); var linksList = links == null ? new List<HtmlNode>() : links.ToList(); var info = new ChannelItemInfo { ContentType = ChannelMediaContentType.MovieExtra, ExtraType = ExtraType.Trailer, TrailerTypes = new List<TrailerType> { type }, Id = url, MediaType = ChannelMediaType.Video, Type = ChannelItemType.Media, Name = titleElement == null ? null : titleElement.InnerText, MediaSources = GetMediaInfo(linksList, html), DateCreated = DateTime.UtcNow }; // For older trailers just rely on core image providers if (TrailerType != TrailerType.ComingSoonToTheaters) { info.ImageUrl = null; } return info; }