refactor: Refactor lyrics download logic and abstract a new logger.

This commit is contained in:
real-zony 2022-10-23 13:38:51 +08:00
parent 3e27e18098
commit 7d17fc0b97
18 changed files with 245 additions and 163 deletions

View File

@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using McMaster.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using ZonyLrcTools.Cli.Infrastructure.Tag;
using ZonyLrcTools.Common;
@ -15,6 +12,7 @@ using ZonyLrcTools.Common.Configuration;
using ZonyLrcTools.Common.Infrastructure.Exceptions;
using ZonyLrcTools.Common.Infrastructure.Extensions;
using ZonyLrcTools.Common.Infrastructure.IO;
using ZonyLrcTools.Common.Infrastructure.Logging;
using ZonyLrcTools.Common.Infrastructure.Threading;
using ZonyLrcTools.Common.Lyrics;
using File = System.IO.File;
@ -24,26 +22,25 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
[Command("download", Description = "下载歌词文件或专辑图像。")]
public class DownloadCommand : ToolCommandBase
{
private readonly ILogger<DownloadCommand> _logger;
private readonly ILyricsDownloader _lyricsDownloader;
private readonly IFileScanner _fileScanner;
private readonly ITagLoader _tagLoader;
private readonly IEnumerable<ILyricsProvider> _lyricDownloaderList;
private readonly IEnumerable<IAlbumDownloader> _albumDownloaderList;
private readonly ITagLoader _tagLoader;
private readonly IWarpLogger _logger;
private readonly GlobalOptions _options;
public DownloadCommand(ILogger<DownloadCommand> logger,
IFileScanner fileScanner,
public DownloadCommand(IFileScanner fileScanner,
IOptions<GlobalOptions> options,
IEnumerable<IAlbumDownloader> albumDownloaderList,
ITagLoader tagLoader,
IEnumerable<ILyricsProvider> lyricDownloaderList,
IEnumerable<IAlbumDownloader> albumDownloaderList)
ILyricsDownloader lyricsDownloader, IWarpLogger logger)
{
_logger = logger;
_fileScanner = fileScanner;
_tagLoader = tagLoader;
_lyricDownloaderList = lyricDownloaderList;
_albumDownloaderList = albumDownloaderList;
_tagLoader = tagLoader;
_lyricsDownloader = lyricsDownloader;
_logger = logger;
_options = options.Value;
}
@ -62,18 +59,14 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
[Option("-n|--number", CommandOptionType.SingleValue, Description = "指定下载时候的线程数量。(默认值 2)")]
public int ParallelNumber { get; set; } = 2;
[Option] public string ErrorMessage { get; set; } = Path.Combine(Directory.GetCurrentDirectory(), "error.log");
#endregion
protected override async Task<int> OnExecuteAsync(CommandLineApplication app)
{
if (DownloadLyric)
{
await DownloadLyricFilesAsync(
await LoadMusicInfoAsync(
RemoveExistLyricFiles(
await ScanMusicFilesAsync())));
var musicInfos = await LoadMusicInfoAsync(RemoveExistLyricFiles(await ScanMusicFilesAsync()));
await _lyricsDownloader.DownloadAsync(musicInfos.ToList(), ParallelNumber);
}
if (DownloadAlbum)
@ -94,11 +87,11 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
if (files.Count == 0)
{
_logger.LogError("没有找到任何音乐文件。");
await _logger.ErrorAsync("没有找到任何音乐文件。");
throw new ErrorCodeException(ErrorCodes.NoFilesWereScanned);
}
_logger.LogInformation($"已经扫描到了 {files.Count} 个音乐文件。");
await _logger.InfoAsync($"已经扫描到了 {files.Count} 个音乐文件。");
return files;
}
@ -118,7 +111,7 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
return true;
}
_logger.LogWarning($"已经存在歌词文件 {path},跳过。");
_logger.WarnAsync($"已经存在歌词文件 {path},跳过。").GetAwaiter().GetResult();
return false;
})
.ToList();
@ -126,7 +119,7 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
private async Task<ImmutableList<MusicInfo>> LoadMusicInfoAsync(IReadOnlyCollection<string> files)
{
_logger.LogInformation("开始加载音乐文件的标签信息...");
await _logger.InfoAsync("开始加载音乐文件的标签信息...");
var warpTask = new WarpTask(ParallelNumber);
var warpTaskList = files.Select(file => warpTask.RunAsync(() => Task.Run(async () => await _tagLoader.LoadTagAsync(file))));
@ -138,111 +131,16 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
// Load music total time info.
// result.Foreach(m => { m.TotalTime = (long?)new AudioFileReader(m.FilePath).TotalTime.TotalMilliseconds; });
_logger.LogInformation($"已成功加载 {files.Count} 个音乐文件的标签信息。");
await _logger.InfoAsync($"已成功加载 {files.Count} 个音乐文件的标签信息。");
return result.ToImmutableList();
}
private IEnumerable<ILyricsProvider> GetLyricDownloaderList()
{
var downloader = _options.Provider.Lyric.Plugin
.Where(op => op.Priority != -1)
.OrderBy(op => op.Priority)
.Join(_lyricDownloaderList,
op => op.Name,
loader => loader.DownloaderName,
(op, loader) => loader);
return downloader;
}
#region > Lyric download logic <
private async ValueTask DownloadLyricFilesAsync(ImmutableList<MusicInfo> musicInfos)
{
_logger.LogInformation("开始下载歌词文件数据...");
var downloaderList = GetLyricDownloaderList();
var warpTask = new WarpTask(ParallelNumber);
var warpTaskList = musicInfos.Select(info =>
warpTask.RunAsync(() => Task.Run(async () => await DownloadLyricTaskLogicAsync(downloaderList, info))));
await Task.WhenAll(warpTaskList);
_logger.LogInformation($"歌词数据下载完成,成功: {musicInfos.Count(m => m.IsSuccessful)} 失败{musicInfos.Count(m => m.IsSuccessful == false)}。");
}
private async Task DownloadLyricTaskLogicAsync(IEnumerable<ILyricsProvider> downloaderList, MusicInfo info)
{
async Task InternalDownloadLogicAsync(ILyricsProvider downloader)
{
try
{
var lyric = await downloader.DownloadAsync(info.Name, info.Artist, info.TotalTime);
var lyricFilePath = Path.Combine(Path.GetDirectoryName(info.FilePath)!,
$"{Path.GetFileNameWithoutExtension(info.FilePath)}.lrc");
if (File.Exists(lyricFilePath))
{
File.Delete(lyricFilePath);
}
info.IsSuccessful = true;
if (lyric.IsPruneMusic)
{
return;
}
await using var stream = new FileStream(lyricFilePath, FileMode.Create);
await using var sw = new BinaryWriter(stream);
sw.Write(EncodingConvert(lyric));
await stream.FlushAsync();
}
catch (ErrorCodeException ex)
{
info.IsSuccessful = ex.ErrorCode == ErrorCodes.NoMatchingSong;
_logger.LogWarningInfo(ex);
}
catch (Exception ex)
{
_logger.LogError($"下载歌词文件时发生错误:{ex.Message},歌曲名: {info.Name},歌手: {info.Artist}。");
info.IsSuccessful = false;
}
}
foreach (var downloader in downloaderList)
{
await InternalDownloadLogicAsync(downloader);
if (info.IsSuccessful)
{
_logger.LogSuccessful(info);
return;
}
}
}
private byte[] EncodingConvert(LyricItemCollection lyric)
{
var supportEncodings = Encoding.GetEncodings();
if (supportEncodings.All(x => x.Name != _options.Provider.Lyric.Config.FileEncoding))
{
throw new ErrorCodeException(ErrorCodes.NotSupportedFileEncoding);
}
return Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(_options.Provider.Lyric.Config.FileEncoding), lyric.GetUtf8Bytes());
}
#endregion
#region > Ablum image download logic <
private async ValueTask DownloadAlbumAsync(ImmutableList<MusicInfo> musicInfos)
{
_logger.LogInformation("开始下载专辑图像数据...");
await _logger.InfoAsync("开始下载专辑图像数据...");
var downloader = _albumDownloaderList.FirstOrDefault(d => d.DownloaderName == InternalAlbumDownloaderNames.NetEase);
var warpTask = new WarpTask(ParallelNumber);
@ -251,7 +149,7 @@ namespace ZonyLrcTools.Cli.Commands.SubCommand
await Task.WhenAll(warpTaskList);
_logger.LogInformation($"专辑数据下载完成,成功: {musicInfos.Count(m => m.IsSuccessful)} 失败{musicInfos.Count(m => m.IsSuccessful == false)}。");
await _logger.InfoAsync($"专辑数据下载完成,成功: {musicInfos.Count(m => m.IsSuccessful)} 失败{musicInfos.Count(m => m.IsSuccessful == false)}。");
}
private async Task DownloadAlbumTaskLogicAsync(IAlbumDownloader downloader, MusicInfo info)

