Example #1
0
        /// <summary>
        /// Ensures the list.
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <param name="file">The file.</param>
        /// <param name="httpClient">The HTTP client.</param>
        /// <param name="fileSystem">The file system.</param>
        /// <param name="semaphore">The semaphore.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        public static async Task EnsureList(string url, string file, IHttpClient httpClient, IFileSystem fileSystem, SemaphoreSlim semaphore, CancellationToken cancellationToken)
        {
            var fileInfo = fileSystem.GetFileInfo(file);

            if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1)
            {
                await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

                try
                {
                    var temp = await httpClient.GetTempFile(new HttpRequestOptions
                    {
                        CancellationToken = cancellationToken,
                        Progress = new Progress<double>(),
                        Url = url

                    }).ConfigureAwait(false);

					fileSystem.CreateDirectory(Path.GetDirectoryName(file));

					fileSystem.CopyFile(temp, file, true);
                }
                finally
                {
                    semaphore.Release();
                }
            }
        }
Example #2
0
        /// <summary>
        /// Sets the initial item values.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="parent">The parent.</param>
        /// <param name="fileSystem">The file system.</param>
        /// <param name="libraryManager">The library manager.</param>
        /// <param name="directoryService">The directory service.</param>
        /// <exception cref="System.ArgumentException">Item must have a path</exception>
        public static void SetInitialItemValues(BaseItem item, Folder parent, IFileSystem fileSystem, ILibraryManager libraryManager, IDirectoryService directoryService)
        {
            // This version of the below method has no ItemResolveArgs, so we have to require the path already being set
            if (string.IsNullOrWhiteSpace(item.Path))
            {
                throw new ArgumentException("Item must have a Path");
            }

            // If the resolver didn't specify this
            if (parent != null)
            {
                item.Parent = parent;
            }

            item.Id = libraryManager.GetNewItemId(item.Path, item.GetType());

            item.IsLocked = item.Path.IndexOf("[dontfetchmeta]", StringComparison.OrdinalIgnoreCase) != -1 ||
                item.Parents.Any(i => i.IsLocked);

            // Make sure DateCreated and DateModified have values
            var fileInfo = directoryService.GetFile(item.Path);
            item.DateModified = fileSystem.GetLastWriteTimeUtc(fileInfo);
            SetDateCreated(item, fileSystem, fileInfo);

            EnsureName(item, fileInfo);
        }
