< Summary - Jellyfin

Information
Class: Emby.Server.Implementations.ScheduledTasks.Tasks.ChapterImagesTask
Assembly: Emby.Server.Implementations
File(s): /srv/git/jellyfin/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
Line coverage
72%
Covered lines: 8
Uncovered lines: 3
Coverable lines: 11
Total lines: 168
Line coverage: 72.7%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Name()100%11100%
get_Description()100%210%
get_Category()100%210%
get_Key()100%210%

File(s)

/srv/git/jellyfin/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Linq;
 5using System.Threading;
 6using System.Threading.Tasks;
 7using Jellyfin.Data.Enums;
 8using Jellyfin.Extensions;
 9using MediaBrowser.Common.Configuration;
 10using MediaBrowser.Controller.Chapters;
 11using MediaBrowser.Controller.Dto;
 12using MediaBrowser.Controller.Entities;
 13using MediaBrowser.Controller.Library;
 14using MediaBrowser.Controller.Providers;
 15using MediaBrowser.Model.Globalization;
 16using MediaBrowser.Model.IO;
 17using MediaBrowser.Model.Tasks;
 18using Microsoft.Extensions.Logging;
 19
 20namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
 21
 22/// <summary>
 23/// Class ChapterImagesTask.
 24/// </summary>
 25public class ChapterImagesTask : IScheduledTask
 26{
 27    private readonly ILogger<ChapterImagesTask> _logger;
 28    private readonly ILibraryManager _libraryManager;
 29    private readonly IApplicationPaths _appPaths;
 30    private readonly IChapterManager _chapterManager;
 31    private readonly IFileSystem _fileSystem;
 32    private readonly ILocalizationManager _localization;
 33
 34    /// <summary>
 35    /// Initializes a new instance of the <see cref="ChapterImagesTask" /> class.
 36    /// </summary>
 37    /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
 38    /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 39    /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
 40    /// <param name="chapterManager">Instance of the <see cref="IChapterManager"/> interface.</param>
 41    /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
 42    /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
 43    public ChapterImagesTask(
 44        ILogger<ChapterImagesTask> logger,
 45        ILibraryManager libraryManager,
 46        IApplicationPaths appPaths,
 47        IChapterManager chapterManager,
 48        IFileSystem fileSystem,
 49        ILocalizationManager localization)
 50    {
 2151        _logger = logger;
 2152        _libraryManager = libraryManager;
 2153        _appPaths = appPaths;
 2154        _chapterManager = chapterManager;
 2155        _fileSystem = fileSystem;
 2156        _localization = localization;
 2157    }
 58
 59    /// <inheritdoc />
 2160    public string Name => _localization.GetLocalizedString("TaskRefreshChapterImages");
 61
 62    /// <inheritdoc />
 063    public string Description => _localization.GetLocalizedString("TaskRefreshChapterImagesDescription");
 64
 65    /// <inheritdoc />
 066    public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
 67
 68    /// <inheritdoc />
 069    public string Key => "RefreshChapterImages";
 70
 71    /// <inheritdoc />
 72    public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
 73    {
 74        yield return new TaskTriggerInfo
 75        {
 76            Type = TaskTriggerInfoType.DailyTrigger,
 77            TimeOfDayTicks = TimeSpan.FromHours(2).Ticks,
 78            MaxRuntimeTicks = TimeSpan.FromHours(4).Ticks
 79        };
 80    }
 81
 82    /// <inheritdoc />
 83    public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
 84    {
 85        var videos = _libraryManager.GetItemList(new InternalItemsQuery
 86        {
 87            MediaTypes = [MediaType.Video],
 88            IsFolder = false,
 89            Recursive = true,
 90            DtoOptions = new DtoOptions(false)
 91            {
 92                EnableImages = false
 93            },
 94            SourceTypes = [SourceType.Library],
 95            IsVirtualItem = false
 96        })
 97        .OfType<Video>()
 98        .ToList();
 99
 100        var numComplete = 0;
 101
 102        var failHistoryPath = Path.Combine(_appPaths.CachePath, "chapter-failures.txt");
 103
 104        List<string> previouslyFailedImages;
 105
 106        if (File.Exists(failHistoryPath))
 107        {
 108            try
 109            {
 110                previouslyFailedImages = (await File.ReadAllTextAsync(failHistoryPath, cancellationToken).ConfigureAwait
 111                    .Split('|', StringSplitOptions.RemoveEmptyEntries)
 112                    .ToList();
 113            }
 114            catch (IOException)
 115            {
 116                previouslyFailedImages = [];
 117            }
 118        }
 119        else
 120        {
 121            previouslyFailedImages = [];
 122        }
 123
 124        var directoryService = new DirectoryService(_fileSystem);
 125
 126        foreach (var video in videos)
 127        {
 128            cancellationToken.ThrowIfCancellationRequested();
 129
 130            var key = video.Path + video.DateModified.Ticks;
 131
 132            var extract = !previouslyFailedImages.Contains(key, StringComparison.OrdinalIgnoreCase);
 133
 134            try
 135            {
 136                var chapters = _chapterManager.GetChapters(video.Id);
 137
 138                var success = await _chapterManager.RefreshChapterImages(video, directoryService, chapters, extract, tru
 139
 140                if (!success)
 141                {
 142                    previouslyFailedImages.Add(key);
 143
 144                    var parentPath = Path.GetDirectoryName(failHistoryPath);
 145                    if (parentPath is not null)
 146                    {
 147                        Directory.CreateDirectory(parentPath);
 148                    }
 149
 150                    string text = string.Join('|', previouslyFailedImages);
 151                    await File.WriteAllTextAsync(failHistoryPath, text, cancellationToken).ConfigureAwait(false);
 152                }
 153
 154                numComplete++;
 155                double percent = numComplete;
 156                percent /= videos.Count;
 157
 158                progress.Report(100 * percent);
 159            }
 160            catch (ObjectDisposedException ex)
 161            {
 162                // TODO Investigate and properly fix.
 163                _logger.LogError(ex, "Object Disposed");
 164                break;
 165            }
 166        }
 167    }
 168}