diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations/Channels')
| -rw-r--r-- | MediaBrowser.Server.Implementations/Channels/ChannelItemImageProvider.cs | 87 | ||||
| -rw-r--r-- | MediaBrowser.Server.Implementations/Channels/ChannelManager.cs | 257 |
2 files changed, 344 insertions, 0 deletions
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelItemImageProvider.cs b/MediaBrowser.Server.Implementations/Channels/ChannelItemImageProvider.cs new file mode 100644 index 000000000..23504aaaa --- /dev/null +++ b/MediaBrowser.Server.Implementations/Channels/ChannelItemImageProvider.cs @@ -0,0 +1,87 @@ +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Channels +{ + public class ChannelItemImageProvider : IDynamicImageProvider, IHasChangeMonitor + { + private readonly IHttpClient _httpClient; + private readonly ILogger _logger; + + public ChannelItemImageProvider(IHttpClient httpClient, ILogger logger) + { + _httpClient = httpClient; + _logger = logger; + } + + public IEnumerable<ImageType> GetSupportedImages(IHasImages item) + { + return new[] { ImageType.Primary }; + } + + public async Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken) + { + var channelItem = (IChannelItem)item; + + var imageResponse = new DynamicImageResponse(); + + if (!string.IsNullOrEmpty(channelItem.OriginalImageUrl)) + { + var options = new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = channelItem.OriginalImageUrl + }; + + var response = await _httpClient.GetResponse(options).ConfigureAwait(false); + + if (response.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)) + { + imageResponse.HasImage = true; + imageResponse.Stream = response.Content; + imageResponse.SetFormatFromMimeType(response.ContentType); + } + else + { + _logger.Error("Provider did not return an image content type."); + } + } + + return imageResponse; + } + + public string Name + { + get { return "Channel Image Provider"; } + } + + public bool Supports(IHasImages item) + { + return item is IChannelItem; + } + + public int Order + { + get { return 0; } + } + + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + { + var channelItem = item as IChannelItem; + + if (channelItem != null) + { + return !channelItem.HasImage(ImageType.Primary) && !string.IsNullOrWhiteSpace(channelItem.OriginalImageUrl); + } + return false; + } + } +} diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs new file mode 100644 index 000000000..630c7373e --- /dev/null +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -0,0 +1,257 @@ +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Channels; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Querying; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Channels +{ + public class ChannelManager : IChannelManager + { + private IChannel[] _channels; + private List<Channel> _channelEntities = new List<Channel>(); + + private readonly IUserManager _userManager; + private readonly IDtoService _dtoService; + private readonly ILibraryManager _libraryManager; + private readonly ILogger _logger; + private readonly IServerConfigurationManager _config; + private readonly IFileSystem _fileSystem; + + public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem) + { + _userManager = userManager; + _dtoService = dtoService; + _libraryManager = libraryManager; + _logger = logger; + _config = config; + _fileSystem = fileSystem; + } + + public void AddParts(IEnumerable<IChannel> channels) + { + _channels = channels.ToArray(); + } + + public Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken) + { + var user = string.IsNullOrWhiteSpace(query.UserId) + ? null + : _userManager.GetUserById(new Guid(query.UserId)); + + var channels = _channelEntities.OrderBy(i => i.SortName).ToList(); + + if (user != null) + { + channels = channels.Where(i => GetChannelProvider(i).IsEnabledFor(user) && i.IsVisible(user)) + .ToList(); + } + + // Get everything + var fields = Enum.GetNames(typeof(ItemFields)) + .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)) + .ToList(); + + var returnItems = channels.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) + .ToArray(); + + var result = new QueryResult<BaseItemDto> + { + Items = returnItems, + TotalRecordCount = returnItems.Length + }; + + return Task.FromResult(result); + } + + public async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken) + { + var allChannelsList = _channels.ToList(); + + var list = new List<Channel>(); + + var numComplete = 0; + + foreach (var channelInfo in allChannelsList) + { + cancellationToken.ThrowIfCancellationRequested(); + + try + { + var item = await GetChannel(channelInfo, cancellationToken).ConfigureAwait(false); + + list.Add(item); + + _libraryManager.RegisterItem(item); + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + _logger.ErrorException("Error getting channel information for {0}", ex, channelInfo.Name); + } + + numComplete++; + double percent = numComplete; + percent /= allChannelsList.Count; + + progress.Report(100 * percent); + } + + _channelEntities = list.ToList(); + progress.Report(100); + } + + private async Task<Channel> GetChannel(IChannel channelInfo, CancellationToken cancellationToken) + { + var path = Path.Combine(_config.ApplicationPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(channelInfo.Name)); + + var fileInfo = new DirectoryInfo(path); + + var isNew = false; + + if (!fileInfo.Exists) + { + _logger.Debug("Creating directory {0}", path); + + Directory.CreateDirectory(path); + fileInfo = new DirectoryInfo(path); + + if (!fileInfo.Exists) + { + throw new IOException("Path not created: " + path); + } + + isNew = true; + } + + var id = GetInternalChannelId(channelInfo.Name); + + var item = _libraryManager.GetItemById(id) as Channel; + + if (item == null) + { + item = new Channel + { + Name = channelInfo.Name, + Id = id, + DateCreated = _fileSystem.GetCreationTimeUtc(fileInfo), + DateModified = _fileSystem.GetLastWriteTimeUtc(fileInfo), + Path = path + }; + + isNew = true; + } + + item.HomePageUrl = channelInfo.HomePageUrl; + item.OriginalChannelName = channelInfo.Name; + + if (string.IsNullOrEmpty(item.Name)) + { + item.Name = channelInfo.Name; + } + + await item.RefreshMetadata(new MetadataRefreshOptions + { + ForceSave = isNew + + }, cancellationToken); + + return item; + } + + private Guid GetInternalChannelId(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentNullException("name"); + } + + return ("Channel " + name).GetMBId(typeof(Channel)); + } + + public async Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken) + { + var user = string.IsNullOrWhiteSpace(query.UserId) + ? null + : _userManager.GetUserById(new Guid(query.UserId)); + + var id = new Guid(query.ChannelId); + var channel = _channelEntities.First(i => i.Id == id); + var channelProvider = GetChannelProvider(channel); + + var items = await GetChannelItems(channelProvider, user, query.CategoryId, cancellationToken) + .ConfigureAwait(false); + + + return await GetReturnItems(items, user, query.StartIndex, query.Limit, cancellationToken).ConfigureAwait(false); + } + + private Task<IEnumerable<ChannelItemInfo>> GetChannelItems(IChannel channel, User user, string categoryId, CancellationToken cancellationToken) + { + // TODO: Put some caching in here + + if (string.IsNullOrWhiteSpace(categoryId)) + { + return channel.GetChannelItems(user, cancellationToken); + } + + return channel.GetChannelItems(categoryId, user, cancellationToken); + } + + private async Task<QueryResult<BaseItemDto>> GetReturnItems(IEnumerable<ChannelItemInfo> items, User user, int? startIndex, int? limit, CancellationToken cancellationToken) + { + if (startIndex.HasValue) + { + items = items.Skip(startIndex.Value); + } + if (limit.HasValue) + { + items = items.Take(limit.Value); + } + + // Get everything + var fields = Enum.GetNames(typeof(ItemFields)) + .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)) + .ToList(); + + var tasks = items.Select(GetChannelItemEntity); + + var returnItems = await Task.WhenAll(tasks).ConfigureAwait(false); + + var returnItemArray = returnItems.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) + .ToArray(); + + return new QueryResult<BaseItemDto> + { + Items = returnItemArray, + TotalRecordCount = returnItems.Length + }; + } + + private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info) + { + return null; + } + + private IChannel GetChannelProvider(Channel channel) + { + return _channels.First(i => string.Equals(i.Name, channel.OriginalChannelName, StringComparison.OrdinalIgnoreCase)); + } + } +} |
