fix: Fixed the issue where Kuwo Music could not download lyrics.

This commit is contained in:
real-zony
2023-12-22 13:52:28 +08:00
parent 2ce7b00d14
commit fea5e1124f
4 changed files with 80 additions and 35 deletions

View File

@@ -4,13 +4,49 @@ namespace ZonyLrcTools.Common.Lyrics.Providers.KuWo.JsonModel;
public class SongSearchRequest public class SongSearchRequest
{ {
[JsonProperty("key")] public string Keyword { get; set; } [JsonProperty("all")] public string Keyword { get; set; }
[JsonProperty("pn")] public int PageNumber { get; } [JsonProperty("pn")] public int PageNumber { get; }
[JsonProperty("rn")] public int PageSize { get; } [JsonProperty("rn")] public int PageSize { get; }
public SongSearchRequest(string name, string artist, int pageNumber = 1, int pageSize = 20) [JsonProperty("ft")] public string Unknown1 { get; } = "music";
[JsonProperty("newsearch")] public string Unknown2 { get; } = "1";
[JsonProperty("alflac")] public string Unknown3 { get; } = "1";
[JsonProperty("itemset")] public string Unknown4 { get; } = "web_2013";
[JsonProperty("client")] public string Unknown5 { get; } = "kt";
[JsonProperty("cluster")] public string Unknown6 { get; } = "0";
[JsonProperty("vermerge")] public string Unknown7 { get; } = "1";
[JsonProperty("rformat")] public string Unknown8 { get; } = "json";
[JsonProperty("encoding")] public string Unknown9 { get; } = "utf8";
[JsonProperty("show_copyright_off")] public string Unknown10 { get; } = "1";
[JsonProperty("pcmp4")] public string Unknown11 { get; } = "1";
[JsonProperty("ver")] public string Unknown12 { get; } = "mbox";
[JsonProperty("plat")] public string Unknown13 { get; } = "pc";
[JsonProperty("vipver")] public string Unknown14 { get; } = "MUSIC_9.2.0.0_W6";
[JsonProperty("devid")] public string Unknown15 { get; } = "11404450";
[JsonProperty("newver")] public string Unknown16 { get; } = "1";
[JsonProperty("issubtitle")] public string Unknown17 { get; } = "1";
[JsonProperty("pcjson")] public string Unknown18 { get; } = "1";
public SongSearchRequest(string name, string artist, int pageNumber = 0, int pageSize = 20)
{ {
Keyword = $"{name} {artist}"; Keyword = $"{name} {artist}";
PageNumber = pageNumber; PageNumber = pageNumber;

View File

@@ -4,15 +4,14 @@ namespace ZonyLrcTools.Common.Lyrics.Providers.KuWo.JsonModel;
public class SongSearchResponse public class SongSearchResponse
{ {
[JsonProperty("code")] public int Code { get; set; } [JsonProperty("TOTAL")] public int TotalCount { get; set; }
[JsonProperty("data")] public SongSearchResponseInnerData InnerData { get; set; } = null!; [JsonProperty("abslist")]
public IList<SongSearchResponseSongDetail> SongList { get; set; }
[JsonProperty("msg")] public string? ErrorMessage { get; set; }
public long GetMatchedMusicId(string musicName, string artistName, long? duration) public long GetMatchedMusicId(string musicName, string artistName, long? duration)
{ {
var prefectMatch = InnerData.SongItems.FirstOrDefault(x => x.Name == musicName && x.Artist == artistName); var prefectMatch = SongList.FirstOrDefault(x => x.Name == musicName && x.Artist == artistName);
if (prefectMatch != null) if (prefectMatch != null)
{ {
return prefectMatch.MusicId; return prefectMatch.MusicId;
@@ -20,27 +19,42 @@ public class SongSearchResponse
if (duration is null or 0) if (duration is null or 0)
{ {
return InnerData.SongItems.First().MusicId; return SongList.First().MusicId;
} }
return InnerData.SongItems.OrderBy(t => Math.Abs(t.Duration - duration.Value)).First().MusicId; return SongList.OrderBy(t => Math.Abs(t.Duration - duration.Value)).First().MusicId;
} }
} }
public class SongSearchResponseInnerData public class SongSearchResponseSongDetail
{ {
[JsonProperty("total")] public string? Total { get; set; } /// <summary>
/// 专辑名称。
/// </summary>
[JsonProperty("ALBUM")]
public string Album { get; set; }
[JsonProperty("list")] public ICollection<SongSearchResponseDetail> SongItems { get; set; } = null!; /// <summary>
} /// 歌手名称。
/// </summary>
[JsonProperty("ARTIST")]
public string Artist { get; set; }
public class SongSearchResponseDetail /// <summary>
{ /// 歌曲名称。
[JsonProperty("artist")] public string? Artist { get; set; } /// </summary>
[JsonProperty("SONGNAME")]
public string Name { get; set; }
[JsonProperty("name")] public string? Name { get; set; } /// <summary>
/// 歌曲的 ID。
/// </summary>
[JsonProperty("DC_TARGETID")]
public long MusicId { get; set; }
[JsonProperty("rid")] public long MusicId { get; set; } /// <summary>
/// 歌曲的时间长度。
[JsonProperty("duration")] public long Duration { get; set; } /// </summary>
[JsonProperty("DURATION")]
public long Duration { get; set; }
} }

View File

@@ -13,29 +13,27 @@ public class KuWoLyricsProvider : LyricsProvider
{ {
public override string DownloaderName => InternalLyricsProviderNames.KuWo; public override string DownloaderName => InternalLyricsProviderNames.KuWo;
private const string KuWoSearchMusicUrl = @"https://www.kuwo.cn/api/www/search/searchMusicBykeyWord"; private const string KuWoSearchMusicUrl = @"https://search.kuwo.cn/r.s";
private const string KuWoSearchLyricsUrl = @"https://m.kuwo.cn/newh5/singles/songinfoandlrc"; private const string KuWoSearchLyricsUrl = @"https://m.kuwo.cn/newh5/singles/songinfoandlrc";
private const string KuWoDefaultToken = "ABCDE12345"; private const string KuWoDefaultToken = "ABCDE12345";
private readonly IWarpHttpClient _warpHttpClient; private readonly IWarpHttpClient _warpHttpClient;
private readonly ILyricsItemCollectionFactory _lyricsItemCollectionFactory;
private readonly GlobalOptions _options; private readonly GlobalOptions _options;
private static readonly ProductInfoHeaderValue UserAgent = new("Chrome", "81.0.4044.138"); private static readonly ProductInfoHeaderValue UserAgent = new("Chrome", "81.0.4044.138");
public KuWoLyricsProvider(IWarpHttpClient warpHttpClient, public KuWoLyricsProvider(IWarpHttpClient warpHttpClient,
ILyricsItemCollectionFactory lyricsItemCollectionFactory,
IOptions<GlobalOptions> options) IOptions<GlobalOptions> options)
{ {
_warpHttpClient = warpHttpClient; _warpHttpClient = warpHttpClient;
_lyricsItemCollectionFactory = lyricsItemCollectionFactory;
_options = options.Value; _options = options.Value;
} }
protected override async ValueTask<object> DownloadDataAsync(LyricsProviderArgs args) protected override async ValueTask<object> DownloadDataAsync(LyricsProviderArgs args)
{ {
var songSearchResponse = await _warpHttpClient.GetAsync<SongSearchResponse>(KuWoSearchMusicUrl, var songSearchResponse = await _warpHttpClient.GetAsync<SongSearchResponse>(KuWoSearchMusicUrl,
new SongSearchRequest(args.SongName, args.Artist, pageSize: _options.Provider.Lyric.GetLyricProviderOption(DownloaderName).Depth), new SongSearchRequest(args.SongName, args.Artist,
pageSize: _options.Provider.Lyric.GetLyricProviderOption(DownloaderName).Depth),
op => op =>
{ {
op.Headers.UserAgent.Add(UserAgent); op.Headers.UserAgent.Add(UserAgent);
@@ -55,7 +53,8 @@ public class KuWoLyricsProvider : LyricsProvider
}); });
} }
protected override async ValueTask<LyricsItemCollection> GenerateLyricAsync(object lyricsObject, LyricsProviderArgs args) protected override async ValueTask<LyricsItemCollection> GenerateLyricAsync(object lyricsObject,
LyricsProviderArgs args)
{ {
await ValueTask.CompletedTask; await ValueTask.CompletedTask;
@@ -69,7 +68,8 @@ public class KuWoLyricsProvider : LyricsProvider
{ {
var position = double.Parse(l.Position); var position = double.Parse(l.Position);
var positionSpan = TimeSpan.FromSeconds(position); var positionSpan = TimeSpan.FromSeconds(position);
return new LyricsItem(positionSpan.Minutes, double.Parse($"{positionSpan.Seconds}.{positionSpan.Milliseconds}"), l.Text); return new LyricsItem(positionSpan.Minutes,
double.Parse($"{positionSpan.Seconds}.{positionSpan.Milliseconds}"), l.Text);
}); });
var lyricsItemCollection = new LyricsItemCollection(_options.Provider.Lyric.Config); var lyricsItemCollection = new LyricsItemCollection(_options.Provider.Lyric.Config);
@@ -79,12 +79,7 @@ public class KuWoLyricsProvider : LyricsProvider
protected virtual void ValidateSongSearchResponse(SongSearchResponse response, LyricsProviderArgs args) protected virtual void ValidateSongSearchResponse(SongSearchResponse response, LyricsProviderArgs args)
{ {
if (response.Code != 200) if (response.TotalCount == 0)
{
throw new ErrorCodeException(ErrorCodes.TheReturnValueIsIllegal, response.ErrorMessage, args);
}
if (response.InnerData.SongItems.Count == 0)
{ {
throw new ErrorCodeException(ErrorCodes.NoMatchingSong, attachObj: args); throw new ErrorCodeException(ErrorCodes.NoMatchingSong, attachObj: args);
} }

View File

@@ -17,7 +17,7 @@ public class KuWoLyricsProviderTests : TestBase
.FirstOrDefault(t => t.DownloaderName == InternalLyricsProviderNames.KuWo); .FirstOrDefault(t => t.DownloaderName == InternalLyricsProviderNames.KuWo);
} }
[Fact(Skip = "Not Working")] [Fact]
[Trait("LyricsProvider ", "KuGou")] [Trait("LyricsProvider ", "KuGou")]
public async Task DownloadAsync_Test() public async Task DownloadAsync_Test()
{ {
@@ -26,7 +26,7 @@ public class KuWoLyricsProviderTests : TestBase
lyric.IsPruneMusic.ShouldBeFalse(); lyric.IsPruneMusic.ShouldBeFalse();
} }
[Fact(Skip = "Not Working")] [Fact]
public async Task DownloadAsync_Source_Null_Test() public async Task DownloadAsync_Source_Null_Test()
{ {
var lyric = await _kuwoLyricsProvider.DownloadAsync("Concerto for Piano and Orchestra No. 12 in A major, K414 - 1. Allegro", var lyric = await _kuwoLyricsProvider.DownloadAsync("Concerto for Piano and Orchestra No. 12 in A major, K414 - 1. Allegro",