diff --git a/Lyricify.Lyrics.Helper/Decrypter/Qrc/Decrypter.cs b/Lyricify.Lyrics.Helper/Decrypter/Qrc/Decrypter.cs index 47ef610..74011a9 100644 --- a/Lyricify.Lyrics.Helper/Decrypter/Qrc/Decrypter.cs +++ b/Lyricify.Lyrics.Helper/Decrypter/Qrc/Decrypter.cs @@ -37,7 +37,7 @@ public class Decrypter } Span unzip = SharpZipLibDecompress(data); - + // 移除字符串头部的 BOM 标识 (如果有) var utf8Bom = Encoding.UTF8.GetPreamble(); if (unzip[..utf8Bom.Length].SequenceEqual(utf8Bom)) diff --git a/Lyricify.Lyrics.Helper/Providers/Web/BaseApi.cs b/Lyricify.Lyrics.Helper/Providers/Web/BaseApi.cs index 126612a..985e676 100644 --- a/Lyricify.Lyrics.Helper/Providers/Web/BaseApi.cs +++ b/Lyricify.Lyrics.Helper/Providers/Web/BaseApi.cs @@ -13,7 +13,7 @@ public abstract class BaseApi protected abstract string? HttpRefer { get; } - protected abstract Dictionary? AdditionalHeaders { get; } + protected abstract Dictionary? AdditionalHeaders { get; } protected async Task GetAsync(string url) { diff --git a/Lyricify.Lyrics.Helper/Providers/Web/MusixMatch/Api.cs b/Lyricify.Lyrics.Helper/Providers/Web/MusixMatch/Api.cs index 33259da..1afc9c1 100644 --- a/Lyricify.Lyrics.Helper/Providers/Web/MusixMatch/Api.cs +++ b/Lyricify.Lyrics.Helper/Providers/Web/MusixMatch/Api.cs @@ -1,5 +1,4 @@ using Newtonsoft.Json; -using static Lyricify.Lyrics.Providers.Web.Musixmatch.GetTrackResponse; namespace Lyricify.Lyrics.Providers.Web.Musixmatch { diff --git a/Lyricify.Lyrics.Helper/Providers/Web/Netease/Api.cs b/Lyricify.Lyrics.Helper/Providers/Web/Netease/Api.cs index 85bccc8..4c9cc8c 100644 --- a/Lyricify.Lyrics.Helper/Providers/Web/Netease/Api.cs +++ b/Lyricify.Lyrics.Helper/Providers/Web/Netease/Api.cs @@ -54,8 +54,49 @@ public enum SearchTypeEnum return JsonConvert.DeserializeObject(res); } + public async Task SearchNew(string keyword) + { + const string url = "https://interface.music.163.com/eapi/cloudsearch/pc"; + + var data = new Dictionary + { + { "s", keyword }, + { "type", "1" }, + { "limit", "30" }, + { "offset", "0" }, + { "total", "true" } + }; + + var raw = await EapiHelper.PostAsync(url, HttpClient, data); + + var eapiResult = JsonConvert.DeserializeObject(raw); + if (eapiResult is null) return null; + + var result = new SearchResult(); + result.Code = eapiResult.Code; + result.NeedLogin = eapiResult.NeedLogin; + result.Result = eapiResult.Result; + var list = new List(); + foreach (var song in eapiResult.Result.Songs) + { + list.Add(new() + { + Album = song.Album, + Alias = song.Alias, + Artists = song.Artists, + Duration = song.Duration, + Id = song.Id, + Name = song.Name, + Privilege = song.Privilege, + PublishTime = song.PublishTime + }); + } + result.Result.Songs = list.ToArray(); + return result; + } + /// - /// + /// /// /// /// diff --git a/Lyricify.Lyrics.Helper/Providers/Web/Netease/EapiHelper.cs b/Lyricify.Lyrics.Helper/Providers/Web/Netease/EapiHelper.cs index 1f85ea4..3184fee 100644 --- a/Lyricify.Lyrics.Helper/Providers/Web/Netease/EapiHelper.cs +++ b/Lyricify.Lyrics.Helper/Providers/Web/Netease/EapiHelper.cs @@ -66,6 +66,7 @@ private static ulong GetCurrentTotalMilliseconds() public static Dictionary EApi(string url, object @object) { url = url.Replace("https://interface3.music.163.com/e", "/"); + url = url.Replace("https://interface.music.163.com/e", "/"); string text = JsonConvert.SerializeObject(@object); string message = $"nobody{url}use{text}md5forencrypt"; string digest = message.ToByteArrayUtf8().ComputeMd5().ToHexStringLower(); diff --git a/Lyricify.Lyrics.Helper/Providers/Web/Netease/Response.cs b/Lyricify.Lyrics.Helper/Providers/Web/Netease/Response.cs index 638dd4f..1e03f71 100644 --- a/Lyricify.Lyrics.Helper/Providers/Web/Netease/Response.cs +++ b/Lyricify.Lyrics.Helper/Providers/Web/Netease/Response.cs @@ -1,4 +1,6 @@ #nullable disable +using Newtonsoft.Json; + namespace Lyricify.Lyrics.Providers.Web.Netease { /// @@ -11,27 +13,44 @@ public class SearchResult public SearchResultData Result { get; set; } public long Code { get; set; } + } - public class SearchResultData - { - /* SearchType = SONG */ + public class SearchResultData + { + /* SearchType = SONG */ + + public Song[] Songs { get; set; } - public Song[] Songs { get; set; } + public long SongCount { get; set; } - public long SongCount { get; set; } + /* SearchType = ALBUM */ - /* SearchType = ALBUM */ + public Album[] Albums { get; set; } - public Album[] Albums { get; set; } + public long AlbumCount { get; set; } - public long AlbumCount { get; set; } + /* SearchType = PLAYLIST */ - /* SearchType = PLAYLIST */ + public SimplePlaylist[] Playlists { get; set; } - public SimplePlaylist[] Playlists { get; set; } + public long PlaylistCount { get; set; } + } + + public class EapiSearchResultData : SearchResultData + { + public new EapiSong[] Songs { get; set; } + } - public long PlaylistCount { get; set; } - } + /// + /// 搜索接口结果 + /// + public class EapiSearchResult + { + public bool NeedLogin { get; set; } + + public EapiSearchResultData Result { get; set; } + + public long Code { get; set; } } public class SongUrls @@ -264,6 +283,28 @@ public class Song public Privilege Privilege { get; set; } } + public class EapiSong + { + public string Name { get; set; } + public string Id { get; set; } + [JsonProperty("ar")] + public List Artists { get; set; } + [JsonProperty("alia")] + public List Alias { get; set; } + [JsonProperty("al")] + public Al Album { get; set; } + /// + /// 时长,单位ms + /// + [JsonProperty("dt")] + public long Duration { get; set; } + /// + /// 时间戳,eg 1657900800000 + /// + public long PublishTime { get; set; } + public Privilege Privilege { get; set; } + } + public class Info { public CommentThread CommentThread { get; set; } diff --git a/Lyricify.Lyrics.Helper/Searchers/NeteaseSearcher.cs b/Lyricify.Lyrics.Helper/Searchers/NeteaseSearcher.cs index ecef36b..35483f4 100644 --- a/Lyricify.Lyrics.Helper/Searchers/NeteaseSearcher.cs +++ b/Lyricify.Lyrics.Helper/Searchers/NeteaseSearcher.cs @@ -8,13 +8,37 @@ public class NeteaseSearcher : Searcher, ISearcher public override string DisplayName => "Netease Cloud Music"; + private bool useNewSearchFirst = false; + public override async Task?> SearchForResults(string searchString) { var search = new List(); + SearchResult? result = null; + if (useNewSearchFirst) + { + try { result = await Providers.Web.Providers.NeteaseApi.SearchNew(searchString); } + catch + { + useNewSearchFirst = !useNewSearchFirst; + try { result = await Providers.Web.Providers.NeteaseApi.Search(searchString, Api.SearchTypeEnum.SONG_ID); } + catch { } + } + } + else + { + try { result = await Providers.Web.Providers.NeteaseApi.Search(searchString, Api.SearchTypeEnum.SONG_ID); } + catch + { + useNewSearchFirst = !useNewSearchFirst; + // 尝试新接口,可以在外网使用 + try { result = await Providers.Web.Providers.NeteaseApi.SearchNew(searchString); } + catch { } + } + } + try { - var result = await Providers.Web.Providers.NeteaseApi.Search(searchString, Api.SearchTypeEnum.SONG_ID); var results = result?.Result.Songs; if (results == null) return null; foreach (var track in results)