mirror of
https://github.com/real-zony/ZonyLrcToolsX.git
synced 2025-09-06 05:36:53 +00:00
refactor: Common components are moved to the Common library.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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; }
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user