View File

@ -0,0 +1,42 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ZonyLrcTools.Common.Infrastructure.DependencyInject;
using ZonyLrcTools.Common.Infrastructure.Logging;
namespace ZonyLrcTools.Cli.Infrastructure.Logging;
public class SerilogWarpLogger : IWarpLogger, ITransientDependency
{
private readonly ILogger<SerilogWarpLogger> _logger;
public SerilogWarpLogger(ILogger<SerilogWarpLogger> logger)
{
_logger = logger;
}
public Task DebugAsync(string message, Exception exception = null)
{
_logger.LogDebug(message, exception);
return Task.CompletedTask;
}
public Task InfoAsync(string message, Exception exception = null)
{
_logger.LogInformation(message, exception);
return Task.CompletedTask;
}
public Task WarnAsync(string message, Exception exception = null)
{
_logger.LogWarning(message, exception);
return Task.CompletedTask;
}
public Task ErrorAsync(string message, Exception exception = null)
{
_logger.LogError(message, exception);
return Task.CompletedTask;
}
}

View File

@ -2,6 +2,7 @@ using System.Text;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using ZonyLrcTools.Common.Infrastructure.Exceptions;
using ZonyLrcTools.Common.Infrastructure.Logging;
namespace ZonyLrcTools.Common.Infrastructure.Extensions
{
@ -16,9 +17,9 @@ namespace ZonyLrcTools.Common.Infrastructure.Extensions
/// <param name="logger">日志记录器实例。</param>
/// <param name="errorCode">错误码,具体请参考 <see cref="ErrorCodes"/> 类的定义。</param>
/// <param name="e">异常实例,可为空。</param>
public static void LogWarningWithErrorCode(this ILogger logger, int errorCode, Exception e = null)
public static void LogWarningWithErrorCode(this IWarpLogger logger, int errorCode, Exception e = null)
{
logger.LogWarning($"错误代码: {errorCode}\n堆栈异常: {e?.StackTrace}");
logger.WarnAsync($"错误代码: {errorCode}\n堆栈异常: {e?.StackTrace}").GetAwaiter().GetResult();
}
/// <summary>
@ -26,7 +27,7 @@ namespace ZonyLrcTools.Common.Infrastructure.Extensions
/// </summary>
/// <param name="logger">日志记录器的实例。</param>
/// <param name="exception">错误码异常实例。</param>
public static void LogWarningInfo(this ILogger logger, ErrorCodeException exception)
public static void LogWarningInfo(this IWarpLogger logger, ErrorCodeException exception)
{
if (exception.ErrorCode < 50000)
{
@ -36,7 +37,7 @@ namespace ZonyLrcTools.Common.Infrastructure.Extensions
var sb = new StringBuilder();
sb.Append($"错误代码: {exception.ErrorCode},信息: {ErrorCodeHelper.GetMessage(exception.ErrorCode)}");
sb.Append($"\n附加信息:\n {JsonConvert.SerializeObject(exception.AttachObject)}");
logger.LogWarning(sb.ToString());
logger.WarnAsync(sb.ToString()).GetAwaiter().GetResult();
}
/// <summary>
@ -44,9 +45,9 @@ namespace ZonyLrcTools.Common.Infrastructure.Extensions
/// </summary>
/// <param name="logger">日志记录器的实例。</param>
/// <param name="musicInfo">需要打印的歌曲信息。</param>
public static void LogSuccessful(this ILogger logger, MusicInfo musicInfo)
public static void LogSuccessful(this IWarpLogger logger, MusicInfo musicInfo)
{
logger.LogInformation($"歌曲名: {musicInfo.Name}, 艺术家: {musicInfo.Artist}, 下载成功.");
logger.InfoAsync($"歌曲名: {musicInfo.Name}, 艺术家: {musicInfo.Artist}, 下载成功.").GetAwaiter().GetResult();
}
}
}

