mirror of
https://github.com/real-zony/ZonyLrcToolsX.git
synced 2025-09-05 21:16:52 +00:00
refactor: Common components are moved to the Common library.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ZonyLrcTools.Common.Lyrics.Providers.KuGou.JsonModel
|
||||
{
|
||||
public class GetLyricAccessKeyRequest
|
||||
{
|
||||
[JsonProperty("ver")] public int UnknownParameters1 { get; }
|
||||
|
||||
[JsonProperty("man")] public string UnknownParameters2 { get; }
|
||||
|
||||
[JsonProperty("client")] public string UnknownParameters3 { get; }
|
||||
|
||||
[JsonProperty("hash")] public string FileHash { get; }
|
||||
|
||||
public GetLyricAccessKeyRequest(string fileHash)
|
||||
{
|
||||
UnknownParameters1 = 1;
|
||||
UnknownParameters2 = "yes";
|
||||
UnknownParameters3 = "mobi";
|
||||
FileHash = fileHash;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ZonyLrcTools.Common.Lyrics.Providers.KuGou.JsonModel
|
||||
{
|
||||
public class GetLyricAccessKeyResponse
|
||||
{
|
||||
[JsonProperty("status")] public int Status { get; set; }
|
||||
|
||||
[JsonProperty("errcode")] public int ErrorCode { get; set; }
|
||||
|
||||
[JsonProperty("candidates")] public List<GetLyricAccessKeyDataObject> AccessKeyDataObjects { get; set; }
|
||||
}
|
||||
|
||||
public class GetLyricAccessKeyDataObject
|
||||
{
|
||||
[JsonProperty("accesskey")] public string AccessKey { get; set; }
|
||||
|
||||
[JsonProperty("id")] public string Id { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ZonyLrcTools.Common.Lyrics.Providers.KuGou.JsonModel
|
||||
{
|
||||
public class GetLyricRequest
|
||||
{
|
||||
[JsonProperty("ver")] public int UnknownParameters1 { get; }
|
||||
|
||||
[JsonProperty("client")] public string UnknownParameters2 { get; }
|
||||
|
||||
[JsonProperty("fmt")] public string UnknownParameters3 { get; }
|
||||
|
||||
[JsonProperty("charset")] public string UnknownParameters4 { get; }
|
||||
|
||||
[JsonProperty("id")] public string Id { get; }
|
||||
|
||||
[JsonProperty("accesskey")] public string AccessKey { get; }
|
||||
|
||||
public GetLyricRequest(string id, string accessKey)
|
||||
{
|
||||
UnknownParameters1 = 1;
|
||||
UnknownParameters2 = "iphone";
|
||||
UnknownParameters3 = "lrc";
|
||||
UnknownParameters4 = "utf8";
|
||||
Id = id;
|
||||
AccessKey = accessKey;
|
||||
}
|
||||
}
|
||||
|
||||
public class GetLyricResponse
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ZonyLrcTools.Common.Lyrics.Providers.KuGou.JsonModel
|
||||
{
|
||||
public class SongSearchRequest
|
||||
{
|
||||
[JsonProperty("filter")] public int Filter { get; }
|
||||
|
||||
[JsonProperty("platform")] public string Platform { get; }
|
||||
|
||||
[JsonProperty("keyword")] public string Keyword { get; }
|
||||
|
||||
[JsonProperty("pagesize")] public int PageSize { get; }
|
||||
|
||||
[JsonProperty("page")] public int Page { get; }
|
||||
|
||||
public SongSearchRequest(string musicName, string artistName, int pageSize = 30)
|
||||
{
|
||||
Filter = 2;
|
||||
Platform = "WebFilter";
|
||||
Keyword = HttpUtility.UrlEncode($"{musicName}+{artistName}", Encoding.UTF8);
|
||||
PageSize = pageSize;
|
||||
Page = 1;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ZonyLrcTools.Common.Lyrics.Providers.KuGou.JsonModel
|
||||
{
|
||||
public class SongSearchResponse
|
||||
{
|
||||
[JsonProperty("status")] public int Status { get; set; }
|
||||
|
||||
[JsonProperty("data")] public SongSearchResponseInnerData Data { get; set; }
|
||||
|
||||
[JsonProperty("error_code")] public int ErrorCode { get; set; }
|
||||
|
||||
[JsonProperty("error_msg")] public string ErrorMessage { get; set; }
|
||||
}
|
||||
|
||||
public class SongSearchResponseInnerData
|
||||
{
|
||||
[JsonProperty("lists")] public List<SongSearchResponseSongDetail> List { get; set; }
|
||||
}
|
||||
|
||||
public class SongSearchResponseSongDetail
|
||||
{
|
||||
public string FileHash { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ZonyLrcTools.Common.Configuration;
|
||||
using ZonyLrcTools.Common.Infrastructure.Exceptions;
|
||||
using ZonyLrcTools.Common.Infrastructure.Network;
|
||||
using ZonyLrcTools.Common.Lyrics.Providers.KuGou.JsonModel;
|
||||
|
||||
namespace ZonyLrcTools.Common.Lyrics.Providers.KuGou
|
||||
{
|
||||
public class KuGourLyricDownloader : LyricDownloader
|
||||
{
|
||||
public override string DownloaderName => InternalLyricDownloaderNames.KuGou;
|
||||
|
||||
private readonly IWarpHttpClient _warpHttpClient;
|
||||
private readonly ILyricItemCollectionFactory _lyricItemCollectionFactory;
|
||||
private readonly GlobalOptions _options;
|
||||
|
||||
private const string KuGouSearchMusicUrl = @"https://songsearch.kugou.com/song_search_v2";
|
||||
private const string KuGouGetLyricAccessKeyUrl = @"http://lyrics.kugou.com/search";
|
||||
private const string KuGouGetLyricUrl = @"http://lyrics.kugou.com/download";
|
||||
|
||||
public KuGourLyricDownloader(IWarpHttpClient warpHttpClient,
|
||||
ILyricItemCollectionFactory lyricItemCollectionFactory,
|
||||
IOptions<GlobalOptions> options)
|
||||
{
|
||||
_warpHttpClient = warpHttpClient;
|
||||
_lyricItemCollectionFactory = lyricItemCollectionFactory;
|
||||
_options = options.Value;
|
||||
}
|
||||
|
||||
protected override async ValueTask<byte[]> DownloadDataAsync(LyricDownloaderArgs args)
|
||||
{
|
||||
var searchResult = await _warpHttpClient.GetAsync<SongSearchResponse>(KuGouSearchMusicUrl,
|
||||
new SongSearchRequest(args.SongName, args.Artist, _options.Provider.Lyric.GetLyricProviderOption(DownloaderName).Depth));
|
||||
|
||||
ValidateSongSearchResponse(searchResult, args);
|
||||
|
||||
// 获得特殊的 AccessToken 与 Id,真正请求歌词数据。
|
||||
var accessKeyResponse = await _warpHttpClient.GetAsync<GetLyricAccessKeyResponse>(KuGouGetLyricAccessKeyUrl,
|
||||
new GetLyricAccessKeyRequest(searchResult.Data.List[0].FileHash));
|
||||
|
||||
var accessKeyObject = accessKeyResponse.AccessKeyDataObjects[0];
|
||||
var lyricResponse = await _warpHttpClient.GetAsync(KuGouGetLyricUrl,
|
||||
new GetLyricRequest(accessKeyObject.Id, accessKeyObject.AccessKey));
|
||||
|
||||
return Encoding.UTF8.GetBytes(lyricResponse);
|
||||
}
|
||||
|
||||
protected override async ValueTask<LyricItemCollection> GenerateLyricAsync(byte[] data, LyricDownloaderArgs args)
|
||||
{
|
||||
await ValueTask.CompletedTask;
|
||||
var lyricJsonObj = JObject.Parse(Encoding.UTF8.GetString(data));
|
||||
if (lyricJsonObj.SelectToken("$.status").Value<int>() != 200)
|
||||
{
|
||||
throw new ErrorCodeException(ErrorCodes.NoMatchingSong, attachObj: args);
|
||||
}
|
||||
|
||||
var lyricText = Encoding.UTF8.GetString(Convert.FromBase64String(lyricJsonObj.SelectToken("$.content").Value<string>()));
|
||||
return _lyricItemCollectionFactory.Build(lyricText);
|
||||
}
|
||||
|
||||
protected virtual void ValidateSongSearchResponse(SongSearchResponse response, LyricDownloaderArgs args)
|
||||
{
|
||||
if (response.ErrorCode != 0 && response.Status != 1 || response.Data.List == null)
|
||||
{
|
||||
throw new ErrorCodeException(ErrorCodes.NoMatchingSong, attachObj: args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user