Example #3
0
        /// <inheritdoc />
        public async Task <(string Path, string?MimeType, DateTime DateModified)> ProcessImage(ImageProcessingOptions options)
        {
            ItemImageInfo originalImage = options.Image;
            BaseItem      item          = options.Item;

            string          originalImagePath = originalImage.Path;
            DateTime        dateModified      = originalImage.DateModified;
            ImageDimensions?originalImageSize = null;

            if (originalImage.Width > 0 && originalImage.Height > 0)
            {
                originalImageSize = new ImageDimensions(originalImage.Width, originalImage.Height);
            }

            var mimeType = MimeTypes.GetMimeType(originalImagePath);

            if (!_imageEncoder.SupportsImageEncoding)
            {
                return(originalImagePath, mimeType, dateModified);
            }

            var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);

            originalImagePath = supportedImageInfo.Path;

            // Original file doesn't exist, or original file is gif.
            if (!File.Exists(originalImagePath) || string.Equals(mimeType, MediaTypeNames.Image.Gif, StringComparison.OrdinalIgnoreCase))
            {
                return(originalImagePath, mimeType, dateModified);
            }

            dateModified = supportedImageInfo.DateModified;
            bool requiresTransparency = _transparentImageTypes.Contains(Path.GetExtension(originalImagePath));

            bool             autoOrient  = false;
            ImageOrientation?orientation = null;

            if (item is Photo photo)
            {
                if (photo.Orientation.HasValue)
                {
                    if (photo.Orientation.Value != ImageOrientation.TopLeft)
                    {
                        autoOrient  = true;
                        orientation = photo.Orientation;
                    }
                }
                else
                {
                    // Orientation unknown, so do it
                    autoOrient  = true;
                    orientation = photo.Orientation;
                }
            }

            if (options.HasDefaultOptions(originalImagePath, originalImageSize) && (!autoOrient || !options.RequiresAutoOrientation))
            {
                // Just spit out the original file if all the options are default
                return(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
            }

            int quality = options.Quality;

            ImageFormat outputFormat  = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency);
            string      cacheFilePath = GetCacheFilePath(
                originalImagePath,
                options.Width,
                options.Height,
                options.MaxWidth,
                options.MaxHeight,
                options.FillWidth,
                options.FillHeight,
                quality,
                dateModified,
                outputFormat,
                options.AddPlayedIndicator,
                options.PercentPlayed,
                options.UnplayedCount,
                options.Blur,
                options.BackgroundColor,
                options.ForegroundLayer);

            try
            {
                if (!File.Exists(cacheFilePath))
                {
                    string resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);

                    if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
                    {
                        return(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
                    }
                }

                return(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
            }
            catch (Exception ex)
            {
                // If it fails for whatever reason, return the original image
                _logger.LogError(ex, "Error encoding image");
                return(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
            }
        }
 public DateTime GetLastWriteTimeUtc(string path)
 {
     return(_lastWriteTimeCache.GetOrAdd(path, p => _fileSystem.GetLastWriteTimeUtc(p)));
 }
Example #5
0
        /// <inheritdoc />
        public async Task <(string path, string mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var libraryManager = _libraryManager();

            ItemImageInfo originalImage = options.Image;
            BaseItem      item          = options.Item;

            if (!originalImage.IsLocalFile)
            {
                if (item == null)
                {
                    item = libraryManager.GetItemById(options.ItemId);
                }

                originalImage = await libraryManager.ConvertImageToLocal(item, originalImage, options.ImageIndex).ConfigureAwait(false);
            }

            string          originalImagePath = originalImage.Path;
            DateTime        dateModified      = originalImage.DateModified;
            ImageDimensions?originalImageSize = null;

            if (originalImage.Width > 0 && originalImage.Height > 0)
            {
                originalImageSize = new ImageDimensions(originalImage.Width, originalImage.Height);
            }

            if (!_imageEncoder.SupportsImageEncoding)
            {
                return(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
            }

            var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);

            originalImagePath = supportedImageInfo.path;

            if (!File.Exists(originalImagePath))
            {
                return(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
            }

            dateModified = supportedImageInfo.dateModified;
            bool requiresTransparency = _transparentImageTypes.Contains(Path.GetExtension(originalImagePath));

            bool             autoOrient  = false;
            ImageOrientation?orientation = null;

            if (item is Photo photo)
            {
                if (photo.Orientation.HasValue)
                {
                    if (photo.Orientation.Value != ImageOrientation.TopLeft)
                    {
                        autoOrient  = true;
                        orientation = photo.Orientation;
                    }
                }
                else
                {
                    // Orientation unknown, so do it
                    autoOrient  = true;
                    orientation = photo.Orientation;
                }
            }

            if (options.HasDefaultOptions(originalImagePath, originalImageSize) && (!autoOrient || !options.RequiresAutoOrientation))
            {
                // Just spit out the original file if all the options are default
                return(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
            }

            ImageDimensions newSize = ImageHelper.GetNewImageSize(options, null);
            int             quality = options.Quality;

            ImageFormat outputFormat  = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency);
            string      cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer);

            try
            {
                if (!File.Exists(cacheFilePath))
                {
                    if (options.CropWhiteSpace && !SupportsTransparency(originalImagePath))
                    {
                        options.CropWhiteSpace = false;
                    }

                    string resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);

                    if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
                    {
                        return(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
                    }
                }

                return(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
            }
            catch (Exception ex)
            {
                // If it fails for whatever reason, return the original image
                _logger.LogError(ex, "Error encoding image");
                return(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
            }
        }
Example #6
0
        /// <summary>
        /// Gets the item image infos.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns>Task{List{ImageInfo}}.</returns>
        public List <ImageInfo> GetItemImageInfos(BaseItem item)
        {
            var list = new List <ImageInfo>();

            foreach (var image in item.ImageInfos.Where(i => !item.AllowsMultipleImages(i.Type)))
            {
                var info = GetImageInfo(item, image, null);

                if (info != null)
                {
                    list.Add(info);
                }
            }

            foreach (var imageType in item.ImageInfos.Select(i => i.Type).Distinct().Where(item.AllowsMultipleImages))
            {
                var index = 0;

                // Prevent implicitly captured closure
                var currentImageType = imageType;

                foreach (var image in item.ImageInfos.Where(i => i.Type == currentImageType))
                {
                    var info = GetImageInfo(item, image, index);

                    if (info != null)
                    {
                        list.Add(info);
                    }

                    index++;
                }
            }

            var video = item as Video;

            if (video != null)
            {
                var index = 0;

                foreach (var chapter in _itemRepo.GetChapters(video.Id))
                {
                    if (!string.IsNullOrEmpty(chapter.ImagePath))
                    {
                        var image = chapter.ImagePath;

                        var info = GetImageInfo(item, new ItemImageInfo
                        {
                            Path         = image,
                            Type         = ImageType.Chapter,
                            DateModified = _fileSystem.GetLastWriteTimeUtc(image)
                        }, index);

                        if (info != null)
                        {
                            list.Add(info);
                        }
                    }

                    index++;
                }
            }

            return(list);
        }
Example #7
0
        public async Task <bool> RefreshChapterImages(Video video, IDirectoryService directoryService, List <ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
        {
            if (!IsEligibleForChapterImageExtraction(video))
            {
                extractImages = false;
            }

            var success     = true;
            var changesMade = false;

            var runtimeTicks = video.RunTimeTicks ?? 0;

            var currentImages = GetSavedChapterImages(video, directoryService);

            foreach (var chapter in chapters)
            {
                if (chapter.StartPositionTicks >= runtimeTicks)
                {
                    _logger.Info("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name);
                    break;
                }

                var path = GetChapterImagePath(video, chapter.StartPositionTicks);

                if (!currentImages.Contains(path, StringComparer.OrdinalIgnoreCase))
                {
                    if (extractImages)
                    {
                        try
                        {
                            // Add some time for the first chapter to make sure we don't end up with a black image
                            var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks);

                            var protocol = MediaProtocol.File;

                            var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, new string[] { });

                            _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));

                            var container = video.Container;

                            var tempFile = await _encoder.ExtractVideoImage(inputPath, container, protocol, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false);

                            _fileSystem.CopyFile(tempFile, path, true);

                            try
                            {
                                _fileSystem.DeleteFile(tempFile);
                            }
                            catch
                            {
                            }

                            chapter.ImagePath         = path;
                            chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path);
                            changesMade = true;
                        }
                        catch (Exception ex)
                        {
                            _logger.ErrorException("Error extracting chapter images for {0}", ex, string.Join(",", video.Path));
                            success = false;
                            break;
                        }
                    }
                    else if (!string.IsNullOrEmpty(chapter.ImagePath))
                    {
                        chapter.ImagePath = null;
                        changesMade       = true;
                    }
                }
                else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase))
                {
                    chapter.ImagePath         = path;
                    chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path);
                    changesMade = true;
                }
            }

            if (saveChapters && changesMade)
            {
                _chapterManager.SaveChapters(video.Id.ToString(), chapters);
            }

            DeleteDeadImages(currentImages, chapters);

            return(success);
        }