View File

@ -4,16 +4,17 @@ using Microsoft.Extensions.Logging.Abstractions;
using ZonyLrcTools.Common.Infrastructure.DependencyInject;
using ZonyLrcTools.Common.Infrastructure.Exceptions;
using ZonyLrcTools.Common.Infrastructure.Extensions;
using ZonyLrcTools.Common.Infrastructure.Logging;
namespace ZonyLrcTools.Common.Infrastructure.IO
{
public class FileScanner : IFileScanner, ITransientDependency
{
public ILogger<FileScanner> Logger { get; set; }
private readonly IWarpLogger _logger;
public FileScanner()
public FileScanner(IWarpLogger logger)
{
Logger = NullLogger<FileScanner>.Instance;
_logger = logger;
}
public Task<List<FileScannerResult>> ScanAsync(string path, IEnumerable<string> extensions)
@ -58,7 +59,7 @@ namespace ZonyLrcTools.Common.Infrastructure.IO
}
catch (Exception e)
{
Logger.LogWarningWithErrorCode(ErrorCodes.ScanFileError, e);
_logger.LogWarningWithErrorCode(ErrorCodes.ScanFileError, e);
}
}
}

View File

@ -0,0 +1,9 @@
namespace ZonyLrcTools.Common.Infrastructure.Logging;
public interface IWarpLogger
{
Task DebugAsync(string message, Exception? exception = null);
Task InfoAsync(string message, Exception? exception = null);
Task WarnAsync(string message, Exception? exception = null);
Task ErrorAsync(string message, Exception? exception = null);
}

