refactor: Refactored lyrics download logic and file scanning logic.

This commit is contained in:
real-zony 2022-10-23 19:28:57 +08:00
parent f9570508c2
commit 64d26cbc4c
8 changed files with 114 additions and 63 deletions

View File

@ -4,7 +4,6 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using McMaster.Extensions.CommandLineUtils; using McMaster.Extensions.CommandLineUtils;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using ZonyLrcTools.Cli.Infrastructure.Tag;
using ZonyLrcTools.Common; using ZonyLrcTools.Common;
using ZonyLrcTools.Common.Album; using ZonyLrcTools.Common.Album;
using ZonyLrcTools.Common.Configuration; using ZonyLrcTools.Common.Configuration;
@ -14,7 +13,6 @@ using ZonyLrcTools.Common.Infrastructure.IO;
using ZonyLrcTools.Common.Infrastructure.Logging; using ZonyLrcTools.Common.Infrastructure.Logging;
using ZonyLrcTools.Common.Infrastructure.Threading; using ZonyLrcTools.Common.Infrastructure.Threading;
using ZonyLrcTools.Common.Lyrics; using ZonyLrcTools.Common.Lyrics;
using File = System.IO.File;
namespace ZonyLrcTools.Cli.Commands.SubCommand namespace ZonyLrcTools.Cli.Commands.SubCommand
{ {
@ -22,24 +20,22 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
public class DownloadCommand : ToolCommandBase public class DownloadCommand : ToolCommandBase
{ {
private readonly ILyricsDownloader _lyricsDownloader; private readonly ILyricsDownloader _lyricsDownloader;
private readonly IFileScanner _fileScanner; private readonly IMusicInfoLoader _musicInfoLoader;
private readonly IEnumerable<IAlbumDownloader> _albumDownloaderList; private readonly IEnumerable<IAlbumDownloader> _albumDownloaderList;
private readonly ITagLoader _tagLoader;
private readonly IWarpLogger _logger;
private readonly IWarpLogger _logger;
private readonly GlobalOptions _options; private readonly GlobalOptions _options;
public DownloadCommand(IFileScanner fileScanner, public DownloadCommand(IOptions<GlobalOptions> options,
IOptions<GlobalOptions> options,
IEnumerable<IAlbumDownloader> albumDownloaderList, IEnumerable<IAlbumDownloader> albumDownloaderList,
ITagLoader tagLoader, ILyricsDownloader lyricsDownloader,
ILyricsDownloader lyricsDownloader, IWarpLogger logger) IWarpLogger logger,
IMusicInfoLoader musicInfoLoader)
{ {
_fileScanner = fileScanner;
_albumDownloaderList = albumDownloaderList; _albumDownloaderList = albumDownloaderList;
_tagLoader = tagLoader;
_lyricsDownloader = lyricsDownloader; _lyricsDownloader = lyricsDownloader;
_logger = logger; _logger = logger;
_musicInfoLoader = musicInfoLoader;
_options = options.Value; _options = options.Value;
} }
@ -64,39 +60,19 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
{ {
if (DownloadLyric) if (DownloadLyric)
{ {
await _lyricsDownloader.DownloadAsync( await _lyricsDownloader.DownloadAsync(await _musicInfoLoader.LoadAsync(SongsDirectory, ParallelNumber), ParallelNumber);
await LoadMusicInfoAsync(
RemoveExistLyricFiles(
await ScanMusicFilesAsync())), ParallelNumber);
} }
if (DownloadAlbum) if (DownloadAlbum)
{ {
await DownloadAlbumAsync( // await DownloadAlbumAsync(
await LoadMusicInfoAsync( // await LoadMusicInfoAsync(
await ScanMusicFilesAsync())); // await ScanMusicFilesAsync()));
} }
return 0; return 0;
} }
private async Task<List<string>> ScanMusicFilesAsync()
{
var files = (await _fileScanner.ScanAsync(SongsDirectory, _options.SupportFileExtensions))
.SelectMany(t => t.FilePaths)
.ToList();
if (files.Count == 0)
{
await _logger.ErrorAsync("没有找到任何音乐文件。");
throw new ErrorCodeException(ErrorCodes.NoFilesWereScanned);
}
await _logger.InfoAsync($"已经扫描到了 {files.Count} 个音乐文件。");
return files;
}
private List<string> RemoveExistLyricFiles(List<string> filePaths) private List<string> RemoveExistLyricFiles(List<string> filePaths)
{ {
if (!_options.Provider.Lyric.Config.IsSkipExistLyricFiles) if (!_options.Provider.Lyric.Config.IsSkipExistLyricFiles)
@ -118,21 +94,6 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
.ToList(); .ToList();
} }
private async Task<List<MusicInfo>> LoadMusicInfoAsync(IReadOnlyCollection<string> files)
{
await _logger.InfoAsync("开始加载音乐文件的标签信息...");
var warpTask = new WarpTask(ParallelNumber);
var warpTaskList = files.Select(file => warpTask.RunAsync(() => Task.Run(async () => await _tagLoader.LoadTagAsync(file))));
var result = (await Task.WhenAll(warpTaskList))
.Where(m => m != null)
.Where(m => !string.IsNullOrEmpty(m.Name) || !string.IsNullOrEmpty(m.Artist))
.ToList();
await _logger.InfoAsync($"已成功加载 {files.Count} 个音乐文件的标签信息。");
return result;
}
#region > Ablum image download logic < #region > Ablum image download logic <
private async ValueTask DownloadAlbumAsync(List<MusicInfo> musicInfos) private async ValueTask DownloadAlbumAsync(List<MusicInfo> musicInfos)

View File

@ -0,0 +1,12 @@
namespace ZonyLrcTools.Common;
public interface IMusicInfoLoader
{
Task<List<MusicInfo?>> LoadAsync(string dirPath,
int parallelCount = 2,
CancellationToken cancellationToken = default);
Task<List<MusicInfo?>> LoadAsync(IReadOnlyCollection<string> filePaths,
int parallelCount = 2,
CancellationToken cancellationToken = default);
}

View File

@ -0,0 +1,15 @@
namespace ZonyLrcTools.Common.Infrastructure.IO;
public static class FileScannerExtensions
{
public static async Task<IEnumerable<string>> ScanMusicFilesAsync(this IFileScanner fileScanner,
string dirPath,
IEnumerable<string> extensions)
{
var files = (await fileScanner.ScanAsync(dirPath, extensions))
.SelectMany(t => t.FilePaths)
.ToList();
return files;
}
}

View File

@ -0,0 +1,69 @@
using Microsoft.Extensions.Options;
using ZonyLrcTools.Common.Configuration;
using ZonyLrcTools.Common.Infrastructure.Exceptions;
using ZonyLrcTools.Common.Infrastructure.IO;
using ZonyLrcTools.Common.Infrastructure.Logging;
using ZonyLrcTools.Common.Infrastructure.Threading;
using ZonyLrcTools.Common.TagInfo;
namespace ZonyLrcTools.Common;
public class MusicInfoLoader : IMusicInfoLoader
{
private readonly IWarpLogger _logger;
private readonly IFileScanner _fileScanner;
private readonly ITagLoader _tagLoader;
private readonly GlobalOptions _options;
public MusicInfoLoader(IWarpLogger logger,
ITagLoader tagLoader,
IFileScanner fileScanner,
IOptions<GlobalOptions> options)
{
_logger = logger;
_tagLoader = tagLoader;
_fileScanner = fileScanner;
_options = options.Value;
}
public async Task<List<MusicInfo?>> LoadAsync(string dirPath,
int parallelCount = 2,
CancellationToken cancellationToken = default)
{
var files = (await _fileScanner.ScanMusicFilesAsync(dirPath, _options.SupportFileExtensions)).ToList();
if (files.Count == 0)
{
await _logger.ErrorAsync("没有找到任何音乐文件。");
throw new ErrorCodeException(ErrorCodes.NoFilesWereScanned);
}
await _logger.InfoAsync($"已经扫描到了 {files.Count} 个音乐文件。");
return await LoadAsync(files, parallelCount, cancellationToken);
}
public async Task<List<MusicInfo?>> LoadAsync(IReadOnlyCollection<string> filePaths,
int parallelCount = 2,
CancellationToken cancellationToken = default)
{
await _logger.InfoAsync("开始加载音乐文件的标签信息...");
var warpTask = new WarpTask(parallelCount);
var warpTaskList = filePaths.Select(file =>
warpTask.RunAsync(() =>
Task.Run(async () =>
await _tagLoader.LoadTagAsync(file),
cancellationToken),
cancellationToken));
var result = (await Task.WhenAll(warpTaskList))
.Where(m => m != null)
.Where(m => !string.IsNullOrEmpty(m?.Name) || !string.IsNullOrEmpty(m?.Artist))
.ToList();
await _logger.InfoAsync($"已成功加载 {filePaths.Count} 个音乐文件的标签信息。");
return result;
}
}

View File

@ -1,15 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using ZonyLrcTools.Common; using ZonyLrcTools.Cli.Infrastructure.Tag;
using ZonyLrcTools.Common.Configuration; using ZonyLrcTools.Common.Configuration;
using ZonyLrcTools.Common.Infrastructure.DependencyInject; using ZonyLrcTools.Common.Infrastructure.DependencyInject;
using ZonyLrcTools.Common.Infrastructure.Exceptions; using ZonyLrcTools.Common.Infrastructure.Exceptions;
namespace ZonyLrcTools.Cli.Infrastructure.Tag namespace ZonyLrcTools.Common.TagInfo
{ {
/// <summary> /// <summary>
/// 默认的标签加载器 <see cref="ITagLoader"/> 实现。 /// 默认的标签加载器 <see cref="ITagLoader"/> 实现。
@ -37,7 +33,7 @@ namespace ZonyLrcTools.Cli.Infrastructure.Tag
_sortedTagInfoProviders = GetTagInfoProviders(); _sortedTagInfoProviders = GetTagInfoProviders();
} }
public virtual async ValueTask<MusicInfo> LoadTagAsync(string filePath) public virtual async ValueTask<MusicInfo?> LoadTagAsync(string filePath)
{ {
foreach (var provider in _sortedTagInfoProviders) foreach (var provider in _sortedTagInfoProviders)
{ {

View File

@ -1,7 +1,4 @@
using System.Threading.Tasks; namespace ZonyLrcTools.Common.TagInfo
using ZonyLrcTools.Common;
namespace ZonyLrcTools.Cli.Infrastructure.Tag
{ {
/// <summary> /// <summary>
/// 标签加载器,用于加载文件的音乐标签信息。 /// 标签加载器,用于加载文件的音乐标签信息。
@ -13,6 +10,6 @@ namespace ZonyLrcTools.Cli.Infrastructure.Tag
/// </summary> /// </summary>
/// <param name="filePath">歌曲文件的路径。</param> /// <param name="filePath">歌曲文件的路径。</param>
/// <returns>加载完成的歌曲信息。</returns> /// <returns>加载完成的歌曲信息。</returns>
ValueTask<MusicInfo> LoadTagAsync(string filePath); ValueTask<MusicInfo?> LoadTagAsync(string filePath);
} }
} }

View File

@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection;
using Shouldly; using Shouldly;
using Xunit; using Xunit;
using ZonyLrcTools.Cli.Infrastructure.Tag; using ZonyLrcTools.Cli.Infrastructure.Tag;
using ZonyLrcTools.Common.TagInfo;
namespace ZonyLrcTools.Tests.Infrastructure.Tag namespace ZonyLrcTools.Tests.Infrastructure.Tag
{ {