Example #8
0
        public async Task <Tuple <string, string, DateTime> > ProcessImage(ImageProcessingOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            var        originalImage = options.Image;
            IHasImages item          = options.Item;

            if (!originalImage.IsLocalFile)
            {
                if (item == null)
                {
                    item = _libraryManager().GetItemById(options.ItemId);
                }
                originalImage = await _libraryManager().ConvertImageToLocal(item, originalImage, options.ImageIndex).ConfigureAwait(false);
            }

            var originalImagePath = originalImage.Path;
            var dateModified      = originalImage.DateModified;

            if (!_imageEncoder.SupportsImageEncoding)
            {
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }

            if (options.Enhancers.Count > 0)
            {
                if (item == null)
                {
                    item = _libraryManager().GetItemById(options.ItemId);
                }

                var tuple = await GetEnhancedImage(new ItemImageInfo
                {
                    DateModified = dateModified,
                    Type         = originalImage.Type,
                    Path         = originalImagePath
                }, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false);

                originalImagePath = tuple.Item1;
                dateModified      = tuple.Item2;
            }

            var photo      = item as Photo;
            var autoOrient = false;
            ImageOrientation?orientation = null;

            if (photo != null && photo.Orientation.HasValue && photo.Orientation.Value != ImageOrientation.TopLeft)
            {
                autoOrient  = true;
                orientation = photo.Orientation;
            }

            if (options.HasDefaultOptions(originalImagePath) && !autoOrient)
            {
                // Just spit out the original file if all the options are default
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }

            ImageSize?originalImageSize = GetSavedImageSize(originalImagePath, dateModified);

            if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value) && !autoOrient)
            {
                // Just spit out the original file if all the options are default
                _logger.Info("Returning original image {0}", originalImagePath);
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }

            var newSize = ImageHelper.GetNewImageSize(options, originalImageSize);
            var quality = options.Quality;

            var outputFormat  = GetOutputFormat(options.SupportedOutputFormats[0]);
            var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer);

            try
            {
                CheckDisposed();

                if (!_fileSystem.FileExists(cacheFilePath))
                {
                    var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
                    _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));

                    if (item == null && string.Equals(options.ItemType, typeof(Photo).Name, StringComparison.OrdinalIgnoreCase))
                    {
                        item = _libraryManager().GetItemById(options.ItemId);
                    }

                    var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, tmpPath, autoOrient, orientation, quality, options, outputFormat);

                    if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
                    {
                        return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
                    }

                    _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
                    CopyFile(tmpPath, cacheFilePath);

                    return(new Tuple <string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath)));
                }

                return(new Tuple <string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath)));
            }
            catch (Exception ex)
            {
                // If it fails for whatever reason, return the original image
                _logger.ErrorException("Error encoding image", ex);

                // Just spit out the original file if all the options are default
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }
        }
 /// <summary>
 ///     Gets latest modification time of all dependencies.
 /// </summary>
 /// <returns></returns>
 public DateTime?GetLastModificationTime()
 {
     return(_fileDependencies.Count == 0
         ? (DateTime?)null
         : _fileDependencies.Distinct().Select(fn => _fileSystem.GetLastWriteTimeUtc(fn)).Max());
 }
Example #10
0
        /// <summary>
        /// Runs the specified progress.
        /// </summary>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        public async Task Run(IProgress <double> progress, CancellationToken cancellationToken)
        {
            var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);

            _fileSystem.CreateDirectory(path);

            var timestampFile = Path.Combine(path, "time.txt");

            var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile);

            // Don't check for tvdb updates anymore frequently than 24 hours
            if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
            {
                return;
            }

            // Find out the last time we queried tvdb for updates
            var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;

            string newUpdateTime;

            var existingDirectories = _fileSystem.GetDirectoryPaths(path)
                                      .Select(Path.GetFileName)
                                      .ToList();

            var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
            {
                IncludeItemTypes             = new[] { typeof(Series).Name },
                Recursive                    = true,
                GroupByPresentationUniqueKey = false,
                DtoOptions                   = new DtoOptions(false)
                {
                    EnableImages = false
                }
            }).Cast <Series>()
                             .ToList();

            var seriesIdsInLibrary = seriesList
                                     .Where(i => !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb)))
                                     .Select(i => i.GetProviderId(MetadataProviders.Tvdb))
                                     .ToList();

            var missingSeries = seriesIdsInLibrary.Except(existingDirectories, StringComparer.OrdinalIgnoreCase)
                                .ToList();

            var enableInternetProviders = seriesList.Count == 0 ? false : seriesList[0].IsMetadataFetcherEnabled(_libraryManager.GetLibraryOptions(seriesList[0]), TvdbSeriesProvider.Current.Name);

            if (!enableInternetProviders)
            {
                progress.Report(100);
                return;
            }

            // If this is our first time, update all series
            if (string.IsNullOrEmpty(lastUpdateTime))
            {
                // First get tvdb server time
                using (var response = await _httpClient.SendAsync(new HttpRequestOptions
                {
                    Url = ServerTimeUrl,
                    CancellationToken = cancellationToken,
                    EnableHttpCompression = true,
                    BufferContent = false
                }, "GET").ConfigureAwait(false))
                {
                    // First get tvdb server time
                    using (var stream = response.Content)
                    {
                        newUpdateTime = GetUpdateTime(stream);
                    }
                }

                existingDirectories.AddRange(missingSeries);

                await UpdateSeries(existingDirectories, path, null, progress, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false);

                newUpdateTime = seriesToUpdate.Item2;

                long lastUpdateValue;

                long.TryParse(lastUpdateTime, NumberStyles.Any, UsCulture, out lastUpdateValue);

                var nullableUpdateValue = lastUpdateValue == 0 ? (long?)null : lastUpdateValue;

                var listToUpdate = seriesToUpdate.Item1.ToList();
                listToUpdate.AddRange(missingSeries);

                await UpdateSeries(listToUpdate, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false);
            }

            _fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
            progress.Report(100);
        }
