private async Task<LiveTvRecording> GetRecording(RecordingInfo info, string serviceName, CancellationToken cancellationToken)
        {
            var isNew = false;

            var id = _tvDtoService.GetInternalRecordingId(serviceName, info.Id);

            var item = _itemRepo.RetrieveItem(id) as LiveTvRecording;

            if (item == null)
            {
                item = new LiveTvRecording
                {
                    Name = info.Name,
                    Id = id,
                    DateCreated = DateTime.UtcNow,
                    DateModified = DateTime.UtcNow
                };

                isNew = true;
            }

            item.RecordingInfo = info;
            item.ServiceName = serviceName;

            await item.RefreshMetadata(cancellationToken, forceSave: isNew, resetResolveArgs: false);

            return item;
        }
        public RecordingInfoDto GetRecordingInfoDto(LiveTvRecording recording, LiveTvChannel channel, ILiveTvService service, User user = null)
        {
            var info = recording.RecordingInfo;
            
            var dto = new RecordingInfoDto
            {
                Id = GetInternalRecordingId(service.Name, info.Id).ToString("N"),
                SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) ? null : GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"),
                Type = recording.GetClientTypeName(),
                Overview = info.Overview,
                EndDate = info.EndDate,
                Name = info.Name,
                StartDate = info.StartDate,
                ExternalId = info.Id,
                ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"),
                Status = info.Status,
                Path = info.Path,
                Genres = info.Genres,
                IsRepeat = info.IsRepeat,
                EpisodeTitle = info.EpisodeTitle,
                ChannelType = info.ChannelType,
                MediaType = info.ChannelType == ChannelType.Radio ? MediaType.Audio : MediaType.Video,
                CommunityRating = GetClientCommunityRating(info.CommunityRating),
                OfficialRating = info.OfficialRating,
                Audio = info.Audio,
                IsHD = info.IsHD,
                ServiceName = service.Name,
                Url = info.Url,
                IsMovie = info.IsMovie,
                IsSeries = info.IsSeries,
                IsSports = info.IsSports,
                IsLive = info.IsLive,
                IsNews = info.IsNews,
                IsKids = info.IsKids,
                IsPremiere = info.IsPremiere,
                RunTimeTicks = (info.EndDate - info.StartDate).Ticks
            };

            var imageTag = GetImageTag(recording);

            if (imageTag.HasValue)
            {
                dto.ImageTags[ImageType.Primary] = imageTag.Value;
            }

            if (user != null)
            {
                dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, recording.GetUserDataKey()));
            }

            if (!string.IsNullOrEmpty(info.ProgramId))
            {
                dto.ProgramId = GetInternalProgramId(service.Name, info.ProgramId).ToString("N");
            }

            if (channel != null)
            {
                dto.ChannelName = channel.ChannelInfo.Name;
            }
            
            return dto;
        }
        private async Task<bool> DownloadImage(LiveTvRecording item, CancellationToken cancellationToken)
        {
            var recordingInfo = item.RecordingInfo;

            Stream imageStream = null;
            string contentType = null;

            if (!string.IsNullOrEmpty(recordingInfo.ImagePath))
            {
                contentType = "image/" + Path.GetExtension(recordingInfo.ImagePath).ToLower();
                imageStream = _fileSystem.GetFileStream(recordingInfo.ImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true);
            }
            else if (!string.IsNullOrEmpty(recordingInfo.ImageUrl))
            {
                var options = new HttpRequestOptions
                {
                    CancellationToken = cancellationToken,
                    Url = recordingInfo.ImageUrl
                };

                var response = await _httpClient.GetResponse(options).ConfigureAwait(false);

                if (!response.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
                {
                    Logger.Error("Provider did not return an image content type.");
                    return false;
                }

                imageStream = response.Content;
                contentType = response.ContentType;
            }
            else if (recordingInfo.HasImage ?? true)
            {
                var service = _liveTvManager.Services.FirstOrDefault(i => string.Equals(i.Name, item.ServiceName, StringComparison.OrdinalIgnoreCase));

                if (service != null)
                {
                    try
                    {
                        var response = await service.GetRecordingImageAsync(recordingInfo.Id, cancellationToken).ConfigureAwait(false);

                        if (response != null)
                        {
                            imageStream = response.Stream;
                            contentType = response.MimeType;
                        }
                    }
                    catch (NotImplementedException)
                    {
                        return false;
                    }
                }
            }

            if (imageStream != null)
            {
                // Dummy up the original url
                var url = item.ServiceName + recordingInfo.Id;

                await _providerManager.SaveImage(item, imageStream, contentType, ImageType.Primary, null, url, cancellationToken).ConfigureAwait(false);
                return true;
            }

            return false;
        }