< Summary - Jellyfin

Information
Class: MediaBrowser.Providers.Lyric.LyricScheduledTask
Assembly: MediaBrowser.Providers
File(s): /srv/git/jellyfin/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs
Line coverage
66%
Covered lines: 14
Uncovered lines: 7
Coverable lines: 21
Total lines: 170
Line coverage: 66.6%
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
.cctor()100%210%
.ctor(...)100%11100%
get_Name()100%11100%
get_Key()100%210%
get_Description()100%210%
get_Category()100%210%
GetDefaultTriggers()100%11100%

File(s)

/srv/git/jellyfin/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Threading;
 5using System.Threading.Tasks;
 6using Jellyfin.Data.Enums;
 7using MediaBrowser.Controller.Dto;
 8using MediaBrowser.Controller.Entities;
 9using MediaBrowser.Controller.Entities.Audio;
 10using MediaBrowser.Controller.Library;
 11using MediaBrowser.Controller.Lyrics;
 12using MediaBrowser.Model.Entities;
 13using MediaBrowser.Model.Globalization;
 14using MediaBrowser.Model.Lyrics;
 15using MediaBrowser.Model.Tasks;
 16using Microsoft.Extensions.Logging;
 17
 18namespace MediaBrowser.Providers.Lyric;
 19
 20/// <summary>
 21/// Task to download lyrics.
 22/// </summary>
 23public class LyricScheduledTask : IScheduledTask
 24{
 25    private const int QueryPageLimit = 100;
 26
 027    private static readonly BaseItemKind[] _itemKinds = [BaseItemKind.Audio];
 028    private static readonly MediaType[] _mediaTypes = [MediaType.Audio];
 029    private static readonly SourceType[] _sourceTypes = [SourceType.Library];
 030    private static readonly DtoOptions _dtoOptions = new(false);
 31
 32    private readonly ILibraryManager _libraryManager;
 33    private readonly ILyricManager _lyricManager;
 34    private readonly ILogger<LyricScheduledTask> _logger;
 35    private readonly ILocalizationManager _localizationManager;
 36
 37    /// <summary>
 38    /// Initializes a new instance of the <see cref="LyricScheduledTask"/> class.
 39    /// </summary>
 40    /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
 41    /// <param name="lyricManager">Instance of the <see cref="ILyricManager"/> interface.</param>
 42    /// <param name="logger">Instance of the <see cref="ILogger{DownloaderScheduledTask}"/> interface.</param>
 43    /// <param name="localizationManager">Instance of the <see cref="ILocalizationManager"/> interface.</param>
 44    public LyricScheduledTask(
 45        ILibraryManager libraryManager,
 46        ILyricManager lyricManager,
 47        ILogger<LyricScheduledTask> logger,
 48        ILocalizationManager localizationManager)
 49    {
 2250        _libraryManager = libraryManager;
 2251        _lyricManager = lyricManager;
 2252        _logger = logger;
 2253        _localizationManager = localizationManager;
 2254    }
 55
 56    /// <inheritdoc />
 2257    public string Name => _localizationManager.GetLocalizedString("TaskDownloadMissingLyrics");
 58
 59    /// <inheritdoc />
 060    public string Key => "DownloadLyrics";
 61
 62    /// <inheritdoc />
 063    public string Description => _localizationManager.GetLocalizedString("TaskDownloadMissingLyricsDescription");
 64
 65    /// <inheritdoc />
 066    public string Category => _localizationManager.GetLocalizedString("TasksLibraryCategory");
 67
 68    /// <inheritdoc />
 69    public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
 70    {
 71        var totalCount = _libraryManager.GetCount(new InternalItemsQuery
 72        {
 73            Recursive = true,
 74            IsVirtualItem = false,
 75            IncludeItemTypes = _itemKinds,
 76            DtoOptions = _dtoOptions,
 77            MediaTypes = _mediaTypes,
 78            SourceTypes = _sourceTypes
 79        });
 80
 81        var completed = 0;
 82
 83        foreach (var library in _libraryManager.RootFolder.Children.ToList())
 84        {
 85            var libraryOptions = _libraryManager.GetLibraryOptions(library);
 86            var itemQuery = new InternalItemsQuery
 87            {
 88                Recursive = true,
 89                IsVirtualItem = false,
 90                IncludeItemTypes = _itemKinds,
 91                DtoOptions = _dtoOptions,
 92                MediaTypes = _mediaTypes,
 93                SourceTypes = _sourceTypes,
 94                Limit = QueryPageLimit,
 95                Parent = library
 96            };
 97
 98            int previousCount;
 99            var startIndex = 0;
 100            do
 101            {
 102                itemQuery.StartIndex = startIndex;
 103                var audioItems = _libraryManager.GetItemList(itemQuery);
 104
 105                foreach (var audioItem in audioItems.OfType<Audio>())
 106                {
 107                    cancellationToken.ThrowIfCancellationRequested();
 108
 109                    try
 110                    {
 111                        if (audioItem.GetMediaStreams().All(s => s.Type != MediaStreamType.Lyric))
 112                        {
 113                            _logger.LogDebug("Searching for lyrics for {Path}", audioItem.Path);
 114                            var lyricResults = await _lyricManager.SearchLyricsAsync(
 115                                    new LyricSearchRequest
 116                                    {
 117                                        MediaPath = audioItem.Path,
 118                                        SongName = audioItem.Name,
 119                                        AlbumName = audioItem.Album,
 120                                        ArtistNames = audioItem.GetAllArtists().ToList(),
 121                                        Duration = audioItem.RunTimeTicks,
 122                                        IsAutomated = true,
 123                                        DisabledLyricFetchers = libraryOptions.DisabledLyricFetchers,
 124                                        LyricFetcherOrder = libraryOptions.LyricFetcherOrder
 125                                    },
 126                                    cancellationToken)
 127                                .ConfigureAwait(false);
 128
 129                            if (lyricResults.Count != 0)
 130                            {
 131                                _logger.LogDebug("Saving lyrics for {Path}", audioItem.Path);
 132                                await _lyricManager.DownloadLyricsAsync(
 133                                        audioItem,
 134                                        libraryOptions,
 135                                        lyricResults[0].Id,
 136                                        cancellationToken)
 137                                    .ConfigureAwait(false);
 138                            }
 139                        }
 140                    }
 141                    catch (Exception ex)
 142                    {
 143                        _logger.LogError(ex, "Error downloading lyrics for {Path}", audioItem.Path);
 144                    }
 145
 146                    completed++;
 147                    progress.Report(100d * completed / totalCount);
 148                }
 149
 150                startIndex += QueryPageLimit;
 151                previousCount = audioItems.Count;
 152            } while (previousCount > 0);
 153        }
 154
 155        progress.Report(100);
 156    }
 157
 158    /// <inheritdoc />
 159    public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
 160    {
 22161        return
 22162        [
 22163            new TaskTriggerInfo
 22164            {
 22165                Type = TaskTriggerInfo.TriggerInterval,
 22166                IntervalTicks = TimeSpan.FromHours(24).Ticks
 22167            }
 22168        ];
 169    }
 170}