Example #11
0
        public string ReadCachedModule(string filePath)
        {
            if (_skipCache)
            {
                return(string.Empty);
            }

            var cachePath = GetCacheFilePath(filePath);

            if (string.IsNullOrEmpty(cachePath))
            {
                return(string.Empty);
            }

            var       cachedFileExists            = false;
            var       cachedFileOlderThanAssembly = false;
            var       cachedFileOlderThanSource   = false;
            Exception exception = null;

            try {
                cachedFileExists = _fs.FileExists(cachePath);
                if (cachedFileExists)
                {
                    // Source path is fake for scraped/compiled modules.
                    // The time will be very old, which is good.
                    var sourceTime = _fs.GetLastWriteTimeUtc(filePath);
                    var cacheTime  = _fs.GetLastWriteTimeUtc(cachePath);

                    cachedFileOlderThanSource = cacheTime < sourceTime;
                    if (!cachedFileOlderThanSource)
                    {
                        var assemblyTime = _fs.GetLastWriteTimeUtc(GetType().Assembly.Location);
                        if (assemblyTime > cacheTime)
                        {
                            cachedFileOlderThanAssembly = true;
                        }
                        else
                        {
                            return(_fs.ReadTextWithRetry(cachePath));
                        }
                    }
                }
            } catch (Exception ex) when(!ex.IsCriticalException())
            {
                exception = ex;
            }

            var reason = "Unknown";

            if (!cachedFileExists)
            {
                reason = "Cached file does not exist";
            }
            else if (cachedFileOlderThanAssembly)
            {
                reason = "Cached file is older than the assembly.";
            }
            else if (cachedFileOlderThanSource)
            {
                reason = $"Cached file is older than the source {filePath}.";
            }
            else
            {
                reason = $"Exception during cache file check {exception.Message}.";
            }

            _log?.Log(TraceEventType.Verbose, $"Invalidate cached module {cachePath}. Reason: {reason}");
            _fs.DeleteFileWithRetries(cachePath);
            return(string.Empty);
        }
Example #12
0
 private Tuple <string, DateTime> GetResult(string path)
 {
     return(new Tuple <string, DateTime>(path, _fileSystem.GetLastWriteTimeUtc(path)));
 }
Example #13
0
        /// <summary>
        /// Runs the specified progress.
        /// </summary>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        public async Task Run(IProgress <double> progress, CancellationToken cancellationToken)
        {
            if (!_config.Configuration.EnableInternetProviders)
            {
                progress.Report(100);
                return;
            }

            var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase));

            if (seriesConfig != null && seriesConfig.DisabledMetadataFetchers.Contains(TvdbSeriesProvider.Current.Name, StringComparer.OrdinalIgnoreCase))
            {
                progress.Report(100);
                return;
            }

            var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);

            _fileSystem.CreateDirectory(path);

            var timestampFile = Path.Combine(path, "time.txt");

            var timestampFileInfo = _fileSystem.GetFileInfo(timestampFile);

            // Don't check for tvdb updates anymore frequently than 24 hours
            if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
            {
                return;
            }

            // Find out the last time we queried tvdb for updates
            var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;

            string newUpdateTime;

            var existingDirectories = Directory.EnumerateDirectories(path)
                                      .Select(Path.GetFileName)
                                      .ToList();

            var seriesIdsInLibrary = _libraryManager.RootFolder
                                     .GetRecursiveChildren(i => i is Series && !string.IsNullOrEmpty(i.GetProviderId(MetadataProviders.Tvdb)))
                                     .Cast <Series>()
                                     .Select(i => i.GetProviderId(MetadataProviders.Tvdb))
                                     .ToList();

            var missingSeries = seriesIdsInLibrary.Except(existingDirectories, StringComparer.OrdinalIgnoreCase)
                                .ToList();

            // If this is our first time, update all series
            if (string.IsNullOrEmpty(lastUpdateTime))
            {
                // First get tvdb server time
                using (var stream = await _httpClient.Get(new HttpRequestOptions
                {
                    Url = ServerTimeUrl,
                    CancellationToken = cancellationToken,
                    EnableHttpCompression = true,
                    ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
                }).ConfigureAwait(false))
                {
                    newUpdateTime = GetUpdateTime(stream);
                }

                existingDirectories.AddRange(missingSeries);

                await UpdateSeries(existingDirectories, path, null, progress, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false);

                newUpdateTime = seriesToUpdate.Item2;

                long lastUpdateValue;

                long.TryParse(lastUpdateTime, NumberStyles.Any, UsCulture, out lastUpdateValue);

                var nullableUpdateValue = lastUpdateValue == 0 ? (long?)null : lastUpdateValue;

                var listToUpdate = seriesToUpdate.Item1.ToList();
                listToUpdate.AddRange(missingSeries);

                await UpdateSeries(listToUpdate, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false);
            }

            _fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
            progress.Report(100);
        }