View File

@ -0,0 +1,127 @@
using System.Text;
using Microsoft.Extensions.Options;
using ZonyLrcTools.Common.Configuration;
using ZonyLrcTools.Common.Infrastructure.DependencyInject;
using ZonyLrcTools.Common.Infrastructure.Exceptions;
using ZonyLrcTools.Common.Infrastructure.Extensions;
using ZonyLrcTools.Common.Infrastructure.Logging;
using ZonyLrcTools.Common.Infrastructure.Threading;
namespace ZonyLrcTools.Common.Lyrics;
public class DefaultLyricsDownloader : ILyricsDownloader, ISingletonDependency
{
private readonly IEnumerable<ILyricsProvider> _lyricDownloaderList;
private readonly GlobalOptions _options;
private readonly IWarpLogger _logger;
public IEnumerable<ILyricsProvider> AvailableProviders => new Lazy<IEnumerable<ILyricsProvider>>(() =>
{
return _options.Provider.Lyric.Plugin
.Where(op => op.Priority != -1)
.OrderBy(op => op.Priority)
.Join(_lyricDownloaderList,
op => op.Name,
loader => loader.DownloaderName,
(op, loader) => loader);
}).Value;
public DefaultLyricsDownloader(IEnumerable<ILyricsProvider> lyricDownloaderList,
IOptions<GlobalOptions> options,
IWarpLogger logger)
{
_lyricDownloaderList = lyricDownloaderList;
_logger = logger;
_options = options.Value;
}
public async Task<List<MusicInfo>> DownloadAsync(List<MusicInfo> needDownloadMusicInfos,
int parallelCount = 2,
CancellationToken cancellationToken = default)
{
await _logger.InfoAsync("开始下载歌词文件数据...");
if (parallelCount <= 0)
{
parallelCount = 1;
}
var warpTask = new WarpTask(parallelCount);
var downloadTasks = needDownloadMusicInfos.Select(info =>
warpTask.RunAsync(() =>
Task.Run(async () =>
{
// Try to download lyrics from all available providers.
foreach (var lyricsProvider in AvailableProviders)
{
await DownloadAndWriteLyricsAsync(lyricsProvider, info);
if (info.IsSuccessful)
{
_logger.LogSuccessful(info);
return;
}
}
}, cancellationToken), cancellationToken));
await Task.WhenAll(downloadTasks);
await _logger.InfoAsync($"歌词数据下载完成,成功: {needDownloadMusicInfos.Count(m => m.IsSuccessful)} 失败{needDownloadMusicInfos.Count(m => m.IsSuccessful == false)}。");
return needDownloadMusicInfos;
}
private async Task DownloadAndWriteLyricsAsync(ILyricsProvider provider, MusicInfo info)
{
try
{
var lyrics = await provider.DownloadAsync(info.Name, info.Artist);
if (lyrics.IsPruneMusic)
{
info.IsSuccessful = true;
return;
}
var newLyricsFilePath = Path.Combine(Path.GetDirectoryName(info.FilePath)!,
$"{Path.GetFileNameWithoutExtension(info.FilePath)}.lrc");
if (File.Exists(newLyricsFilePath))
{
File.Delete(newLyricsFilePath);
}
// Write lyrics to file.
await using (var fileStream = new FileStream(newLyricsFilePath, FileMode.CreateNew, FileAccess.Write))
{
await using (var binaryWriter = new BinaryWriter(fileStream, Encoding.UTF8))
{
binaryWriter.Write(Utf8ToSelectedEncoding(lyrics));
binaryWriter.Flush();
}
}
info.IsSuccessful = true;
}
catch (ErrorCodeException ex)
{
_logger.LogWarningInfo(ex);
info.IsSuccessful = false;
}
catch (Exception ex)
{
await _logger.ErrorAsync($"下载歌词文件时发生错误:{ex.Message},歌曲名: {info.Name},歌手: {info.Artist}。");
info.IsSuccessful = false;
}
}
private byte[] Utf8ToSelectedEncoding(LyricsItemCollection lyrics)
{
var supportEncodings = Encoding.GetEncodings();
if (supportEncodings.All(x => x.Name != _options.Provider.Lyric.Config.FileEncoding))
{
throw new ErrorCodeException(ErrorCodes.NotSupportedFileEncoding);
}
return Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding(_options.Provider.Lyric.Config.FileEncoding), lyrics.GetUtf8Bytes());
}
}

