refactor: Common components are moved to the Common library.

This commit is contained in:
real-zony
2022-10-06 13:02:20 +08:00
parent ecab0e0f5c
commit 740e8f4c63
64 changed files with 84 additions and 150 deletions

View File

@@ -0,0 +1,33 @@
using Newtonsoft.Json;
namespace ZonyLrcTools.Common.Lyrics.Providers.QQMusic.JsonModel
{
public class GetLyricRequest
{
[JsonProperty("nobase64")] public int IsNoBase64Encoding { get; set; }
[JsonProperty("songmid")] public string SongId { get; set; }
[JsonProperty("platform")] public string ClientPlatform { get; set; }
[JsonProperty("inCharset")] public string InCharset { get; set; }
[JsonProperty("outCharset")] public string OutCharset { get; set; }
[JsonProperty("g_tk")] public int Gtk { get; set; }
protected GetLyricRequest()
{
}
public GetLyricRequest(string songId)
{
IsNoBase64Encoding = 1;
SongId = songId;
ClientPlatform = "yqq";
InCharset = "utf8";
OutCharset = "utf-8";
Gtk = 5381;
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Text;
using System.Web;
using Newtonsoft.Json;
namespace ZonyLrcTools.Common.Lyrics.Providers.QQMusic.JsonModel
{
public class SongSearchRequest
{
[JsonProperty("format")]
public string Format { get; protected set; }
[JsonProperty("inCharset")]
public string InCharset { get; protected set; }
[JsonProperty("outCharset")]
public string OutCharset { get; protected set; }
[JsonProperty("platform")]
public string Platform { get; protected set; }
[JsonProperty("key")]
public string Keyword { get; protected set; }
protected SongSearchRequest()
{
Format = "json";
InCharset = OutCharset = "utf-8";
Platform = "yqq.json";
}
public SongSearchRequest(string musicName, string artistName) : this()
{
Keyword = HttpUtility.UrlEncode($"{musicName}+{artistName}", Encoding.UTF8);
}
}
}

View File

@@ -0,0 +1,26 @@
using Newtonsoft.Json;
namespace ZonyLrcTools.Common.Lyrics.Providers.QQMusic.JsonModel
{
public class SongSearchResponse
{
[JsonProperty("code")] public int StatusCode { get; set; }
[JsonProperty("data")] public QQMusicInnerDataModel Data { get; set; }
}
public class QQMusicInnerDataModel
{
[JsonProperty("song")] public QQMusicInnerSongModel Song { get; set; }
}
public class QQMusicInnerSongModel
{
[JsonProperty("itemlist")] public List<QQMusicInnerSongItem> SongItems { get; set; }
}
public class QQMusicInnerSongItem
{
[JsonProperty("mid")] public string SongId { get; set; }
}
}

View File

@@ -0,0 +1,82 @@
using System.Text;
using System.Web;
using Newtonsoft.Json.Linq;
using ZonyLrcTools.Common.Infrastructure.Exceptions;
using ZonyLrcTools.Common.Infrastructure.Network;
using ZonyLrcTools.Common.Lyrics.Providers.QQMusic.JsonModel;
namespace ZonyLrcTools.Common.Lyrics.Providers.QQMusic
{
public class QQLyricDownloader : LyricDownloader
{
public override string DownloaderName => InternalLyricDownloaderNames.QQ;
private readonly IWarpHttpClient _warpHttpClient;
private readonly ILyricItemCollectionFactory _lyricItemCollectionFactory;
// private const string QQSearchMusicUrl = @"https://c.y.qq.com/soso/fcgi-bin/client_search_cp";
private const string QQSearchMusicUrl = @"https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg";
private const string QQGetLyricUrl = @"https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg";
private const string QQMusicRequestReferer = @"https://y.qq.com/";
public QQLyricDownloader(IWarpHttpClient warpHttpClient,
ILyricItemCollectionFactory lyricItemCollectionFactory)
{
_warpHttpClient = warpHttpClient;
_lyricItemCollectionFactory = lyricItemCollectionFactory;
}
protected override async ValueTask<byte[]> DownloadDataAsync(LyricDownloaderArgs args)
{
var searchResult = await _warpHttpClient.GetAsync<SongSearchResponse>(
QQSearchMusicUrl,
new SongSearchRequest(args.SongName, args.Artist));
ValidateSongSearchResponse(searchResult, args);
var lyricJsonString = await _warpHttpClient.GetAsync(QQGetLyricUrl,
new GetLyricRequest(searchResult.Data.Song.SongItems.FirstOrDefault()?.SongId),
op => op.Headers.Referrer = new Uri(QQMusicRequestReferer));
return Encoding.UTF8.GetBytes(lyricJsonString);
}
protected override async ValueTask<LyricItemCollection> GenerateLyricAsync(byte[] data, LyricDownloaderArgs args)
{
await ValueTask.CompletedTask;
var lyricJsonString = Encoding.UTF8.GetString(data);
lyricJsonString = lyricJsonString.Replace(@"MusicJsonCallback(", string.Empty).TrimEnd(')');
if (lyricJsonString.Contains("\"code\":-1901"))
{
throw new ErrorCodeException(ErrorCodes.NoMatchingSong, attachObj: args);
}
if (lyricJsonString.Contains("此歌曲为没有填词的纯音乐,请您欣赏"))
{
return _lyricItemCollectionFactory.Build(null);
}
var lyricJsonObj = JObject.Parse(lyricJsonString);
var sourceLyric = HttpUtility.HtmlDecode(HttpUtility.HtmlDecode(lyricJsonObj.SelectToken("$.lyric").Value<string>()));
var translateLyric = HttpUtility.HtmlDecode(HttpUtility.HtmlDecode(lyricJsonObj.SelectToken("$.trans").Value<string>()));
return _lyricItemCollectionFactory.Build(sourceLyric, translateLyric);
}
protected virtual void ValidateSongSearchResponse(SongSearchResponse response, LyricDownloaderArgs args)
{
if (response is not { StatusCode: 0 } || response.Data.Song.SongItems == null)
{
throw new ErrorCodeException(ErrorCodes.TheReturnValueIsIllegal, attachObj: args);
}
if (response.Data.Song.SongItems.Count <= 0)
{
throw new ErrorCodeException(ErrorCodes.NoMatchingSong, attachObj: args);
}
}
}
}