Example #14
0
        public async Task <Tuple <string, string, DateTime> > ProcessImage(ImageProcessingOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            var originalImage = options.Image;

            if (!originalImage.IsLocalFile)
            {
                originalImage = await _libraryManager().ConvertImageToLocal(options.Item, originalImage, options.ImageIndex).ConfigureAwait(false);
            }

            var originalImagePath = originalImage.Path;
            var dateModified      = originalImage.DateModified;

            if (!_imageEncoder.SupportsImageEncoding)
            {
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }

            if (options.CropWhiteSpace && _imageEncoder.SupportsImageEncoding)
            {
                var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false);

                originalImagePath = tuple.Item1;
                dateModified      = tuple.Item2;
            }

            if (options.Enhancers.Count > 0)
            {
                var tuple = await GetEnhancedImage(new ItemImageInfo
                {
                    DateModified = dateModified,
                    Type         = originalImage.Type,
                    Path         = originalImagePath
                }, options.Item, options.ImageIndex, options.Enhancers).ConfigureAwait(false);

                originalImagePath = tuple.Item1;
                dateModified      = tuple.Item2;
            }

            if (options.HasDefaultOptions(originalImagePath))
            {
                // Just spit out the original file if all the options are default
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }

            ImageSize?originalImageSize;

            try
            {
                originalImageSize = GetImageSize(originalImagePath, dateModified, true);
                if (options.HasDefaultOptions(originalImagePath, originalImageSize.Value))
                {
                    // Just spit out the original file if all the options are default
                    return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
                }
            }
            catch
            {
                originalImageSize = null;
            }

            var newSize = GetNewImageSize(options, originalImageSize);
            var quality = options.Quality;

            var outputFormat  = GetOutputFormat(options.SupportedOutputFormats[0]);
            var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor, options.ForegroundLayer);

            var imageProcessingLockTaken = false;

            try
            {
                CheckDisposed();

                if (!_fileSystem.FileExists(cacheFilePath))
                {
                    var newWidth  = Convert.ToInt32(newSize.Width);
                    var newHeight = Convert.ToInt32(newSize.Height);

                    _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
                    var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
                    _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));

                    await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);

                    imageProcessingLockTaken = true;

                    _imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
                    CopyFile(tmpPath, cacheFilePath);

                    return(new Tuple <string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath)));
                }

                return(new Tuple <string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath)));
            }
            catch (Exception ex)
            {
                // If it fails for whatever reason, return the original image
                _logger.ErrorException("Error encoding image", ex);

                // Just spit out the original file if all the options are default
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }
            finally
            {
                if (imageProcessingLockTaken)
                {
                    _imageProcessingSemaphore.Release();
                }
            }
        }
			public void SetUp()
			{
				var fakeFiles = CreateFakeFileList();
				expectedModificationTime = DateTime.UtcNow;
				
				log = Substitute.For<ILog>();
				
				fileSystem = Substitute.For<IFileSystem>();
				fileSystem.GetAllFiles("layouts").Returns(fakeFiles);
				fileSystem.ReadStringFromFile(Path.Combine("layouts", "a.html")).Returns("---\nnum: 1\n---\ntest 1");
				fileSystem.ReadStringFromFile(Path.Combine("layouts", "b.html")).Returns("test 2");
				fileSystem.ReadStringFromFile(Path.Combine("layouts", "b.yaml")).Returns("num: 2");
				fileSystem.GetLastWriteTimeUtc(Arg.Any<string>()).Returns(expectedModificationTime);
				
				configuration = Substitute.For<IConfiguration>();
				configuration.TextExtensions.Returns(new string[] { "html", "yaml" });
				
				fileSystemUnified = new FileSystemUnified(log, fileSystem, configuration);
			}
Example #16
0
        private async Task <Channel> GetChannel(IChannel channelInfo, CancellationToken cancellationToken)
        {
            var parentFolderId = Guid.Empty;

            var id = GetInternalChannelId(channelInfo.Name);

            var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);

            var isNew       = false;
            var forceUpdate = false;

            var item = _libraryManager.GetItemById(id) as Channel;

            if (item == null)
            {
                item = new Channel
                {
                    Name         = channelInfo.Name,
                    Id           = id,
                    DateCreated  = _fileSystem.GetCreationTimeUtc(path),
                    DateModified = _fileSystem.GetLastWriteTimeUtc(path)
                };

                isNew = true;
            }

            if (!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
            {
                isNew = true;
            }
            item.Path = path;

            if (!item.ChannelId.Equals(id))
            {
                forceUpdate = true;
            }
            item.ChannelId = id;

            if (item.ParentId != parentFolderId)
            {
                forceUpdate = true;
            }
            item.ParentId = parentFolderId;

            item.OfficialRating = GetOfficialRating(channelInfo.ParentalRating);
            item.Overview       = channelInfo.Description;

            if (string.IsNullOrWhiteSpace(item.Name))
            {
                item.Name = channelInfo.Name;
            }

            if (isNew)
            {
                item.OnMetadataChanged();
                _libraryManager.CreateItem(item, null);
            }

            await item.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_logger, _fileSystem))
            {
                ForceSave = !isNew && forceUpdate
            }, cancellationToken);

            return(item);
        }
