diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json index 1a69627fa..f8f962ee0 100644 --- a/Emby.Server.Implementations/Localization/Core/en-US.json +++ b/Emby.Server.Implementations/Localization/Core/en-US.json @@ -122,6 +122,8 @@ "TaskCleanTranscodeDescription": "Deletes transcode files more than one day old.", "TaskRefreshChannels": "Refresh Channels", "TaskRefreshChannelsDescription": "Refreshes internet channel information.", + "TaskDownloadMissingLyrics": "Download missing lyrics", + "TaskDownloadMissingLyricsDescription": "Task to download missing lyrics", "TaskDownloadMissingSubtitles": "Download missing subtitles", "TaskDownloadMissingSubtitlesDescription": "Searches the internet for missing subtitles based on metadata configuration.", "TaskOptimizeDatabase": "Optimize database", diff --git a/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs b/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs new file mode 100644 index 000000000..184e8495b --- /dev/null +++ b/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Enums; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Lyrics; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.Lyrics; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace MediaBrowser.Providers.Lyric; + +/// +/// Task to download lyrics. +/// +public class LyricDownloadTask : IScheduledTask +{ + private const int QueryPageLimit = 100; + + private static readonly BaseItemKind[] _itemKinds = [BaseItemKind.Audio]; + private static readonly MediaType[] _mediaTypes = [MediaType.Audio]; + private static readonly SourceType[] _sourceTypes = [SourceType.Library]; + private static readonly DtoOptions _dtoOptions = new(false); + + private readonly ILibraryManager _libraryManager; + private readonly ILyricManager _lyricManager; + private readonly ILogger _logger; + private readonly ILocalizationManager _localizationManager; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + public LyricDownloadTask( + ILibraryManager libraryManager, + ILyricManager lyricManager, + ILogger logger, + ILocalizationManager localizationManager) + { + _libraryManager = libraryManager; + _lyricManager = lyricManager; + _logger = logger; + _localizationManager = localizationManager; + } + + /// + public string Name => _localizationManager.GetLocalizedString("TaskDownloadMissingLyrics"); + + /// + public string Key => "DownloadLrcLibLyrics"; + + /// + public string Description => _localizationManager.GetLocalizedString("TaskDownloadMissingLyricsDescription"); + + /// + public string Category => _localizationManager.GetLocalizedString("TasksLibraryCategory"); + + /// + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) + { + var totalCount = _libraryManager.GetCount(new InternalItemsQuery + { + Recursive = true, + IsVirtualItem = false, + IncludeItemTypes = _itemKinds, + DtoOptions = _dtoOptions, + MediaTypes = _mediaTypes, + SourceTypes = _sourceTypes + }); + + var completed = 0; + + foreach (var library in _libraryManager.RootFolder.Children.ToList()) + { + var libraryOptions = _libraryManager.GetLibraryOptions(library); + var itemQuery = new InternalItemsQuery + { + Recursive = true, + IsVirtualItem = false, + IncludeItemTypes = _itemKinds, + DtoOptions = _dtoOptions, + MediaTypes = _mediaTypes, + SourceTypes = _sourceTypes, + Limit = QueryPageLimit, + Parent = library + }; + + int previousCount; + var startIndex = 0; + do + { + itemQuery.StartIndex = startIndex; + var audioItems = _libraryManager.GetItemList(itemQuery); + + foreach (var audioItem in audioItems.OfType