View File

@ -2,5 +2,9 @@
public interface ILyricsDownloader
{
Task<List<MusicInfo>> DownloadAsync(List<MusicInfo> needDownloadMusicInfos,
int parallelCount = 2,
CancellationToken cancellationToken = default);
IEnumerable<ILyricsProvider> AvailableProviders { get; }
}

View File

@ -1,23 +1,23 @@
namespace ZonyLrcTools.Common.Lyrics
{
/// <summary>
/// 构建 <see cref="LyricItemCollection"/> 对象的工厂。
/// 构建 <see cref="LyricsItemCollection"/> 对象的工厂。
/// </summary>
public interface ILyricsItemCollectionFactory
{
/// <summary>
/// 根据指定的歌曲数据构建新的 <see cref="LyricItemCollection"/> 实例。
/// 根据指定的歌曲数据构建新的 <see cref="LyricsItemCollection"/> 实例。
/// </summary>
/// <param name="sourceLyric">原始歌词数据。</param>
/// <returns>构建完成的 <see cref="LyricItemCollection"/> 对象。</returns>
LyricItemCollection Build(string sourceLyric);
/// <returns>构建完成的 <see cref="LyricsItemCollection"/> 对象。</returns>
LyricsItemCollection Build(string sourceLyric);
/// <summary>
/// 根据指定的歌曲数据构建新的 <see cref="LyricItemCollection"/> 实例。
/// 根据指定的歌曲数据构建新的 <see cref="LyricsItemCollection"/> 实例。
/// </summary>
/// <param name="sourceLyric">原始歌词数据。</param>
/// <param name="translationLyric">翻译歌词数据。</param>
/// <returns>构建完成的 <see cref="LyricItemCollection"/> 对象。</returns>
LyricItemCollection Build(string sourceLyric, string translationLyric);
/// <returns>构建完成的 <see cref="LyricsItemCollection"/> 对象。</returns>
LyricsItemCollection Build(string sourceLyric, string translationLyric);
}
}

View File

@ -12,7 +12,7 @@ namespace ZonyLrcTools.Common.Lyrics
/// <param name="artist">歌曲的作者。</param>
/// <param name="duration">歌曲的时长。</param>
/// <returns>歌曲的歌词数据对象。</returns>
ValueTask<LyricItemCollection> DownloadAsync(string songName, string artist, long? duration = null);
ValueTask<LyricsItemCollection> DownloadAsync(string songName, string artist, long? duration = null);
/// <summary>
/// 下载器的名称。