Example #17
0
        public async Task <Tuple <string, string, DateTime> > ProcessImage(ImageProcessingOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            var originalImage = options.Image;
            var item          = options.Item;

            if (!originalImage.IsLocalFile)
            {
                if (item == null)
                {
                    item = _libraryManager().GetItemById(options.ItemId);
                }
                originalImage = await _libraryManager().ConvertImageToLocal(item, originalImage, options.ImageIndex).ConfigureAwait(false);
            }

            var originalImagePath = originalImage.Path;
            var dateModified      = originalImage.DateModified;

            if (!_imageEncoder.SupportsImageEncoding)
            {
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }

            var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);

            originalImagePath = supportedImageInfo.Item1;
            dateModified      = supportedImageInfo.Item2;
            var requiresTransparency = TransparentImageTypes.Contains(Path.GetExtension(originalImagePath) ?? string.Empty);

            if (options.Enhancers.Count > 0)
            {
                if (item == null)
                {
                    item = _libraryManager().GetItemById(options.ItemId);
                }

                var tuple = await GetEnhancedImage(new ItemImageInfo
                {
                    DateModified = dateModified,
                    Type         = originalImage.Type,
                    Path         = originalImagePath
                }, requiresTransparency, item, options.ImageIndex, options.Enhancers, CancellationToken.None).ConfigureAwait(false);

                originalImagePath    = tuple.Item1;
                dateModified         = tuple.Item2;
                requiresTransparency = tuple.Item3;
            }

            var photo      = item as Photo;
            var autoOrient = false;
            ImageOrientation?orientation = null;

            if (photo != null)
            {
                if (photo.Orientation.HasValue)
                {
                    if (photo.Orientation.Value != ImageOrientation.TopLeft)
                    {
                        autoOrient  = true;
                        orientation = photo.Orientation;
                    }
                }
                else
                {
                    // Orientation unknown, so do it
                    autoOrient  = true;
                    orientation = photo.Orientation;
                }
            }

            if (options.HasDefaultOptions(originalImagePath) && (!autoOrient || !options.RequiresAutoOrientation))
            {
                // Just spit out the original file if all the options are default
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }

            //ImageSize? originalImageSize = GetSavedImageSize(originalImagePath, dateModified);
            //if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value) && !autoOrient)
            //{
            //    // Just spit out the original file if all the options are default
            //    _logger.Info("Returning original image {0}", originalImagePath);
            //    return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
            //}

            var newSize = ImageHelper.GetNewImageSize(options, null);
            var quality = options.Quality;

            var outputFormat  = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency);
            var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer);

            CheckDisposed();

            var lockInfo = GetLock(cacheFilePath);

            await lockInfo.Lock.WaitAsync().ConfigureAwait(false);

            try
            {
                if (!_fileSystem.FileExists(cacheFilePath))
                {
                    if (options.CropWhiteSpace && !SupportsTransparency(originalImagePath))
                    {
                        options.CropWhiteSpace = false;
                    }

                    var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);

                    if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
                    {
                        return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
                    }

                    return(new Tuple <string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath)));
                }

                return(new Tuple <string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath)));
            }
            catch (ArgumentOutOfRangeException ex)
            {
                // Decoder failed to decode it
#if DEBUG
                _logger.ErrorException("Error encoding image", ex);
#endif
                // Just spit out the original file if all the options are default
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }
            catch (Exception ex)
            {
                // If it fails for whatever reason, return the original image
                _logger.ErrorException("Error encoding image", ex);

                // Just spit out the original file if all the options are default
                return(new Tuple <string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified));
            }
            finally
            {
                ReleaseLock(cacheFilePath, lockInfo);
            }
        }
        public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
        {
            var file = GetXmlFile(item.Path, item.IsInMixedFolder);

            return(file.Exists && _fileSystem.GetLastWriteTimeUtc(file) > date);
        }
 public DateTime GetLastWriteTimeUtc(string path) => _fileSystem.GetLastWriteTimeUtc(path);
Example #20
0
        public bool MergeImages(BaseItem item, List <LocalImageInfo> images)
        {
            var changed = false;

            foreach (var type in _singularImages)
            {
                var image = images.FirstOrDefault(i => i.Type == type);

                if (image != null)
                {
                    var currentImage = item.GetImageInfo(type, 0);

                    if (currentImage == null)
                    {
                        item.SetImagePath(type, image.FileInfo);
                        changed = true;
                    }
                    else if (!string.Equals(currentImage.Path, image.FileInfo.FullName, StringComparison.OrdinalIgnoreCase))
                    {
                        item.SetImagePath(type, image.FileInfo);
                        changed = true;
                    }
                    else
                    {
                        var newDateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo);

                        // If date changed then we need to reset saved image dimensions
                        if (currentImage.DateModified != newDateModified && (currentImage.Width > 0 || currentImage.Height > 0))
                        {
                            currentImage.Width  = 0;
                            currentImage.Height = 0;
                            changed             = true;
                        }

                        currentImage.DateModified = newDateModified;
                    }
                }
                else
                {
                    var existing = item.GetImageInfo(type, 0);
                    if (existing != null)
                    {
                        if (existing.IsLocalFile && !File.Exists(existing.Path))
                        {
                            item.RemoveImage(existing);
                            changed = true;
                        }
                    }
                }
            }

            if (UpdateMultiImages(item, images, ImageType.Backdrop))
            {
                changed = true;
            }

            var hasScreenshots = item as IHasScreenshots;

            if (hasScreenshots != null)
            {
                if (UpdateMultiImages(item, images, ImageType.Screenshot))
                {
                    changed = true;
                }
            }

            return(changed);
        }
Example #21
0
        /// <summary>
        /// Ensures DateCreated and DateModified have values
        /// </summary>
        /// <param name="fileSystem">The file system.</param>
        /// <param name="item">The item.</param>
        /// <param name="args">The args.</param>
        /// <param name="includeCreationTime">if set to <c>true</c> [include creation time].</param>
        private static void EnsureDates(IFileSystem fileSystem, BaseItem item, ItemResolveArgs args, bool includeCreationTime)
        {
            if (fileSystem == null)
            {
                throw new ArgumentNullException("fileSystem");
            }
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            // See if a different path came out of the resolver than what went in
            if (!string.Equals(args.Path, item.Path, StringComparison.OrdinalIgnoreCase))
            {
                var childData = args.IsDirectory ? args.GetFileSystemEntryByPath(item.Path) : null;

                if (childData != null)
                {
                    if (includeCreationTime)
                    {
                        SetDateCreated(item, fileSystem, childData);
                    }

                    item.DateModified = fileSystem.GetLastWriteTimeUtc(childData);
                }
                else
                {
                    var fileData = fileSystem.GetFileSystemInfo(item.Path);

                    if (fileData.Exists)
                    {
                        if (includeCreationTime)
                        {
                            SetDateCreated(item, fileSystem, fileData);
                        }
                        item.DateModified = fileSystem.GetLastWriteTimeUtc(fileData);
                    }
                }
            }
            else
            {
                if (includeCreationTime)
                {
                    SetDateCreated(item, fileSystem, args.FileInfo);
                }
                item.DateModified = fileSystem.GetLastWriteTimeUtc(args.FileInfo);
            }
        }
Example #22
0
        internal Task EnsureSeriesInfo(string seriesId, string preferredMetadataLanguage, CancellationToken cancellationToken)
        {
            var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesId);

            Directory.CreateDirectory(seriesDataPath);

            var files = new DirectoryInfo(seriesDataPath).EnumerateFiles("*.xml", SearchOption.TopDirectoryOnly)
                        .ToList();

            var seriesXmlFilename = preferredMetadataLanguage + ".xml";

            var download = false;
            var automaticUpdatesEnabled = GetTvDbOptions().EnableAutomaticUpdates;

            const int cacheDays = 2;

            var seriesFile = files.FirstOrDefault(i => string.Equals(seriesXmlFilename, i.Name, StringComparison.OrdinalIgnoreCase));

            // No need to check age if automatic updates are enabled
            if (seriesFile == null || !seriesFile.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(seriesFile)).TotalDays > cacheDays))
            {
                download = true;
            }

            var actorsXml = files.FirstOrDefault(i => string.Equals("actors.xml", i.Name, StringComparison.OrdinalIgnoreCase));

            // No need to check age if automatic updates are enabled
            if (actorsXml == null || !actorsXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(actorsXml)).TotalDays > cacheDays))
            {
                download = true;
            }

            var bannersXml = files.FirstOrDefault(i => string.Equals("banners.xml", i.Name, StringComparison.OrdinalIgnoreCase));

            // No need to check age if automatic updates are enabled
            if (bannersXml == null || !bannersXml.Exists || (!automaticUpdatesEnabled && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(bannersXml)).TotalDays > cacheDays))
            {
                download = true;
            }

            // Only download if not already there
            // The post-scan task will take care of updates so we don't need to re-download here
            if (download)
            {
                return(DownloadSeriesZip(seriesId, seriesDataPath, null, preferredMetadataLanguage, cancellationToken));
            }

            return(_cachedTask);
        }
        /// <summary>
        /// Ensures DateCreated and DateModified have values
        /// </summary>
        /// <param name="fileSystem">The file system.</param>
        /// <param name="item">The item.</param>
        /// <param name="args">The args.</param>
        /// <param name="includeCreationTime">if set to <c>true</c> [include creation time].</param>
        public static void EnsureDates(IFileSystem fileSystem, BaseItem item, ItemResolveArgs args, bool includeCreationTime)
        {
            if (!Path.IsPathRooted(item.Path))
            {
                return;
            }

            // See if a different path came out of the resolver than what went in
            if (!string.Equals(args.Path, item.Path, StringComparison.OrdinalIgnoreCase))
            {
                var childData = args.IsDirectory ? args.GetFileSystemEntryByPath(item.Path) : null;

                if (childData != null)
                {
                    if (includeCreationTime)
                    {
                        item.DateCreated = fileSystem.GetCreationTimeUtc(childData);
                    }

                    item.DateModified = fileSystem.GetLastWriteTimeUtc(childData);
                }
                else
                {
                    var fileData = fileSystem.GetFileSystemInfo(item.Path);

                    if (fileData.Exists)
                    {
                        if (includeCreationTime)
                        {
                            item.DateCreated = fileSystem.GetCreationTimeUtc(fileData);
                        }
                        item.DateModified = fileSystem.GetLastWriteTimeUtc(fileData);
                    }
                }
            }
            else
            {
                if (includeCreationTime)
                {
                    item.DateCreated = fileSystem.GetCreationTimeUtc(args.FileInfo);
                }
                item.DateModified = fileSystem.GetLastWriteTimeUtc(args.FileInfo);
            }
        }