View File

@ -2,6 +2,6 @@ namespace ZonyLrcTools.Common.Lyrics
{
public interface ILyricsTextResolver
{
LyricItemCollection Resolve(string lyricText);
LyricsItemCollection Resolve(string lyricText);
}
}

View File

@ -3,7 +3,7 @@ using System.Text.RegularExpressions;
namespace ZonyLrcTools.Common.Lyrics
{
/// <summary>
/// 歌词的行对象,是 <see cref="LyricItemCollection"/> 的最小单位。。
/// 歌词的行对象,是 <see cref="LyricsItemCollection"/> 的最小单位。。
/// </summary>
public class LyricsItem : IComparable<LyricsItem>
{

View File

@ -7,7 +7,7 @@ namespace ZonyLrcTools.Common.Lyrics
/// <summary>
/// 歌词数据,包含多条歌词行对象(<see cref="LyricsItem"/>)。
/// </summary>
public class LyricItemCollection : List<LyricsItem>
public class LyricsItemCollection : List<LyricsItem>
{
/// <summary>
/// 是否为纯音乐,当没有任何歌词数据的时候,属性值为 True。
@ -16,12 +16,12 @@ namespace ZonyLrcTools.Common.Lyrics
public GlobalLyricsConfigOptions Options { get; private set; }
public LyricItemCollection(GlobalLyricsConfigOptions options)
public LyricsItemCollection(GlobalLyricsConfigOptions options)
{
Options = options;
}
public static LyricItemCollection operator +(LyricItemCollection left, LyricItemCollection right)
public static LyricsItemCollection operator +(LyricsItemCollection left, LyricsItemCollection right)
{
if (right.IsPruneMusic)
{
@ -29,7 +29,7 @@ namespace ZonyLrcTools.Common.Lyrics
}
var option = left.Options;
var newCollection = new LyricItemCollection(option);
var newCollection = new LyricsItemCollection(option);
var indexDiff = left.Count - right.Count;
if (!option.IsOneLine)
{
@ -91,7 +91,7 @@ namespace ZonyLrcTools.Common.Lyrics
/// 这个索引字典用于标识每个索引的歌词是否被处理,为 True 则为已处理,为 False 为未处理。
/// </remarks>
/// <param name="items">等待构建的歌词集合实例。</param>
private static Dictionary<int, bool> BuildMarkDictionary(LyricItemCollection items)
private static Dictionary<int, bool> BuildMarkDictionary(LyricsItemCollection items)
{
return items
.Select((item, index) => new { index, item })

View File

@ -17,9 +17,9 @@ namespace ZonyLrcTools.Common.Lyrics
_options = options.Value;
}
public LyricItemCollection Build(string sourceLyric)
public LyricsItemCollection Build(string sourceLyric)
{
var lyric = new LyricItemCollection(_options.Provider.Lyric.Config);
var lyric = new LyricsItemCollection(_options.Provider.Lyric.Config);
if (string.IsNullOrEmpty(sourceLyric))
{
return lyric;
@ -30,9 +30,9 @@ namespace ZonyLrcTools.Common.Lyrics
return lyric;
}
public LyricItemCollection Build(string sourceLyric, string translationLyric)
public LyricsItemCollection Build(string sourceLyric, string translationLyric)
{
var lyric = new LyricItemCollection(_options.Provider.Lyric.Config);
var lyric = new LyricsItemCollection(_options.Provider.Lyric.Config);
if (string.IsNullOrEmpty(sourceLyric))
{
return lyric;
@ -42,7 +42,7 @@ namespace ZonyLrcTools.Common.Lyrics
if (_options.Provider.Lyric.Config.IsEnableTranslation && !string.IsNullOrEmpty(translationLyric))
{
var translatedLyric = InternalBuildLyricObject(new LyricItemCollection(_options.Provider.Lyric.Config), translationLyric);
var translatedLyric = InternalBuildLyricObject(new LyricsItemCollection(_options.Provider.Lyric.Config), translationLyric);
if (_options.Provider.Lyric.Config.IsOnlyOutputTranslation)
{
return translatedLyric;
@ -54,15 +54,15 @@ namespace ZonyLrcTools.Common.Lyrics
return lyric;
}
private LyricItemCollection InternalBuildLyricObject(LyricItemCollection lyric, string sourceText)
private LyricsItemCollection InternalBuildLyricObject(LyricsItemCollection lyrics, string sourceText)
{
var regex = new Regex(@"\[\d+:\d+.\d+\].+\n?");
foreach (Match match in regex.Matches(sourceText))
{
lyric.Add(new LyricsItem(match.Value));
lyrics.Add(new LyricsItem(match.Value));
}
return lyric;
return lyrics;
}
}
}

View File

@ -17,7 +17,7 @@ namespace ZonyLrcTools.Common.Lyrics
/// <param name="artist">歌曲作者/艺术家。</param>
/// <param name="duration">歌曲的时长。</param>
/// <returns>下载完成的歌曲数据。</returns>
public virtual async ValueTask<LyricItemCollection> DownloadAsync(string songName, string artist, long? duration = null)
public virtual async ValueTask<LyricsItemCollection> DownloadAsync(string songName, string artist, long? duration = null)
{
var args = new LyricsProviderArgs(songName, artist, duration ?? 0);
await ValidateAsync(args);
@ -53,6 +53,6 @@ namespace ZonyLrcTools.Common.Lyrics
/// 根据指定的歌词二进制数据,生成歌词数据。
/// </summary>
/// <param name="data">歌词的原始二进制数据。</param>
protected abstract ValueTask<LyricItemCollection> GenerateLyricAsync(byte[] data, LyricsProviderArgs args);
protected abstract ValueTask<LyricsItemCollection> GenerateLyricAsync(byte[] data, LyricsProviderArgs args);
}
}

View File

@ -47,7 +47,7 @@ namespace ZonyLrcTools.Common.Lyrics.Providers.KuGou
return Encoding.UTF8.GetBytes(lyricResponse);
}
protected override async ValueTask<LyricItemCollection> GenerateLyricAsync(byte[] data, LyricsProviderArgs args)
protected override async ValueTask<LyricsItemCollection> GenerateLyricAsync(byte[] data, LyricsProviderArgs args)
{
await ValueTask.CompletedTask;
var lyricJsonObj = JObject.Parse(Encoding.UTF8.GetString(data));

View File

@ -57,19 +57,19 @@ namespace ZonyLrcTools.Common.Lyrics.Providers.NetEase
return Encoding.UTF8.GetBytes(lyricResponse);
}
protected override async ValueTask<LyricItemCollection> GenerateLyricAsync(byte[] data, LyricsProviderArgs args)
protected override async ValueTask<LyricsItemCollection> GenerateLyricAsync(byte[] data, LyricsProviderArgs args)
{
await ValueTask.CompletedTask;
var json = JsonConvert.DeserializeObject<GetLyricResponse>(Encoding.UTF8.GetString(data));
if (json?.OriginalLyric == null || string.IsNullOrEmpty(json.OriginalLyric.Text))
{
return new LyricItemCollection(null);
return new LyricsItemCollection(null);
}
if (json.OriginalLyric.Text.Contains("纯音乐,请欣赏"))
{
return new LyricItemCollection(null);
return new LyricsItemCollection(null);
}
return _lyricsItemCollectionFactory.Build(

View File

@ -42,7 +42,7 @@ namespace ZonyLrcTools.Common.Lyrics.Providers.QQMusic
return Encoding.UTF8.GetBytes(lyricJsonString);
}
protected override async ValueTask<LyricItemCollection> GenerateLyricAsync(byte[] data, LyricsProviderArgs args)
protected override async ValueTask<LyricsItemCollection> GenerateLyricAsync(byte[] data, LyricsProviderArgs args)
{
await ValueTask.CompletedTask;

View File

@ -10,7 +10,7 @@ namespace ZonyLrcTools.Tests.Infrastructure.Lyric
[Fact]
public void LyricCollectionLineBreak_Test()
{
var lyricObject = new LyricItemCollection(new GlobalLyricsConfigOptions
var lyricObject = new LyricsItemCollection(new GlobalLyricsConfigOptions
{
IsOneLine = false,
LineBreak = LineBreakType.MacOs