Example #24
0
        public bool HasChanged(BaseItem item, IDirectoryService directoryService)
        {
            var file = GetXmlFile(item.Path);

            return(file.Exists && _fileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved);
        }
        private static FileItem[] HandleFacade(IFileSystem facade, bool Recursivity = false, bool index = false)
        {
            HashSet <FileItem> result = new HashSet <FileItem>();

            try
            {
                if (index)
                {
                    // add the root to the array
                    var root = facade.Root;

                    if (root != null)
                    {
                        FileItem fileItem3 = new FileItem();
                        fileItem3.Location = @"\";

                        Console.WriteLine($"Folder: {fileItem3.Location}");

                        var tmpattribs3 = facade.GetAttributes(fileItem3.Location).ToString();
                        fileItem3.Attributes = tmpattribs3.Split(", ");

                        fileItem3.LastAccessTime = root.LastAccessTimeUtc.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
                        fileItem3.LastWriteTime  = root.LastWriteTimeUtc.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
                        fileItem3.CreationTime   = root.CreationTimeUtc.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

                        result.Add(fileItem3);
                    }
                    // end of adding root

                    foreach (var item in facade.GetDirectories("", null, SearchOption.AllDirectories))
                    {
                        FileItem fileItem = new FileItem();
                        fileItem.Location = item;

                        Console.WriteLine($"Folder: {fileItem.Location}");

                        var tmpattribs = facade.GetAttributes(fileItem.Location).ToString();
                        fileItem.Attributes = tmpattribs.Split(", ");

                        fileItem.LastAccessTime = facade.GetLastAccessTimeUtc(fileItem.Location).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
                        fileItem.LastWriteTime  = facade.GetLastWriteTimeUtc(fileItem.Location).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
                        fileItem.CreationTime   = facade.GetCreationTimeUtc(fileItem.Location).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

                        result.Add(fileItem);
                    }
                }

                foreach (var item in facade.GetFiles("", null, SearchOption.AllDirectories))
                {
                    FileItem fileItem = new FileItem();
                    fileItem.Location = item;

                    if (index)
                    {
                        Console.WriteLine($"File: {fileItem.Location}");

                        var tmpattribs = facade.GetAttributes(fileItem.Location).ToString();
                        fileItem.Attributes = tmpattribs.Split(", ");

                        fileItem.LastAccessTime = facade.GetLastAccessTimeUtc(fileItem.Location).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
                        fileItem.LastWriteTime  = facade.GetLastWriteTimeUtc(fileItem.Location).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");
                        fileItem.CreationTime   = facade.GetCreationTimeUtc(fileItem.Location).ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'");

                        fileItem.Size = facade.GetFileLength(fileItem.Location).ToString();

                        fileItem.Hash = new Hash();

                        using var file     = facade.OpenFile(fileItem.Location, FileMode.Open, FileAccess.Read);
                        using var md5Prov  = MD5.Create();
                        using var sha1Prov = SHA1.Create();
                        using var crcProv  = new Crc32();

                        Console.WriteLine("Computing hashes");

                        byte[] buffer    = new byte[16384];
                        int    bytesRead = 0;

                        while ((bytesRead = file.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            md5Prov.TransformBlock(buffer, 0, bytesRead, buffer, 0);
                            sha1Prov.TransformBlock(buffer, 0, bytesRead, buffer, 0);
                            crcProv.TransformBlock(buffer, 0, bytesRead, buffer, 0);
                        }

                        md5Prov.TransformFinalBlock(buffer, 0, 0);
                        sha1Prov.TransformFinalBlock(buffer, 0, 0);
                        crcProv.TransformFinalBlock(buffer, 0, 0);

                        fileItem.Hash.MD5   = BitConverter.ToString(md5Prov.Hash).Replace("-", "");
                        fileItem.Hash.SHA1  = BitConverter.ToString(sha1Prov.Hash).Replace("-", "");
                        fileItem.Hash.CRC32 = BitConverter.ToString(crcProv.Hash).Replace("-", "");
                    }

                    var extension = fileItem.Location.Split(".")[^ 1];
Example #26
0
        public async Task <bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList <ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
        {
            if (!IsEligibleForChapterImageExtraction(video))
            {
                extractImages = false;
            }

            var success     = true;
            var changesMade = false;

            var runtimeTicks = video.RunTimeTicks ?? 0;

            var currentImages = GetSavedChapterImages(video, directoryService);

            foreach (var chapter in chapters)
            {
                if (chapter.StartPositionTicks >= runtimeTicks)
                {
                    _logger.LogInformation("Stopping chapter extraction for {0} because a chapter was found with a position greater than the runtime.", video.Name);
                    break;
                }

                var path = GetChapterImagePath(video, chapter.StartPositionTicks);

                if (!currentImages.Contains(path, StringComparer.OrdinalIgnoreCase))
                {
                    if (extractImages)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        try
                        {
                            // Add some time for the first chapter to make sure we don't end up with a black image
                            var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(_firstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks);

                            var inputPath = video.Path;

                            Directory.CreateDirectory(Path.GetDirectoryName(path));

                            var container   = video.Container;
                            var mediaSource = new MediaSourceInfo
                            {
                                VideoType = video.VideoType,
                                IsoType   = video.IsoType,
                                Protocol  = video.PathProtocol.Value,
                            };

                            var tempFile = await _encoder.ExtractVideoImage(inputPath, container, mediaSource, video.GetDefaultVideoStream(), video.Video3DFormat, time, cancellationToken).ConfigureAwait(false);

                            File.Copy(tempFile, path, true);

                            try
                            {
                                _fileSystem.DeleteFile(tempFile);
                            }
                            catch (IOException ex)
                            {
                                _logger.LogError(ex, "Error deleting temporary chapter image encoding file {Path}", tempFile);
                            }

                            chapter.ImagePath         = path;
                            chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path);
                            changesMade = true;
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "Error extracting chapter images for {0}", string.Join(',', video.Path));
                            success = false;
                            break;
                        }
                    }
                    else if (!string.IsNullOrEmpty(chapter.ImagePath))
                    {
                        chapter.ImagePath = null;
                        changesMade       = true;
                    }
                }
                else if (!string.Equals(path, chapter.ImagePath, StringComparison.OrdinalIgnoreCase))
                {
                    chapter.ImagePath         = path;
                    chapter.ImageDateModified = _fileSystem.GetLastWriteTimeUtc(path);
                    changesMade = true;
                }
            }

            if (saveChapters && changesMade)
            {
                _chapterManager.SaveChapters(video.Id, chapters);
            }

            DeleteDeadImages(currentImages, chapters);

            return(success);
        }
Example #27
0
        /// <summary>
        /// Runs the specified progress.
        /// </summary>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        public async Task Run(IProgress <double> progress, CancellationToken cancellationToken)
        {
            if (!_config.Configuration.EnableInternetProviders ||
                _config.Configuration.InternetProviderExcludeTypes.Contains(typeof(Series).Name, StringComparer.OrdinalIgnoreCase))
            {
                progress.Report(100);
                return;
            }

            var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);

            Directory.CreateDirectory(path);

            var timestampFile = Path.Combine(path, "time.txt");

            var timestampFileInfo = new FileInfo(timestampFile);

            // Don't check for tvdb updates anymore frequently than 24 hours
            if (timestampFileInfo.Exists && (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(timestampFileInfo)).TotalDays < 1)
            {
                return;
            }

            // Find out the last time we queried tvdb for updates
            var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;

            string newUpdateTime;

            var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();

            // If this is our first time, update all series
            if (string.IsNullOrEmpty(lastUpdateTime))
            {
                // First get tvdb server time
                using (var stream = await _httpClient.Get(new HttpRequestOptions
                {
                    Url = ServerTimeUrl,
                    CancellationToken = cancellationToken,
                    EnableHttpCompression = true,
                    ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
                }).ConfigureAwait(false))
                {
                    newUpdateTime = GetUpdateTime(stream);
                }

                await UpdateSeries(existingDirectories, path, null, progress, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                var seriesToUpdate = await GetSeriesIdsToUpdate(existingDirectories, lastUpdateTime, cancellationToken).ConfigureAwait(false);

                newUpdateTime = seriesToUpdate.Item2;

                long lastUpdateValue;

                long.TryParse(lastUpdateTime, NumberStyles.Any, UsCulture, out lastUpdateValue);

                var nullableUpdateValue = lastUpdateValue == 0 ? (long?)null : lastUpdateValue;

                await UpdateSeries(seriesToUpdate.Item1, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false);
            }

            File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
            progress.Report(100);
        }