diff --git a/.github/workflows/nativeaot-test.yml b/.github/workflows/nativeaot-test.yml index 9a91994..4667098 100644 --- a/.github/workflows/nativeaot-test.yml +++ b/.github/workflows/nativeaot-test.yml @@ -26,10 +26,10 @@ jobs: ${{ secrets.NETEASE_LOGIN_SECRET }} - name: Restore - run: dotnet restore -r linux-x64 -p:TargetFramework=net9.0 + run: dotnet restore -r linux-x64 -p:TargetFramework=net10.0 -p:RuntimeIdentifier=linux-x64 - name: Publish with AOT - run: dotnet publish -c Release -f net9.0 -r linux-x64 --no-restore + run: dotnet publish -c Release -f net10.0 -r linux-x64 --no-restore - name: Run AOT tests - run: ./HyPlayer.NeteaseProvider.Tests/bin/Release/net9.0/linux-x64/publish/HyPlayer.NeteaseProvider.Tests \ No newline at end of file + run: ./HyPlayer.NeteaseProvider.Tests/bin/Release/net10.0/linux-x64/publish/HyPlayer.NeteaseProvider.Tests diff --git a/EasyDumper/EasyDumper.csproj b/EasyDumper/EasyDumper.csproj index 59ef220..73c2e1d 100644 --- a/EasyDumper/EasyDumper.csproj +++ b/EasyDumper/EasyDumper.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/HyPlayer.NeteaseApi/ApiContracts/Album/AlbumApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Album/AlbumApi.cs index 23806fa..a3bf95d 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Album/AlbumApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Album/AlbumApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Album; +using HyPlayer.NeteaseApi.ApiContracts.Album; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using HyPlayer.NeteaseApi.Models; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSongsApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSongsApi.cs index 2c361b7..23dd427 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSongsApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSongsApi.cs @@ -23,7 +23,7 @@ public class ArtistSongsApi : EApiContractBase { public override string IdentifyRoute => "/artist/songs"; - public override string Url { get; protected set; } = "https://interface3.music.163.com/eapi/v2/artist/songs"; + public override string Url { get; protected set; } = "https://interfacepc.music.163.com/eapi/v2/artist/songs"; public override HttpMethod Method => HttpMethod.Post; public override Task MapRequest(ApiHandlerOption option) @@ -32,19 +32,6 @@ public override Task MapRequest(ApiHandlerOption option) ActualRequest = new ArtistSongsActualRequest { Id = Request.ArtistId, - OrderType = Request.OrderType switch - { - ArtistSongsOrderType.Time => "time", - _ => "hot" - }, - WorkType = Request.WorkType switch - { - ArtistSongsWorkType.All => 1, - ArtistSongsWorkType.Sing => 5, - ArtistSongsWorkType.Lyric => 6, - ArtistSongsWorkType.Compose => 7, - _ => 1 - }, Offset = Request.Offset, Limit = Request.Limit }; @@ -57,27 +44,10 @@ public override Task MapRequest(ApiHandlerOption option) public class ArtistSongsActualRequest : EApiActualRequestBase { [JsonPropertyName("id")] public required string Id { get; set; } - [JsonPropertyName("private_cloud")] public bool PrivateCloud => true; - [JsonPropertyName("work_type")] public int WorkType = 1; - [JsonPropertyName("order")] public string OrderType { get; set; } = "hot"; [JsonPropertyName("offset")] public int Offset { get; set; } = 0; [JsonPropertyName("limit")] public int Limit { get; set; } = 100; } - public enum ArtistSongsOrderType - { - Hot, - Time - } - - public enum ArtistSongsWorkType - { - All, - Sing, - Lyric, - Compose - } - public class ArtistSongsRequest : RequestBase { /// @@ -85,16 +55,6 @@ public class ArtistSongsRequest : RequestBase /// public required string ArtistId { get; set; } - /// - /// 排序类型 hot, time - /// - public ArtistSongsOrderType OrderType { get; set; } = ArtistSongsOrderType.Hot; - - /// - ///作品类型 - /// - public ArtistSongsWorkType WorkType { get; set; } = ArtistSongsWorkType.All; - /// /// 起始位置 /// @@ -110,6 +70,6 @@ public class ArtistSongsResponse : CodedResponseBase { [JsonPropertyName("total")] public int Total { get; set; } [JsonPropertyName("more")] public bool HasMore { get; set; } - [JsonPropertyName("songs")] public EmittedSongDtoWithPrivilege[]? Songs { get; set; } + [JsonPropertyName("songs")] public ArtistSongDto[]? Songs { get; set; } } } \ No newline at end of file diff --git a/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSublistApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSublistApi.cs index 359221b..ef8aa89 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSublistApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSublistApi.cs @@ -1,7 +1,7 @@ using HyPlayer.NeteaseApi.ApiContracts.Artist; using HyPlayer.NeteaseApi.Bases; -using HyPlayer.NeteaseApi.Bases.ApiContractBases; using HyPlayer.NeteaseApi.Models.ResponseModels; +using HyPlayer.NeteaseApi.Bases.ApiContractBases; using System.Text.Json.Serialization; using HyPlayer.NeteaseApi.Bases.WeApiContractBases; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSubscribeApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSubscribeApi.cs new file mode 100644 index 0000000..adbf06a --- /dev/null +++ b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistSubscribeApi.cs @@ -0,0 +1,56 @@ +using HyPlayer.NeteaseApi.ApiContracts.Artist; +using HyPlayer.NeteaseApi.Bases; +using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using System.Text.Json.Serialization; + +namespace HyPlayer.NeteaseApi.ApiContracts +{ + public static partial class NeteaseApis + { + /// + /// 艺术家收藏 + /// + public static ArtistSubscribeApi ArtistSubscribeApi => new(); + } +} + +namespace HyPlayer.NeteaseApi.ApiContracts.Artist +{ + public class ArtistSubscribeApi : EApiContractBase, IFakeCheckTokenApi + { + public override string ApiPath { get; protected set; } = "/api/artist/sub"; + + public override string IdentifyRoute => "/artist/subscribe"; + + public override string Url { get; protected set; } = "https://interface.music.163.com/eapi/artist/sub"; + + public override HttpMethod Method => HttpMethod.Post; + + public override Task MapRequest(ApiHandlerOption option) + { + if (Request is not null) + { + ActualRequest = new ArtistSubscribeActualRequest + { + ArtistId = Request.ArtistId + }; + } + return Task.CompletedTask; + } + } + + public class ArtistSubscribeRequest : RequestBase + { + public required string ArtistId { get; set; } + } + + public class ArtistSubscribeResponse : CodedResponseBase + { + } + + public class ArtistSubscribeActualRequest : EApiActualRequestBase + { + [JsonPropertyName("artistId")] public required string ArtistId { get; set; } + } +} diff --git a/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistTopSongApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistTopSongApi.cs index 1ca9cc7..24d3e09 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistTopSongApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistTopSongApi.cs @@ -95,4 +95,17 @@ public class ArtistTopSongActualRequest : EApiActualRequestBase [JsonPropertyName("offset")] public int Offset { get; set; } = 0; [JsonPropertyName("limit")] public int Limit { get; set; } = 100; } + public enum ArtistSongsOrderType + { + Hot, + Time + } + + public enum ArtistSongsWorkType + { + All, + Sing, + Lyric, + Compose + } } \ No newline at end of file diff --git a/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistUnsubscribeApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistUnsubscribeApi.cs new file mode 100644 index 0000000..60180f4 --- /dev/null +++ b/HyPlayer.NeteaseApi/ApiContracts/Artist/ArtistUnsubscribeApi.cs @@ -0,0 +1,59 @@ +using HyPlayer.NeteaseApi.Bases; +using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using System.Text.Json; +using System.Text.Json.Serialization; +using HyPlayer.NeteaseApi.ApiContracts.Artist; + +namespace HyPlayer.NeteaseApi.ApiContracts +{ + public static partial class NeteaseApis + { + public static ArtistUnsubscribeApi ArtistUnsubscribeApi => new(); + } +} + +namespace HyPlayer.NeteaseApi.ApiContracts.Artist +{ + public class ArtistUnsubscribeApi : EApiContractBase + { + public override string ApiPath { get; protected set; } = "/api/artist/unsub"; + + public override string IdentifyRoute => "/artist/unsub"; + + public override string Url { get; protected set; } = "https://interface.music.163.com/eapi/artist/"; + + public override HttpMethod Method => HttpMethod.Post; + + public override Task MapRequest(ApiHandlerOption option) + { + if (Request is not null) + { + ActualRequest = new ArtistUnsubscribeActualRequest + { + // serialize C# array of ids to JSON array string expected by the API + ArtistIds = JsonSerializer.Serialize(Request.ArtistIds) + }; + Url += "unsub"; + } + return Task.CompletedTask; + } + } + + public class ArtistUnsubscribeRequest : RequestBase + { + /// + /// Array of artist ids. Will be converted to a JSON array string in the request, e.g. new long[] { 35374786 } -> "[35374786]" + /// + public required long[] ArtistIds { get; set; } + } + + public class ArtistUnsubscribeResponse : CodedResponseBase + { + } + + public class ArtistUnsubscribeActualRequest : EApiActualRequestBase + { + [JsonPropertyName("artistIds")] public required string ArtistIds { get; set; } + } +} diff --git a/HyPlayer.NeteaseApi/ApiContracts/Cloud/NeteaseUploadLoadBalancerGetApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Cloud/NeteaseUploadLoadBalancerGetApi.cs index 3e8866d..956c342 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Cloud/NeteaseUploadLoadBalancerGetApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Cloud/NeteaseUploadLoadBalancerGetApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Cloud; +using HyPlayer.NeteaseApi.ApiContracts.Cloud; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.RawApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Comment/CommentLikeApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Comment/CommentLikeApi.cs index cf3706d..47cfba4 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Comment/CommentLikeApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Comment/CommentLikeApi.cs @@ -1,8 +1,8 @@ using HyPlayer.NeteaseApi.ApiContracts.Comment; using HyPlayer.NeteaseApi.Bases; -using HyPlayer.NeteaseApi.Bases.ApiContractBases; using HyPlayer.NeteaseApi.Extensions; using HyPlayer.NeteaseApi.Models; +using HyPlayer.NeteaseApi.Bases.ApiContractBases; using System.Text.Json.Serialization; using HyPlayer.NeteaseApi.Bases.WeApiContractBases; diff --git a/HyPlayer.NeteaseApi/ApiContracts/DjChannel/DjChannelSubscribeApi.cs b/HyPlayer.NeteaseApi/ApiContracts/DjChannel/DjChannelSubscribeApi.cs new file mode 100644 index 0000000..8726d78 --- /dev/null +++ b/HyPlayer.NeteaseApi/ApiContracts/DjChannel/DjChannelSubscribeApi.cs @@ -0,0 +1,55 @@ +using HyPlayer.NeteaseApi.Bases; +using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using System.Text.Json.Serialization; +using HyPlayer.NeteaseApi.ApiContracts.DjChannel; + +namespace HyPlayer.NeteaseApi.ApiContracts +{ + public static partial class NeteaseApis + { + public static DjChannelSubscribeApi DjChannelSubscribeApi => new(); + } +} + +namespace HyPlayer.NeteaseApi.ApiContracts.DjChannel +{ + public class DjChannelSubscribeApi : EApiContractBase + { + public override string ApiPath { get; protected set; } = " /api/djradio/sub"; + + public override string IdentifyRoute => "/djchannel/subscribe"; + + public override string Url { get; protected set; } = "https://interface.music.163.com/eapi/djradio/"; + + public override HttpMethod Method => HttpMethod.Post; + + public override Task MapRequest(ApiHandlerOption option) + { + if (Request is not null) + { + ActualRequest = new DjChannelSubscribeActualRequest + { + Id = Request.Id + }; + Url += Request.IsSubscribe ? "sub" : "unsub"; + } + + return Task.CompletedTask; + } + } + + public class DjChannelSubscribeActualRequest : EApiActualRequestBase + { + [JsonPropertyName("id")] public required string Id { get; set; } + } + + public class DjChannelSubscribeResponse : CodedResponseBase + { + } + + public class DjChannelSubscribeRequest : RequestBase + { + public required string Id { get; set; } + public bool IsSubscribe { get; set; } + } +} diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherEndApi.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherEndApi.cs index ad57ac8..a19848a 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherEndApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherEndApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherHeartbeatApi.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherHeartbeatApi.cs index acfb4f4..9ff1a8b 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherHeartbeatApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherHeartbeatApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherInvitationAcceptApi.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherInvitationAcceptApi.cs index c589865..0164595 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherInvitationAcceptApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherInvitationAcceptApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherPlayCommandApi.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherPlayCommandApi.cs index 6f2543c..b47adb9 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherPlayCommandApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherPlayCommandApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherRoomCheckApi.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherRoomCheckApi.cs index 39b956f..d11a3b0 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherRoomCheckApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherRoomCheckApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherRoomCreate.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherRoomCreate.cs index ae762ec..d96e323 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherRoomCreate.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherRoomCreate.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherStatusApi.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherStatusApi.cs index d6065a2..0adda74 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherStatusApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherStatusApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; using HyPlayer.NeteaseApi.ApiContracts.ListenTogether.Dual; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherSyncListCommandApi.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherSyncListCommandApi.cs index f1cd89e..52a8cd6 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherSyncListCommandApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherSyncListCommandApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json; diff --git a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherSyncListGetApi.cs b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherSyncListGetApi.cs index a22c51e..977ad66 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherSyncListGetApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/ListenTogether/Dual/ListenTogetherSyncListGetApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; +using HyPlayer.NeteaseApi.ApiContracts.ListenTogether; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/PersonalFM/AiDjContentRcmdInfo.cs b/HyPlayer.NeteaseApi/ApiContracts/PersonalFM/AiDjContentRcmdInfo.cs index 0340154..22324d7 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/PersonalFM/AiDjContentRcmdInfo.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/PersonalFM/AiDjContentRcmdInfo.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.PersonalFM; +using HyPlayer.NeteaseApi.ApiContracts.PersonalFM; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using HyPlayer.NeteaseApi.Models.ResponseModels; diff --git a/HyPlayer.NeteaseApi/ApiContracts/PersonalFM/PersonalFmTrashApi.cs b/HyPlayer.NeteaseApi/ApiContracts/PersonalFM/PersonalFmTrashApi.cs index 993596f..dcff556 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/PersonalFM/PersonalFmTrashApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/PersonalFM/PersonalFmTrashApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.PersonalFM; +using HyPlayer.NeteaseApi.ApiContracts.PersonalFM; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.ApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaylistCreateApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaylistCreateApi.cs index 4fa94d0..d0d46f7 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaylistCreateApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaylistCreateApi.cs @@ -1,7 +1,7 @@ using HyPlayer.NeteaseApi.ApiContracts.Playlist; using HyPlayer.NeteaseApi.Bases; -using HyPlayer.NeteaseApi.Bases.ApiContractBases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using HyPlayer.NeteaseApi.Bases.ApiContractBases; using System.Text.Json.Serialization; using HyPlayer.NeteaseApi.Bases.WeApiContractBases; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaylistTracksGetApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaylistTracksGetApi.cs index 18c69b9..827f67e 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaylistTracksGetApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaylistTracksGetApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Playlist; +using HyPlayer.NeteaseApi.ApiContracts.Playlist; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaymodeIntelligenceListApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaymodeIntelligenceListApi.cs index 58d625e..8270898 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaymodeIntelligenceListApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Playlist/PlaymodeIntelligenceListApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Playlist; +using HyPlayer.NeteaseApi.ApiContracts.Playlist; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using HyPlayer.NeteaseApi.Models.ResponseModels; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Recommend/SearchApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Recommend/SearchApi.cs index e0ca1c3..d9102c8 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Recommend/SearchApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Recommend/SearchApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Recommend; +using HyPlayer.NeteaseApi.ApiContracts.Recommend; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using HyPlayer.NeteaseApi.Models; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Recommend/SearchSuggestionApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Recommend/SearchSuggestionApi.cs index 9eb28bb..09ca8b3 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Recommend/SearchSuggestionApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Recommend/SearchSuggestionApi.cs @@ -1,9 +1,10 @@ using HyPlayer.NeteaseApi.ApiContracts.Recommend; using HyPlayer.NeteaseApi.Bases; -using HyPlayer.NeteaseApi.Bases.ApiContractBases; using System.Text.Json.Serialization; +using HyPlayer.NeteaseApi.Bases.ApiContractBases; using HyPlayer.NeteaseApi.Bases.WeApiContractBases; + namespace HyPlayer.NeteaseApi.ApiContracts { public static partial class NeteaseApis diff --git a/HyPlayer.NeteaseApi/ApiContracts/Song/MusicFirstListenInfoApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Song/MusicFirstListenInfoApi.cs index 2e0edef..f3d4e73 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Song/MusicFirstListenInfoApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Song/MusicFirstListenInfoApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Song; +using HyPlayer.NeteaseApi.ApiContracts.Song; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.ApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Song/SongChorusApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Song/SongChorusApi.cs index 05d30ce..fd51769 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Song/SongChorusApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Song/SongChorusApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Song; +using HyPlayer.NeteaseApi.ApiContracts.Song; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/User/UserFollowApi.cs b/HyPlayer.NeteaseApi/ApiContracts/User/UserFollowApi.cs new file mode 100644 index 0000000..252ed69 --- /dev/null +++ b/HyPlayer.NeteaseApi/ApiContracts/User/UserFollowApi.cs @@ -0,0 +1,51 @@ +using HyPlayer.NeteaseApi.Bases; +using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using HyPlayer.NeteaseApi.ApiContracts.User; + +namespace HyPlayer.NeteaseApi.ApiContracts +{ + public static partial class NeteaseApis + { + public static UserFollowApi UserFollowApi => new(); + } +} + +namespace HyPlayer.NeteaseApi.ApiContracts.User +{ + public class UserFollowApi : EApiContractBase, IFakeCheckTokenApi + { + public override string ApiPath { get; protected set; } = "/api/user/follow/"; + + public override string IdentifyRoute => "/user/follow"; + + public override string Url { get; protected set; } = "https://interfacepc.music.163.com/eapi/user/follow/"; + + public override HttpMethod Method => HttpMethod.Post; + + public override Task MapRequest(ApiHandlerOption option) + { + ActualRequest = new UserFollowActualRequestBase(); + if (Request is not null) + { + Url += Request.Id; + ApiPath += Request.Id; + } + + + return Task.CompletedTask; + } + } + + public class UserFollowActualRequestBase : EApiActualRequestBase + { + } + + public class UserFollowResponse : CodedResponseBase + { + } + + public class UserFollowRequest : RequestBase + { + public required string Id { get; set; } + } +} diff --git a/HyPlayer.NeteaseApi/ApiContracts/User/UserPlaylistApi.cs b/HyPlayer.NeteaseApi/ApiContracts/User/UserPlaylistApi.cs index 960587a..1e51135 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/User/UserPlaylistApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/User/UserPlaylistApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.User; +using HyPlayer.NeteaseApi.ApiContracts.User; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using HyPlayer.NeteaseApi.Models.ResponseModels; diff --git a/HyPlayer.NeteaseApi/ApiContracts/User/UserUnfollowApi.cs b/HyPlayer.NeteaseApi/ApiContracts/User/UserUnfollowApi.cs new file mode 100644 index 0000000..813a055 --- /dev/null +++ b/HyPlayer.NeteaseApi/ApiContracts/User/UserUnfollowApi.cs @@ -0,0 +1,50 @@ +using HyPlayer.NeteaseApi.Bases; +using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using HyPlayer.NeteaseApi.ApiContracts.User; + +namespace HyPlayer.NeteaseApi.ApiContracts +{ + public static partial class NeteaseApis + { + public static UserUnfollowApi UserUnfollowApi => new(); + } +} + +namespace HyPlayer.NeteaseApi.ApiContracts.User +{ + public class UserUnfollowApi : EApiContractBase, IFakeCheckTokenApi + { + public override string ApiPath { get; protected set; } = "/api/user/delfollow/"; + + public override string IdentifyRoute => "/user/delfollow"; + + public override string Url { get; protected set; } = "https://interfacepc.music.163.com/eapi/user/delfollow/"; + + public override HttpMethod Method => HttpMethod.Post; + + public override Task MapRequest(ApiHandlerOption option) + { + ActualRequest = new UserUnfollowActualRequestBase(); + if (Request is not null) + { + Url += Request.Id; + ApiPath += Request.Id; + } + + return Task.CompletedTask; + } + } + + public class UserUnfollowActualRequestBase : EApiActualRequestBase + { + } + + public class UserUnfollowResponse : CodedResponseBase + { + } + + public class UserUnfollowRequest : RequestBase + { + public required string Id { get; set; } + } +} diff --git a/HyPlayer.NeteaseApi/ApiContracts/Utils/BatchApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Utils/BatchApi.cs index 59b9892..0cb1ce1 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Utils/BatchApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Utils/BatchApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Utils; +using HyPlayer.NeteaseApi.ApiContracts.Utils; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using HyPlayer.NeteaseApi.Extensions; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Utils/LoginAnnounceDeviceApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Utils/LoginAnnounceDeviceApi.cs index b4acb49..e373df7 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Utils/LoginAnnounceDeviceApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Utils/LoginAnnounceDeviceApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Utils; +using HyPlayer.NeteaseApi.ApiContracts.Utils; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using HyPlayer.NeteaseApi.Extensions; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Utils/PasswordUrlDecodeApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Utils/PasswordUrlDecodeApi.cs index 23cb9e2..5dde9dd 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Utils/PasswordUrlDecodeApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Utils/PasswordUrlDecodeApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Utils; +using HyPlayer.NeteaseApi.ApiContracts.Utils; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.EApiContractBases; using System.Text.Json.Serialization; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Utils/RegisterAnonymousApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Utils/RegisterAnonymousApi.cs index 420838b..c293675 100644 --- a/HyPlayer.NeteaseApi/ApiContracts/Utils/RegisterAnonymousApi.cs +++ b/HyPlayer.NeteaseApi/ApiContracts/Utils/RegisterAnonymousApi.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts.Utils; +using HyPlayer.NeteaseApi.ApiContracts.Utils; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.ApiContractBases; using System.Security.Cryptography; diff --git a/HyPlayer.NeteaseApi/ApiContracts/Video/VideoSubscribeApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Video/VideoSubscribeApi.cs new file mode 100644 index 0000000..d1a29d4 --- /dev/null +++ b/HyPlayer.NeteaseApi/ApiContracts/Video/VideoSubscribeApi.cs @@ -0,0 +1,53 @@ +using HyPlayer.NeteaseApi.ApiContracts.Video; +using HyPlayer.NeteaseApi.Bases; +using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using System.Text.Json.Serialization; + +namespace HyPlayer.NeteaseApi.ApiContracts +{ + public static partial class NeteaseApis + { + public static VideoSubscribeApi VideoSubscribeApi => new(); + } +} + +namespace HyPlayer.NeteaseApi.ApiContracts.Video +{ + + public class VideoSubscribeApi : EApiContractBase + { + public override string IdentifyRoute => "/mv/subscribe"; + public override string Url { get; protected set; } = "https://interface.music.163.com/eapi/mv/sub"; + public override HttpMethod Method => HttpMethod.Post; + + public override Task MapRequest(ApiHandlerOption option) + { + if (Request is not null) + { + ActualRequest = new VideoSubscribeActualRequest + { + MvId = Request.MvId + }; + } + + return Task.CompletedTask; + } + + public override string ApiPath { get; protected set; } = "/api/mv/sub"; + } + + public class VideoSubscribeRequest : RequestBase + { + public required string MvId { get; set; } + } + + public class VideoSubscribeResponse : CodedResponseBase + { + } + + public class VideoSubscribeActualRequest : EApiActualRequestBase + { + [JsonPropertyName("mvId")] public required string MvId { get; set; } + } +} \ No newline at end of file diff --git a/HyPlayer.NeteaseApi/ApiContracts/Video/VideoUnsubscribeApi.cs b/HyPlayer.NeteaseApi/ApiContracts/Video/VideoUnsubscribeApi.cs new file mode 100644 index 0000000..73507e9 --- /dev/null +++ b/HyPlayer.NeteaseApi/ApiContracts/Video/VideoUnsubscribeApi.cs @@ -0,0 +1,54 @@ +using HyPlayer.NeteaseApi.Bases; +using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using System.Text.Json; +using System.Text.Json.Serialization; +using HyPlayer.NeteaseApi.ApiContracts.Video; + +namespace HyPlayer.NeteaseApi.ApiContracts +{ + public static partial class NeteaseApis + { + public static VideoUnsubscribeApi VideoUnsubscribeApi => new(); + } +} + +namespace HyPlayer.NeteaseApi.ApiContracts.Video +{ + public class VideoUnsubscribeApi : EApiContractBase + { + public override string ApiPath { get; protected set; } = "/api/mv/unsub"; + + public override string IdentifyRoute => "/mv/unsub"; + + public override string Url { get; protected set; } = "https://interface.music.163.com/eapi/mv/unsub"; + + public override HttpMethod Method => HttpMethod.Post; + + public override Task MapRequest(ApiHandlerOption option) + { + if (Request is not null) + { + ActualRequest = new VideoUnsubscribeActualRequest + { + VideoIds = Request.ConvertToQuotedIdStringList() + }; + } + return Task.CompletedTask; + } + } + + public class VideoUnsubscribeRequest : IdOrIdListListRequest + { + + } + + public class VideoUnsubscribeResponse : CodedResponseBase + { + } + + public class VideoUnsubscribeActualRequest : EApiActualRequestBase + { + [JsonPropertyName("mvIds")] public required string VideoIds { get; set; } + } +} \ No newline at end of file diff --git a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ActualRequestBase.cs b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ActualRequestBase.cs index 4a4e979..5608f06 100644 --- a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ActualRequestBase.cs +++ b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ActualRequestBase.cs @@ -1,4 +1,4 @@ -namespace HyPlayer.NeteaseApi.Bases.ApiContractBases; +namespace HyPlayer.NeteaseApi.Bases.ApiContractBases; public class ActualRequestBase { diff --git a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ApiContractBase.cs b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ApiContractBase.cs index 8811e0c..cc9b39f 100644 --- a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ApiContractBase.cs +++ b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ApiContractBase.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.Bases.ApiContractBases; +using HyPlayer.NeteaseApi.Bases.ApiContractBases; using HyPlayer.NeteaseApi.Extensions; namespace HyPlayer.NeteaseApi.Bases; diff --git a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ErrorResultBase.cs b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ErrorResultBase.cs index 2b3b6f4..2232d54 100644 --- a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ErrorResultBase.cs +++ b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ErrorResultBase.cs @@ -1,4 +1,4 @@ -namespace HyPlayer.NeteaseApi.Bases; +namespace HyPlayer.NeteaseApi.Bases; public class ErrorResultBase : Exception { diff --git a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ExceptionedErrorBase.cs b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ExceptionedErrorBase.cs index 1566c24..4c632c7 100644 --- a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ExceptionedErrorBase.cs +++ b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ExceptionedErrorBase.cs @@ -1,4 +1,4 @@ -namespace HyPlayer.NeteaseApi.Bases; +namespace HyPlayer.NeteaseApi.Bases; public class ExceptionedErrorBase : ErrorResultBase { diff --git a/HyPlayer.NeteaseApi/Bases/ApiContractBases/IdOrIdListRequest.cs b/HyPlayer.NeteaseApi/Bases/ApiContractBases/IdOrIdListRequest.cs index 9081466..57be953 100644 --- a/HyPlayer.NeteaseApi/Bases/ApiContractBases/IdOrIdListRequest.cs +++ b/HyPlayer.NeteaseApi/Bases/ApiContractBases/IdOrIdListRequest.cs @@ -3,12 +3,12 @@ public class IdOrIdListListRequest : RequestBase { /// - /// 歌曲 ID 列表 + /// 资源 ID 列表 /// public List? IdList { get; set; } /// - /// 歌曲 ID + /// 资源 ID /// public string? Id { get; set; } diff --git a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ResponseBase.cs b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ResponseBase.cs index 57f0cf0..28fda88 100644 --- a/HyPlayer.NeteaseApi/Bases/ApiContractBases/ResponseBase.cs +++ b/HyPlayer.NeteaseApi/Bases/ApiContractBases/ResponseBase.cs @@ -1,4 +1,4 @@ -namespace HyPlayer.NeteaseApi.Bases; +namespace HyPlayer.NeteaseApi.Bases; public class ResponseBase { diff --git a/HyPlayer.NeteaseApi/Bases/EApiContractBases/IBatchableApi.cs b/HyPlayer.NeteaseApi/Bases/EApiContractBases/IBatchableApi.cs index 3933c98..ae7a3aa 100644 --- a/HyPlayer.NeteaseApi/Bases/EApiContractBases/IBatchableApi.cs +++ b/HyPlayer.NeteaseApi/Bases/EApiContractBases/IBatchableApi.cs @@ -1,4 +1,4 @@ -namespace HyPlayer.NeteaseApi.Bases.EApiContractBases; +namespace HyPlayer.NeteaseApi.Bases.EApiContractBases; public interface IBatchableApi { diff --git a/HyPlayer.NeteaseApi/Bases/WeApiContractBases/WeApiContractBase.cs b/HyPlayer.NeteaseApi/Bases/WeApiContractBases/WeApiContractBase.cs index d6f80c7..72b6144 100644 --- a/HyPlayer.NeteaseApi/Bases/WeApiContractBases/WeApiContractBase.cs +++ b/HyPlayer.NeteaseApi/Bases/WeApiContractBases/WeApiContractBase.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.Bases.EApiContractBases; +using HyPlayer.NeteaseApi.Bases.ApiContractBases; using HyPlayer.NeteaseApi.Extensions; using System.Numerics; using System.Security.Cryptography; @@ -6,6 +6,7 @@ using System.Text.Json; using System.Text.RegularExpressions; using HyPlayer.NeteaseApi.Bases.WeApiContractBases; +using HyPlayer.NeteaseApi.Bases.EApiContractBases; namespace HyPlayer.NeteaseApi.Bases.ApiContractBases; diff --git a/HyPlayer.NeteaseApi/Extensions/JsonSerializer/JsonBooleanConverter.cs b/HyPlayer.NeteaseApi/Extensions/JsonSerializer/JsonBooleanConverter.cs index f9427e8..9d57b36 100644 --- a/HyPlayer.NeteaseApi/Extensions/JsonSerializer/JsonBooleanConverter.cs +++ b/HyPlayer.NeteaseApi/Extensions/JsonSerializer/JsonBooleanConverter.cs @@ -1,4 +1,4 @@ -using System.Text.Json; +using System.Text.Json; using System.Text.Json.Serialization; namespace HyPlayer.NeteaseApi.Extensions.JsonSerializer; diff --git a/HyPlayer.NeteaseApi/Extensions/JsonSerializer/JsonObjectStringConverter.cs b/HyPlayer.NeteaseApi/Extensions/JsonSerializer/JsonObjectStringConverter.cs index 213cd05..f3978ce 100644 --- a/HyPlayer.NeteaseApi/Extensions/JsonSerializer/JsonObjectStringConverter.cs +++ b/HyPlayer.NeteaseApi/Extensions/JsonSerializer/JsonObjectStringConverter.cs @@ -1,4 +1,4 @@ -using System.Text.Json; +using System.Text.Json; using System.Text.Json.Serialization; namespace HyPlayer.NeteaseApi.Extensions.JsonSerializer; diff --git a/HyPlayer.NeteaseApi/Extensions/Roslyn/CompilerFeatureRequired.cs b/HyPlayer.NeteaseApi/Extensions/Roslyn/CompilerFeatureRequired.cs index 6976920..d1a7d73 100644 --- a/HyPlayer.NeteaseApi/Extensions/Roslyn/CompilerFeatureRequired.cs +++ b/HyPlayer.NeteaseApi/Extensions/Roslyn/CompilerFeatureRequired.cs @@ -1,4 +1,4 @@ -#pragma warning disable +#pragma warning disable #nullable enable annotations // Licensed to the .NET Foundation under one or more agreements. diff --git a/HyPlayer.NeteaseApi/Extensions/Roslyn/ExternalInit.cs b/HyPlayer.NeteaseApi/Extensions/Roslyn/ExternalInit.cs index 1404d49..5590b16 100644 --- a/HyPlayer.NeteaseApi/Extensions/Roslyn/ExternalInit.cs +++ b/HyPlayer.NeteaseApi/Extensions/Roslyn/ExternalInit.cs @@ -1,4 +1,4 @@ -#pragma warning disable +#pragma warning disable #nullable enable annotations // Licensed to the .NET Foundation under one or more agreements. diff --git a/HyPlayer.NeteaseApi/Extensions/Roslyn/RequeiredAttribute.cs b/HyPlayer.NeteaseApi/Extensions/Roslyn/RequeiredAttribute.cs index 988a9bf..49a7131 100644 --- a/HyPlayer.NeteaseApi/Extensions/Roslyn/RequeiredAttribute.cs +++ b/HyPlayer.NeteaseApi/Extensions/Roslyn/RequeiredAttribute.cs @@ -1,4 +1,4 @@ -#pragma warning disable +#pragma warning disable #nullable enable annotations // Licensed to the .NET Foundation under one or more agreements. diff --git a/HyPlayer.NeteaseApi/HyPlayer.NeteaseApi.csproj b/HyPlayer.NeteaseApi/HyPlayer.NeteaseApi.csproj index 9a22102..2e59307 100644 --- a/HyPlayer.NeteaseApi/HyPlayer.NeteaseApi.csproj +++ b/HyPlayer.NeteaseApi/HyPlayer.NeteaseApi.csproj @@ -4,23 +4,21 @@ enable enable default - 0.1.0 + 0.1.2 HyPlayer Team The NeteaseCloudMusic Api https://github.com/HyPlayer/HyPlayer.NeteaseProvider https://github.com/HyPlayer/HyPlayer.NeteaseProvider/blob/main/LICENCE https://github.com/HyPlayer/HyPlayer.NeteaseProvider git - 0.1.0 - 0.1.0 - netstandard2.0;net9.0 + netstandard2.0;net10.0 IL2026;IL3050 true AnyCPU;x64 - + diff --git a/HyPlayer.NeteaseApi/Models/ResponseModels/ArtistSongDto.cs b/HyPlayer.NeteaseApi/Models/ResponseModels/ArtistSongDto.cs new file mode 100644 index 0000000..e740056 --- /dev/null +++ b/HyPlayer.NeteaseApi/Models/ResponseModels/ArtistSongDto.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; + +namespace HyPlayer.NeteaseApi.Models.ResponseModels; + +public class ArtistSongDto +{ + [JsonPropertyName("name")] public string? Name { get; set; } + [JsonPropertyName("id")] public string? Id { get; set; } + [JsonPropertyName("alias")] public string[]? Alias { get; set; } + [JsonPropertyName("duration")] public long Duration { get; set; } + [JsonPropertyName("transNames")] public string[]? Translations { get; set; } + [JsonPropertyName("mvid")] public string? MvId { get; set; } + [JsonPropertyName("no")] public int TrackNumber { get; set; } + [JsonPropertyName("album")] public AlbumDto? Album { get; set; } + [JsonPropertyName("artists")] public ArtistDto[]? Artists { get; set; } + [JsonPropertyName("privilege")] public PrivilegeDto? Privilege { get; set; } +} \ No newline at end of file diff --git a/HyPlayer.NeteaseApi/NeteaseCloudMusicApiHandler.cs b/HyPlayer.NeteaseApi/NeteaseCloudMusicApiHandler.cs index 4447284..3bc7b65 100644 --- a/HyPlayer.NeteaseApi/NeteaseCloudMusicApiHandler.cs +++ b/HyPlayer.NeteaseApi/NeteaseCloudMusicApiHandler.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.Bases; +using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Bases.ApiContractBases; using HyPlayer.NeteaseApi.Extensions; using System.Net; diff --git a/HyPlayer.NeteaseProvider.Tests/HyPlayer.NeteaseProvider.Tests.csproj b/HyPlayer.NeteaseProvider.Tests/HyPlayer.NeteaseProvider.Tests.csproj index 4ad7493..4b2302a 100644 --- a/HyPlayer.NeteaseProvider.Tests/HyPlayer.NeteaseProvider.Tests.csproj +++ b/HyPlayer.NeteaseProvider.Tests/HyPlayer.NeteaseProvider.Tests.csproj @@ -1,4 +1,4 @@ - + net10.0 diff --git a/HyPlayer.NeteaseProvider.Tests/NeteaseApisTests.cs b/HyPlayer.NeteaseProvider.Tests/NeteaseApisTests.cs index 803a1a4..96d1210 100644 --- a/HyPlayer.NeteaseProvider.Tests/NeteaseApisTests.cs +++ b/HyPlayer.NeteaseProvider.Tests/NeteaseApisTests.cs @@ -1,4 +1,4 @@ -#region +#region using AwesomeAssertions; using HyPlayer.NeteaseApi.ApiContracts; @@ -135,8 +135,7 @@ public async Task ArtistSongs_Should_BeNormal(string id, ArtistSongsOrderType or { var result = await _provider.RequestAsync(NeteaseApis.ArtistSongsApi, new ArtistSongsRequest { - ArtistId = id, - OrderType = orderType + ArtistId = id }); result.Match(s => { @@ -867,4 +866,97 @@ public async Task Batch_Should_BeNormal(string id) }, e => throw e); } + [Test] + [Arguments("14548918")] + public async Task VideoSubscribe_Should_BeNormal(string id) + { + var result = await _provider.RequestAsync(NeteaseApis.VideoSubscribeApi, new VideoSubscribeRequest + { + MvId = id + }); + result.Match(s => + { + s.Code.Should().Be(200); + return true; + }, + e => throw e); + } + [Test] + [Arguments("14548918")] + public async Task VideoUnsubscribe_Should_BeNormal(string id) + { + var result = await _provider.RequestAsync(NeteaseApis.VideoUnsubscribeApi, new VideoUnsubscribeRequest + { + Id = id + }); + result.Match(s => + { + s.Code.Should().Be(200); + return true; + }, + e => throw e); + } + + [Test] + [Arguments("793914432")] + public async Task DJChannelSubscribe_Should_BeNormal(string id) + { + var result = await _provider.RequestAsync(NeteaseApis.DjChannelSubscribeApi, new DjChannelSubscribeRequest + { + Id = id, + IsSubscribe = true + }); + result.Match(s => + { + s.Code.Should().Be(200); + return true; + }, + e => throw e); + } + [Test] + [Arguments("793914432")] + public async Task DJChannelUnsubscribe_Should_BeNormal(string id) + { + var result = await _provider.RequestAsync(NeteaseApis.DjChannelSubscribeApi, new DjChannelSubscribeRequest + { + Id = id, + IsSubscribe = false + }); + result.Match(s => + { + s.Code.Should().Be(200); + return true; + }, + e => throw e); + } + /*[Test] + [Arguments("8645419738")] + public async Task UserFollow_Should_BeNormal(string id) + { + var result = await _provider.RequestAsync(NeteaseApis.UserFollowApi, new UserFollowRequest + { + Id = id + }); + result.Match(s => + { + s.Code.Should().Be(200); + return true; + }, + e => throw e); + } + [Test] + [Arguments("8645419738")] + public async Task UserUnfollow_Should_BeNormal(string id) + { + var result = await _provider.RequestAsync(NeteaseApis.UserUnfollowApi, new UserUnfollowRequest + { + Id = id + }); + result.Match(s => + { + s.Code.Should().Be(200); + return true; + }, + e => throw e); + }*/ } \ No newline at end of file diff --git a/HyPlayer.NeteaseProvider.slnx b/HyPlayer.NeteaseProvider.slnx index 02ec932..6ac8be2 100644 --- a/HyPlayer.NeteaseProvider.slnx +++ b/HyPlayer.NeteaseProvider.slnx @@ -4,6 +4,7 @@ + diff --git a/HyPlayer.NeteaseProvider/Extensions/Roslyn/CompilerFeatureRequired.cs b/HyPlayer.NeteaseProvider/Extensions/Roslyn/CompilerFeatureRequired.cs index 6976920..d1a7d73 100644 --- a/HyPlayer.NeteaseProvider/Extensions/Roslyn/CompilerFeatureRequired.cs +++ b/HyPlayer.NeteaseProvider/Extensions/Roslyn/CompilerFeatureRequired.cs @@ -1,4 +1,4 @@ -#pragma warning disable +#pragma warning disable #nullable enable annotations // Licensed to the .NET Foundation under one or more agreements. diff --git a/HyPlayer.NeteaseProvider/Extensions/Roslyn/ExternalInit.cs b/HyPlayer.NeteaseProvider/Extensions/Roslyn/ExternalInit.cs index 1404d49..5590b16 100644 --- a/HyPlayer.NeteaseProvider/Extensions/Roslyn/ExternalInit.cs +++ b/HyPlayer.NeteaseProvider/Extensions/Roslyn/ExternalInit.cs @@ -1,4 +1,4 @@ -#pragma warning disable +#pragma warning disable #nullable enable annotations // Licensed to the .NET Foundation under one or more agreements. diff --git a/HyPlayer.NeteaseProvider/Extensions/Roslyn/RequeiredAttribute.cs b/HyPlayer.NeteaseProvider/Extensions/Roslyn/RequeiredAttribute.cs index 988a9bf..49a7131 100644 --- a/HyPlayer.NeteaseProvider/Extensions/Roslyn/RequeiredAttribute.cs +++ b/HyPlayer.NeteaseProvider/Extensions/Roslyn/RequeiredAttribute.cs @@ -1,4 +1,4 @@ -#pragma warning disable +#pragma warning disable #nullable enable annotations // Licensed to the .NET Foundation under one or more agreements. diff --git a/HyPlayer.NeteaseProvider/HyPlayer.NeteaseProvider.csproj b/HyPlayer.NeteaseProvider/HyPlayer.NeteaseProvider.csproj index 47e2f4c..174a17a 100644 --- a/HyPlayer.NeteaseProvider/HyPlayer.NeteaseProvider.csproj +++ b/HyPlayer.NeteaseProvider/HyPlayer.NeteaseProvider.csproj @@ -14,7 +14,7 @@ git 0.0.12 0.0.12 - netstandard2.0;net9.0 + netstandard2.0;net10.0 true diff --git a/HyPlayer.NeteaseProvider/Mappers/DjRadioProgramToNeteaseRadioProgramMapper.cs b/HyPlayer.NeteaseProvider/Mappers/DjRadioProgramToNeteaseRadioProgramMapper.cs new file mode 100644 index 0000000..c82030b --- /dev/null +++ b/HyPlayer.NeteaseProvider/Mappers/DjRadioProgramToNeteaseRadioProgramMapper.cs @@ -0,0 +1,36 @@ +using HyPlayer.NeteaseApi.Models.ResponseModels; +using HyPlayer.NeteaseProvider.Models; + +namespace HyPlayer.NeteaseProvider.Mappers; + +public static class DjRadioProgramToNeteaseRadioProgramMapper +{ + public static NeteaseRadioProgram MapToNeteaseRadioProgram(this DjRadioProgramDto program) + { + return new NeteaseRadioProgram + { + ActualId = program.Id!, + Name = program.Name ?? "未知节目", + PictureUrl = program.PictureUrl, + CoverUrl = program.CoverUrl, + Description = program.Description, + ProgramDuration = program.Duration, + RadioChannel = program.Radio?.MapToNeteaseRadioChannel(), + MainSong = program.MainSong?.MapToNeteaseMusic(), + Bought = program.Bought, + ListenerCount = program.ListenerCount, + SubscribedCount = program.SubscribedCount, + CommentCount = program.CommentCount, + ShareCount = program.ShareCount, + LikedCount = program.LikedCount, + CreateTime = program.CreateTime, + SerialNum = program.SerialNum, + Host = program.Owner?.MapToNeteaseUser(), + CreatorList = program.Owner != null + ? new List { program.Owner.Nickname ?? program.Owner.UserId ?? "未知主播" } + : new List(), + Duration = program.MainSong?.Duration ?? program.Duration, + Available = true + }; + } +} diff --git a/HyPlayer.NeteaseProvider/Mappers/PlaylistItemToNeteasePlaylistMapper.cs b/HyPlayer.NeteaseProvider/Mappers/PlaylistItemToNeteasePlaylistMapper.cs index 7c44f25..5ce1f76 100644 --- a/HyPlayer.NeteaseProvider/Mappers/PlaylistItemToNeteasePlaylistMapper.cs +++ b/HyPlayer.NeteaseProvider/Mappers/PlaylistItemToNeteasePlaylistMapper.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts; +using HyPlayer.NeteaseApi.ApiContracts; using HyPlayer.NeteaseApi.ApiContracts.Playlist; using HyPlayer.NeteaseApi.Models.ResponseModels; using HyPlayer.NeteaseProvider.Models; diff --git a/HyPlayer.NeteaseProvider/Mappers/RadioChannelToNeteaseRadioChannelMapper.cs b/HyPlayer.NeteaseProvider/Mappers/RadioChannelToNeteaseRadioChannelMapper.cs index 0910d64..2b16b75 100644 --- a/HyPlayer.NeteaseProvider/Mappers/RadioChannelToNeteaseRadioChannelMapper.cs +++ b/HyPlayer.NeteaseProvider/Mappers/RadioChannelToNeteaseRadioChannelMapper.cs @@ -5,14 +5,55 @@ namespace HyPlayer.NeteaseProvider.Mappers; public static class RadioChannelToNeteaseRadioChannelMapper { + /// + /// 将 DjRadioChannelDto 映射到 NeteaseRadioChannel + /// public static NeteaseRadioChannel MapToNeteaseRadioChannel(this DjRadioChannelDto radioChannel) { - // TODO: Implement mapping return new NeteaseRadioChannel { - ActualId = radioChannel.Id, - Name = radioChannel.Name ?? "", + ActualId = radioChannel.Id!, + Name = radioChannel.Name ?? "未知电台", Description = radioChannel.Description, + ProgramCount = radioChannel.ProgramCount, + CreateTime = radioChannel.CreateTime, + SubscribedCount = radioChannel.SubscribedCount, + CoverUrl = radioChannel.CoverUrl, + CategoryId = radioChannel.CategoryId, + Category = radioChannel.Category, + SecondCategoryId = radioChannel.SecondCategoryId, + SecondCategory = radioChannel.SecondCategory, + LikedCount = radioChannel.LikedCount, + CommentCount = radioChannel.CommentCount, + ShareCount = radioChannel.ShareCount, + PlayCount = radioChannel.PlayCount, + RecommendText = radioChannel.RecommendText, + Price = radioChannel.Price, + Bought = radioChannel.Bought, + LastProgramCreateTime = radioChannel.LastProgramCreateTime, + LastProgramId = radioChannel.LastProgramId, + LastProgramName = radioChannel.LastProgramName, + IsHighQuality = radioChannel.IsHighQuality, + Subscribed = radioChannel.Subscribed, + CreatorList = new List() }; } + + /// + /// 将 DjRadioChannelWithDjDto 映射到 NeteaseRadioChannel + /// + public static NeteaseRadioChannel MapToNeteaseRadioChannel(this DjRadioChannelWithDjDto radioChannel) + { + var channel = ((DjRadioChannelDto)radioChannel).MapToNeteaseRadioChannel(); + + if (radioChannel.DjData != null) + { + var host = radioChannel.DjData.MapToNeteaseUser(); + channel.Host = host; + channel.CreatorList?.Clear(); + channel.CreatorList?.Add(host.Name); + } + + return channel; + } } \ No newline at end of file diff --git a/HyPlayer.NeteaseProvider/Mappers/SongDetailItemToNeteaseMusicMapper.cs b/HyPlayer.NeteaseProvider/Mappers/SongDetailItemToNeteaseMusicMapper.cs index 1d166a2..fb7e737 100644 --- a/HyPlayer.NeteaseProvider/Mappers/SongDetailItemToNeteaseMusicMapper.cs +++ b/HyPlayer.NeteaseProvider/Mappers/SongDetailItemToNeteaseMusicMapper.cs @@ -73,4 +73,20 @@ public static NeteaseSong MapToNeteaseMusic(this SongWithPrivilegeDto item) CoverUrl = item.Album?.PictureUrl }; } + public static NeteaseSong MapToNeteaseMusic(this ArtistSongDto item) + { + return new NeteaseSong + { + Name = item.Name ?? "未知歌曲", + ActualId = item.Id!, + Album = item.Album.MapToNeteaseAlbum(), + CreatorList = item.Artists is { Length: > 0 } + ? item.Artists.Select(ar => ar.Name ?? "未知歌手").ToList() + : new List(), + Duration = item.Duration, + Available = item.Privilege?.PlayLevel is not (null or "none"), + Artists = item.Artists?.Select(ar => (PersonBase)ar.MapToNeteaseArtist()).ToList(), + CoverUrl = item.Album?.PictureUrl + }; + } } \ No newline at end of file diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseActionGettableContainer.cs b/HyPlayer.NeteaseProvider/Models/NeteaseActionGettableContainer.cs index 7b4811a..00fe403 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseActionGettableContainer.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseActionGettableContainer.cs @@ -21,7 +21,7 @@ public NeteaseActionGettableContainer(Func>> gette public Func>>? Getter { get; set; } - public override async Task> GetAllItemsAsync(CancellationToken ctk = new()) + public override async Task> GetAllItemsAsync(CancellationToken ctk = default) { return await (Getter?.Invoke() ?? Task.FromResult(new List())); } @@ -38,13 +38,13 @@ public NeteaseActionGettableProgressiveContainer( public Func)>>? ProgressiveGetter { get; set; } - public async Task<(bool, List)> GetProgressiveItemsListAsync(int start, int count, CancellationToken ctk = new()) + public async Task<(bool, List)> GetProgressiveItemsListAsync(int start, int count, CancellationToken ctk = default) { return await (ProgressiveGetter?.Invoke(start, count) ?? Task.FromResult((false, new List()))); } - public override async Task> GetAllItemsAsync(CancellationToken ctk = new()) + public override async Task> GetAllItemsAsync(CancellationToken ctk = default) { return (await GetProgressiveItemsListAsync(0, MaxProgressiveCount, ctk)).Item2; } @@ -64,7 +64,7 @@ public NeteaseActionGettableUndetermindContainer( public Func>>? ProgressiveGetter { get; set; } - public override async Task> GetNextItemsRangeAsync(CancellationToken ctk = new CancellationToken()) + public override async Task> GetNextItemsRangeAsync(CancellationToken ctk = default) { return await (ProgressiveGetter?.Invoke() ?? Task.FromResult(new List())); diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseAlbum.cs b/HyPlayer.NeteaseProvider/Models/NeteaseAlbum.cs index b05f3f3..73289ab 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseAlbum.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseAlbum.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseProvider.Constants; +using HyPlayer.NeteaseProvider.Constants; using HyPlayer.PlayCore.Abstraction.Interfaces.ProvidableItem; using HyPlayer.PlayCore.Abstraction.Models; using HyPlayer.PlayCore.Abstraction.Models.Containers; @@ -48,7 +48,7 @@ public Task GetCoverAsync(ImageResourceQualityTag? qualityTa public string? Translation { get; set; } public string? Description { get; set; } - public Task?> GetCreatorsAsync(CancellationToken ctk = new()) + public Task?> GetCreatorsAsync(CancellationToken ctk = default) { if (Artists is null) return Task.FromResult?>(null); return Task.FromResult(Artists?.Select(ar => (PersonBase)ar).ToList()); diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseArtist.cs b/HyPlayer.NeteaseProvider/Models/NeteaseArtist.cs index f6306c4..93d8678 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseArtist.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseArtist.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseProvider.Constants; +using HyPlayer.NeteaseProvider.Constants; using HyPlayer.PlayCore.Abstraction.Models; using HyPlayer.PlayCore.Abstraction.Models.Containers; @@ -9,7 +9,7 @@ public class NeteaseArtist : ArtistBase public override string ProviderId => "ncm"; public override string TypeId => NeteaseTypeIds.Artist; - public override Task> GetSubContainerAsync(CancellationToken ctk = new()) + public override Task> GetSubContainerAsync(CancellationToken ctk = default) { return Task.FromResult(new List() diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseArtistSubContainer.cs b/HyPlayer.NeteaseProvider/Models/NeteaseArtistSubContainer.cs index 3c061da..04bf6f6 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseArtistSubContainer.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseArtistSubContainer.cs @@ -1,5 +1,6 @@ -using HyPlayer.NeteaseApi.ApiContracts; +using HyPlayer.NeteaseApi.ApiContracts; using HyPlayer.NeteaseApi.ApiContracts.Artist; +using HyPlayer.NeteaseApi.Extensions; using HyPlayer.NeteaseProvider.Constants; using HyPlayer.NeteaseProvider.Mappers; using HyPlayer.PlayCore.Abstraction.Interfaces.PlayListContainer; @@ -13,105 +14,46 @@ public class NeteaseArtistSubContainer : LinerContainerBase, IProgressiveLoading public override string ProviderId => "ncm"; public override string TypeId => NeteaseTypeIds.Artist; - public override async Task> GetAllItemsAsync(CancellationToken ctk = new()) + public override async Task> GetAllItemsAsync(CancellationToken ctk = default) { if (ActualId != null) { var itemType = ActualId.Substring(0, 3); var artistId = ActualId.Substring(3); - switch (itemType) - { - case "hot": - default: - var result = await NeteaseProvider.Instance.RequestAsync( + var resTime = await NeteaseProvider.Instance.RequestAsync( NeteaseApis.ArtistSongsApi, new ArtistSongsRequest { ArtistId = artistId, - OrderType = ArtistSongsOrderType.Hot, Offset = 0, Limit = 50 }); - return result.Match( - success => - success.Songs?.Select(song => (ProvidableItemBase)song.MapToNeteaseMusic()).ToList() ?? [], - error => new List() - ); - case "tim": - var resTime = await NeteaseProvider.Instance.RequestAsync( - NeteaseApis.ArtistSongsApi, - new ArtistSongsRequest - { - ArtistId = artistId, - OrderType = ArtistSongsOrderType.Time, - Offset = 0, - Limit = 50 - }); - return resTime.Match( - success => - success.Songs?.Select(song => (ProvidableItemBase)song.MapToNeteaseMusic()).ToList() ?? [], - error => new List() - ); - case "alb": - var resAlbum = - await NeteaseProvider.Instance.RequestAsync( - NeteaseApis.ArtistAlbumsApi, - new ArtistAlbumsRequest() - { - ArtistId = artistId, - Limit = 50, - Start = 0 - }); - return resAlbum.Match( - success => - success.Albums?.Select(alb => (ProvidableItemBase)alb.MapToNeteaseAlbum()!).ToList() ?? new(), - error => new List() - ); - } + return resTime.Match( + success => + success.Songs?.Select(song => (ProvidableItemBase)song.MapToNeteaseMusic()).ToList() ?? [], + error => new List() + ); } else throw new ArgumentNullException(); } - public async Task<(bool, List)> GetProgressiveItemsListAsync(int start = 0, int count = 50, CancellationToken ctk = new()) + public async Task<(bool, List)> GetProgressiveItemsListAsync(int start = 0, int count = 50, CancellationToken ctk = default) { if(ActualId!= null) { var itemType = ActualId.Substring(0, 3); var artistId = ActualId.Substring(3); - switch (itemType) - { - case "hot": - default: - var result = await NeteaseProvider.Instance.RequestAsync( - NeteaseApis.ArtistSongsApi, - new ArtistSongsRequest - { - ArtistId = artistId, - OrderType = ArtistSongsOrderType.Hot, - Offset = start, - Limit = count - }); - return result.Match( + var resTime = await NeteaseProvider.Instance.RequestAsync( + NeteaseApis.ArtistSongsApi, + new ArtistSongsRequest + { + ArtistId = artistId, + Offset = 0, + Limit = 50 + }); + return resTime.Match( success => (success.HasMore, success.Songs?.Select(song => (ProvidableItemBase)song.MapToNeteaseMusic()).ToList() ?? new List()), - error => (false, new List()) - ); - case "tim": - var resTime = await NeteaseProvider.Instance.RequestAsync( - NeteaseApis.ArtistSongsApi, - new ArtistSongsRequest - { - ArtistId = artistId, - OrderType = ArtistSongsOrderType.Hot, - Offset = 0, - Limit = 50 - }); - return resTime.Match( - success => (success.HasMore, - success.Songs?.Select(song => (ProvidableItemBase)song.MapToNeteaseMusic()).ToList() ?? new List()), - error => (false, new List()) - ); - - } + error => (false, new List())); } else throw new ArgumentNullException(); } diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseImageResource.cs b/HyPlayer.NeteaseProvider/Models/NeteaseImageResource.cs index 81fce7a..37afbb5 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseImageResource.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseImageResource.cs @@ -1,4 +1,4 @@ -using HyPlayer.PlayCore.Abstraction.Models; +using HyPlayer.PlayCore.Abstraction.Models; using HyPlayer.PlayCore.Abstraction.Models.Resources; namespace HyPlayer.NeteaseProvider.Models; diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseImageResourceQualityTag.cs b/HyPlayer.NeteaseProvider/Models/NeteaseImageResourceQualityTag.cs index e5a0334..e2aa164 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseImageResourceQualityTag.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseImageResourceQualityTag.cs @@ -1,4 +1,4 @@ -using HyPlayer.PlayCore.Abstraction.Models.Resources; +using HyPlayer.PlayCore.Abstraction.Models.Resources; namespace HyPlayer.NeteaseProvider.Models { diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseMusicResource.cs b/HyPlayer.NeteaseProvider/Models/NeteaseMusicResource.cs index 1dc3140..768e74b 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseMusicResource.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseMusicResource.cs @@ -1,4 +1,4 @@ -using HyPlayer.PlayCore.Abstraction.Models; +using HyPlayer.PlayCore.Abstraction.Models; using HyPlayer.PlayCore.Abstraction.Models.Resources; namespace HyPlayer.NeteaseProvider.Models; diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseMv.cs b/HyPlayer.NeteaseProvider/Models/NeteaseMv.cs index dd336a8..db43f44 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseMv.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseMv.cs @@ -10,7 +10,7 @@ public class NeteaseMv : ProvidableItemBase, IHasCover public override string ProviderId => "ncm"; public override string TypeId => NeteaseTypeIds.Mv; public string? CoverUrl { get; set; } - public async Task GetCoverAsync(ImageResourceQualityTag? qualityTag = null, CancellationToken ctk = new CancellationToken()) + public async Task GetCoverAsync(ImageResourceQualityTag? qualityTag = null, CancellationToken ctk = default) { if (qualityTag is NeteaseImageResourceQualityTag neteaseImageResourceQualityTag) { diff --git a/HyPlayer.NeteaseProvider/Models/NeteasePersonalFMContainer.cs b/HyPlayer.NeteaseProvider/Models/NeteasePersonalFMContainer.cs index 4bcbdef..8b18420 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteasePersonalFMContainer.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteasePersonalFMContainer.cs @@ -14,7 +14,7 @@ public class NeteasePersonalFMContainer : UndeterminedContainerBase public string RecommendType = "DEFAULT"; - public override async Task> GetNextItemsRangeAsync(CancellationToken ctk = new CancellationToken()) + public override async Task> GetNextItemsRangeAsync(CancellationToken ctk = default) { return (await NeteaseProvider.Instance.RequestAsync(NeteaseApis.PersonalFmApi, new PersonalFmRequest() { Mode = RecommendType }, ctk)) .Match(s => s.Items?.Select(t => (ProvidableItemBase)t.MapToNeteaseMusic()).ToList() ?? new List(), diff --git a/HyPlayer.NeteaseProvider/Models/NeteasePlaylist.cs b/HyPlayer.NeteaseProvider/Models/NeteasePlaylist.cs index 4d5de6f..0f63a77 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteasePlaylist.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteasePlaylist.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts; +using HyPlayer.NeteaseApi.ApiContracts; using HyPlayer.NeteaseApi.ApiContracts.Playlist; using HyPlayer.NeteaseProvider.Constants; using HyPlayer.NeteaseProvider.Mappers; @@ -28,7 +28,7 @@ public class NeteasePlaylist : LinerContainerBase, IProgressiveLoadingContainer, public long ShareCount { get; set; } public bool IsNewImported { get; set; } - public async Task UpdatePlaylistInfoAsync(CancellationToken ctk = new()) + public async Task UpdatePlaylistInfoAsync(CancellationToken ctk = default) { var results = await NeteaseProvider.Instance.RequestAsync( NeteaseApis.PlaylistDetailApi, @@ -59,7 +59,7 @@ public class NeteasePlaylist : LinerContainerBase, IProgressiveLoadingContainer, }, error => false); } - public async Task UpdateTrackListAsync(CancellationToken ctk = new()) + public async Task UpdateTrackListAsync(CancellationToken ctk = default) { if (ActualId == null) throw new ArgumentNullException(); _trackIds = (await NeteaseProvider.Instance.RequestAsync(NeteaseApis.PlaylistTracksGetApi, @@ -71,7 +71,7 @@ public class NeteasePlaylist : LinerContainerBase, IProgressiveLoadingContainer, error => { return Array.Empty(); }); } - public override async Task> GetAllItemsAsync(CancellationToken ctk = new()) + public override async Task> GetAllItemsAsync(CancellationToken ctk = default) { if (_trackIds is null) await UpdateTrackListAsync(ctk); @@ -82,7 +82,7 @@ public class NeteasePlaylist : LinerContainerBase, IProgressiveLoadingContainer, } public async Task<(bool, List)> GetProgressiveItemsListAsync( - int start, int count, CancellationToken ctk = new()) + int start, int count, CancellationToken ctk = default) { if (_trackIds is null) await UpdatePlaylistInfoAsync(ctk); @@ -98,7 +98,7 @@ public class NeteasePlaylist : LinerContainerBase, IProgressiveLoadingContainer, public string? Description { get; set; } - public Task?> GetCreatorsAsync(CancellationToken ctk = new()) + public Task?> GetCreatorsAsync(CancellationToken ctk = default) { return Task.FromResult(new List { Creator! })!; } diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseRadioChannel.cs b/HyPlayer.NeteaseProvider/Models/NeteaseRadioChannel.cs index 33c636e..dba98a1 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseRadioChannel.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseRadioChannel.cs @@ -1,4 +1,7 @@ -using HyPlayer.NeteaseProvider.Constants; +using HyPlayer.NeteaseApi.ApiContracts; +using HyPlayer.NeteaseApi.ApiContracts.DjChannel; +using HyPlayer.NeteaseProvider.Constants; +using HyPlayer.NeteaseProvider.Mappers; using HyPlayer.PlayCore.Abstraction.Interfaces.PlayListContainer; using HyPlayer.PlayCore.Abstraction.Interfaces.ProvidableItem; using HyPlayer.PlayCore.Abstraction.Models; @@ -12,26 +15,214 @@ public class NeteaseRadioChannel : LinerContainerBase, IProgressiveLoadingContai { public override string ProviderId => "ncm"; public override string TypeId => NeteaseTypeIds.RadioChannel; - public override async Task> GetAllItemsAsync(CancellationToken ctk = new CancellationToken()) + + /// + /// 电台节目数量 + /// + public int ProgramCount { get; set; } + + /// + /// 创建时间戳 (毫秒) + /// + public long CreateTime { get; set; } + + /// + /// 订阅人数 + /// + public long SubscribedCount { get; set; } + + /// + /// 电台封面 URL + /// + public string? CoverUrl { get; set; } + + /// + /// 类别ID + /// + public int CategoryId { get; set; } + + /// + /// 类别名称 + /// + public string? Category { get; set; } + + /// + /// 子类别ID + /// + public int SecondCategoryId { get; set; } + + /// + /// 子类别名称 + /// + public string? SecondCategory { get; set; } + + /// + /// 点赞数 + /// + public long LikedCount { get; set; } + + /// + /// 评论数 + /// + public long CommentCount { get; set; } + + /// + /// 分享数 + /// + public long ShareCount { get; set; } + + /// + /// 播放数 + /// + public long PlayCount { get; set; } + + /// + /// 推荐文本 + /// + public string? RecommendText { get; set; } + + /// + /// 价格 + /// + public float Price { get; set; } + + /// + /// 是否已购买 + /// + public bool Bought { get; set; } + + /// + /// 最后一期节目创建时间 + /// + public long LastProgramCreateTime { get; set; } + + /// + /// 最后一期节目ID + /// + public string? LastProgramId { get; set; } + + /// + /// 最后一期节目名称 + /// + public string? LastProgramName { get; set; } + + /// + /// 是否为高质量电台 + /// + public bool IsHighQuality { get; set; } + + /// + /// 是否已订阅 + /// + public bool Subscribed { get; set; } + + /// + /// 电台主播 + /// + public NeteaseUser? Host { get; set; } + + /// + /// 获取所有节目 + /// + public override async Task> GetAllItemsAsync(CancellationToken ctk = default) { - throw new NotImplementedException(); + var programs = new List(); + int offset = 0; + const int pageSize = 100; + bool hasMore = true; + + while (hasMore) + { + var (more, items) = await GetProgressiveItemsListAsync(offset, pageSize, ctk); + programs.AddRange(items.Cast()); + hasMore = more; + offset += pageSize; + } + + return programs.Cast().ToList(); } + /// + /// 获取分页节目列表 + /// public int MaxProgressiveCount => 100; - public async Task<(bool, List)> GetProgressiveItemsListAsync(int start, int count, CancellationToken ctk = new CancellationToken()) + + public async Task<(bool, List)> GetProgressiveItemsListAsync(int start, int count, CancellationToken ctk = default) { - throw new NotImplementedException(); + var result = await NeteaseProvider.Instance.RequestAsync( + NeteaseApis.DjChannelProgramsApi, + new DjChannelProgramsRequest + { + RadioId = ActualId!, + Limit = count, + Offset = start, + Asc = false + }, ctk); + + return result.Match( + success => + { + var programs = success.Data?.Programs? + .Select(p => (ProvidableItemBase)p.MapToNeteaseRadioProgram()) + .ToList() ?? new List(); + bool hasMore = success.Data?.More ?? false; + return (hasMore, programs); + }, + error => (false, new List())); } - public async Task GetCoverAsync(ImageResourceQualityTag? qualityTag = null, CancellationToken ctk = new CancellationToken()) + /// + /// 获取电台封面 + /// + public async Task GetCoverAsync(ImageResourceQualityTag? qualityTag = null, CancellationToken ctk = default) { - throw new NotImplementedException(); + var coverUrl = CoverUrl ?? ""; + if (string.IsNullOrEmpty(coverUrl)) + { + return new NeteaseImageResourceResult() + { + ExternalException = new Exception("No cover URL available"), + ResourceStatus = ResourceStatus.Success, + Uri = null! + }; + } + + if (qualityTag is NeteaseImageResourceQualityTag neteaseImageResourceQualityTag) + { + return new NeteaseImageResourceResult() + { + ExternalException = null, + ResourceStatus = ResourceStatus.Success, + Uri = new Uri($"{coverUrl}?{neteaseImageResourceQualityTag}") + }; + } + + return new NeteaseImageResourceResult() + { + ExternalException = null, + ResourceStatus = ResourceStatus.Success, + Uri = new Uri(coverUrl) + }; } + /// + /// 电台描述 + /// public string? Description { get; set; } + + /// + /// 主播名称列表 + /// public List? CreatorList { get; init; } - public async Task?> GetCreatorsAsync(CancellationToken ctk = new CancellationToken()) + + /// + /// 获取电台主播列表 + /// + public Task?> GetCreatorsAsync(CancellationToken ctk = default) { - throw new NotImplementedException(); + if (Host != null) + return Task.FromResult?>(new List { Host }); + + return Task.FromResult?>(null); } } \ No newline at end of file diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseRadioProgram.cs b/HyPlayer.NeteaseProvider/Models/NeteaseRadioProgram.cs new file mode 100644 index 0000000..02982b9 --- /dev/null +++ b/HyPlayer.NeteaseProvider/Models/NeteaseRadioProgram.cs @@ -0,0 +1,130 @@ +using HyPlayer.NeteaseProvider.Constants; +using HyPlayer.PlayCore.Abstraction.Interfaces.PlayListContainer; +using HyPlayer.PlayCore.Abstraction.Interfaces.ProvidableItem; +using HyPlayer.PlayCore.Abstraction.Models; +using HyPlayer.PlayCore.Abstraction.Models.Containers; +using HyPlayer.PlayCore.Abstraction.Models.Resources; +using HyPlayer.PlayCore.Abstraction.Models.SingleItems; + +namespace HyPlayer.NeteaseProvider.Models; + +public class NeteaseRadioProgram : SingleSongBase, IHasCover, IHasDescription, IHasCreators +{ + public override string ProviderId => "ncm"; + public override string TypeId => NeteaseTypeIds.RadioProgram; + + /// + /// 节目封面 URL + /// + public string? PictureUrl { get; set; } + + /// + /// 节目封面 URL (备用) + /// + public string? CoverUrl { get; set; } + + /// + /// 节目时长 + /// + public long ProgramDuration { get; set; } + + /// + /// 节目所属电台 + /// + public NeteaseRadioChannel? RadioChannel { get; set; } + + /// + /// 节目主歌曲 + /// + public NeteaseSong? MainSong { get; set; } + + /// + /// 是否已购买 + /// + public bool Bought { get; set; } + + /// + /// 监听人数 + /// + public long ListenerCount { get; set; } + + /// + /// 订阅人数 + /// + public long SubscribedCount { get; set; } + + /// + /// 评论数 + /// + public long CommentCount { get; set; } + + /// + /// 分享数 + /// + public long ShareCount { get; set; } + + /// + /// 点赞数 + /// + public long LikedCount { get; set; } + + /// + /// 创建时间戳 (毫秒) + /// + public long CreateTime { get; set; } + + /// + /// 期数 + /// + public int SerialNum { get; set; } + + /// + /// 节目描述 + /// + public string? Description { get; set; } + + /// + /// 主播信息 + /// + public NeteaseUser? Host { get; set; } + + public override Task?> GetCreatorsAsync(CancellationToken ctk = default) + { + if (Host != null) + return Task.FromResult?>(new List { Host }); + + return Task.FromResult?>(null); + } + + public Task GetCoverAsync(ImageResourceQualityTag? qualityTag = null, CancellationToken ctk = default) + { + var coverUrl = CoverUrl ?? PictureUrl ?? ""; + if (string.IsNullOrEmpty(coverUrl)) + { + return Task.FromResult(new NeteaseImageResourceResult() + { + ExternalException = new Exception("No cover URL available"), + ResourceStatus = ResourceStatus.Success, + Uri = null! + }); + } + + if (qualityTag is NeteaseImageResourceQualityTag neteaseImageResourceQualityTag) + { + var result = new NeteaseImageResourceResult() + { + ExternalException = null, + ResourceStatus = ResourceStatus.Success, + Uri = new Uri($"{coverUrl}?{neteaseImageResourceQualityTag}") + }; + return Task.FromResult(result as ResourceResultBase); + } + + return Task.FromResult(new NeteaseImageResourceResult() + { + ExternalException = null, + ResourceStatus = ResourceStatus.Success, + Uri = new Uri(coverUrl) + } as ResourceResultBase); + } +} diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseRawLyricInfo.cs b/HyPlayer.NeteaseProvider/Models/NeteaseRawLyricInfo.cs index 4378d90..51ae48c 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseRawLyricInfo.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseRawLyricInfo.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseProvider.Constants; +using HyPlayer.NeteaseProvider.Constants; using HyPlayer.PlayCore.Abstraction.Models; using HyPlayer.PlayCore.Abstraction.Models.Lyric; using HyPlayer.PlayCore.Abstraction.Models.Resources; diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseSearchContainer.cs b/HyPlayer.NeteaseProvider/Models/NeteaseSearchContainer.cs index 9b2b517..4ed11b7 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseSearchContainer.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseSearchContainer.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts; +using HyPlayer.NeteaseApi.ApiContracts; using HyPlayer.NeteaseApi.ApiContracts.Recommend; using HyPlayer.NeteaseApi.Bases; using HyPlayer.NeteaseApi.Models; @@ -24,12 +24,12 @@ public NeteaseSearchContainer() Name = "搜索结果"; } - public override async Task> GetAllItemsAsync(CancellationToken ctk = new()) + public override async Task> GetAllItemsAsync(CancellationToken ctk = default) { return (await GetProgressiveItemsListAsync(0, MaxProgressiveCount, ctk)).Item2; } - public async Task<(bool, List)> GetProgressiveItemsListAsync(int start, int count, CancellationToken ctk = new()) + public async Task<(bool, List)> GetProgressiveItemsListAsync(int start, int count, CancellationToken ctk = default) { switch (SearchTypeId) { diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseSong.cs b/HyPlayer.NeteaseProvider/Models/NeteaseSong.cs index 9dc31c6..e8c3a07 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseSong.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseSong.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseProvider.Constants; +using HyPlayer.NeteaseProvider.Constants; using HyPlayer.PlayCore.Abstraction.Interfaces.ProvidableItem; using HyPlayer.PlayCore.Abstraction.Models; using HyPlayer.PlayCore.Abstraction.Models.Containers; @@ -21,7 +21,7 @@ public class NeteaseSong : SingleSongBase, IHasTranslation, IHasCover public required List? Artists { get; init; } - public override Task?> GetCreatorsAsync(CancellationToken ctk = new()) + public override Task?> GetCreatorsAsync(CancellationToken ctk = default) { return Task.FromResult(Artists); } diff --git a/HyPlayer.NeteaseProvider/Models/NeteaseUser.cs b/HyPlayer.NeteaseProvider/Models/NeteaseUser.cs index 9d7e06d..90339e0 100644 --- a/HyPlayer.NeteaseProvider/Models/NeteaseUser.cs +++ b/HyPlayer.NeteaseProvider/Models/NeteaseUser.cs @@ -1,4 +1,4 @@ -using HyPlayer.NeteaseApi.ApiContracts; +using HyPlayer.NeteaseApi.ApiContracts; using HyPlayer.NeteaseApi.ApiContracts.User; using HyPlayer.NeteaseProvider.Constants; using HyPlayer.NeteaseProvider.Mappers; @@ -21,7 +21,7 @@ public class NeteaseUser : PersonBase, IHasCover, IHasDescription public string? AvatarUrl { get; set; } - public override async Task> GetSubContainerAsync(CancellationToken ctk = new()) + public override async Task> GetSubContainerAsync(CancellationToken ctk = default) { var results = await NeteaseProvider.Instance.RequestAsync(NeteaseApis.UserPlaylistApi, new UserPlaylistRequest diff --git a/HyPlayer.NeteaseProvider/NeteaseProvider.cs b/HyPlayer.NeteaseProvider/NeteaseProvider.cs index baa20f4..7066096 100644 --- a/HyPlayer.NeteaseProvider/NeteaseProvider.cs +++ b/HyPlayer.NeteaseProvider/NeteaseProvider.cs @@ -1,7 +1,11 @@ -using HyPlayer.NeteaseApi; +using HyPlayer.NeteaseApi; using HyPlayer.NeteaseApi.ApiContracts; using HyPlayer.NeteaseApi.ApiContracts.Login; using HyPlayer.NeteaseApi.ApiContracts.Playlist; +using HyPlayer.NeteaseApi.ApiContracts.Artist; +using HyPlayer.NeteaseApi.ApiContracts.Album; +using HyPlayer.NeteaseApi.ApiContracts.Video; +using HyPlayer.NeteaseApi.ApiContracts.User; using HyPlayer.NeteaseApi.ApiContracts.Recommend; using HyPlayer.NeteaseApi.ApiContracts.Song; using HyPlayer.NeteaseApi.Bases; @@ -16,6 +20,7 @@ using HyPlayer.PlayCore.Abstraction.Models.Resources; using HyPlayer.PlayCore.Abstraction.Models.SingleItems; using HyPlayer.NeteaseApi.Extensions; +using HyPlayer.NeteaseApi.ApiContracts.DjChannel; namespace HyPlayer.NeteaseProvider; @@ -157,7 +162,7 @@ public async Task> RequestAsync< } public async Task LoginEmailAsync(string email, string password, bool isMd5 = false, - CancellationToken ctk = new()) + CancellationToken ctk = default) { var request = new LoginEmailRequest() { @@ -179,7 +184,7 @@ public async Task LoginEmailAsync(string email, string password, bool isMd } public async Task LoginCellphoneAsync(string cellphone, string password, bool isMd5 = false, - CancellationToken ctk = new()) + CancellationToken ctk = default) { var request = new LoginCellphoneRequest() { @@ -201,7 +206,7 @@ public async Task LoginCellphoneAsync(string cellphone, string password, b } - public async Task> GetLyricInfoAsync(SingleSongBase song, CancellationToken ctk = new()) + public async Task> GetLyricInfoAsync(SingleSongBase song, CancellationToken ctk = default) { if (song.ActualId == null) throw new ArgumentNullException(); var results = await RequestAsync(NeteaseApis.LyricApi, new LyricRequest() { Id = song.ActualId }, ctk); @@ -212,7 +217,7 @@ public async Task LoginCellphoneAsync(string cellphone, string password, b } public async Task GetMusicResourceAsync(SingleSongBase song, ResourceQualityTag qualityTag, - CancellationToken ctk = new()) + CancellationToken ctk = default) { var quality = "exhigh"; if (qualityTag is NeteaseMusicQualityTag neteaseMusicQualityTag) @@ -248,7 +253,7 @@ public async Task LoginCellphoneAsync(string cellphone, string password, b ); } - public async Task LikeProvidableItemAsync(string inProviderId, string? targetId, CancellationToken ctk = new()) + public async Task LikeProvidableItemAsync(string inProviderId, string? targetId, CancellationToken ctk = default) { if (inProviderId.StartsWith(NeteaseTypeIds.SingleSong)) { @@ -284,10 +289,51 @@ await RequestAsync(NeteaseApis.PlaylistSubscribeApi, PlaylistId = inProviderId.Substring(2) }, ctk); } - // TODO + else if (inProviderId.StartsWith(NeteaseTypeIds.Artist)) + { + await RequestAsync(NeteaseApis.ArtistSubscribeApi, + new ArtistSubscribeRequest() + { + ArtistId = inProviderId.Substring(2) + }, ctk); + } + else if (inProviderId.StartsWith(NeteaseTypeIds.Album)) + { + await RequestAsync(NeteaseApis.AlbumSubscribeApi, + new AlbumSubscribeRequest() + { + Id = inProviderId.Substring(2), + IsSubscribe = true + }, ctk); + } + else if (inProviderId.StartsWith(NeteaseTypeIds.Mv)) + { + await RequestAsync(NeteaseApis.VideoSubscribeApi, + new VideoSubscribeRequest() + { + MvId = inProviderId.Substring(2) + }, ctk); + } + else if (inProviderId.StartsWith(NeteaseTypeIds.RadioChannel)) + { + await RequestAsync(NeteaseApis.DjChannelSubscribeApi, + new DjChannelSubscribeRequest() + { + Id = inProviderId.Substring(2), + IsSubscribe = true + }, ctk); + } + else if (inProviderId.StartsWith(NeteaseTypeIds.User)) + { + await RequestAsync(NeteaseApis.UserFollowApi, + new UserFollowRequest() + { + Id = inProviderId.Substring(2) + }, ctk); + } } - public async Task UnlikeProvidableItemAsync(string inProviderId, string? targetId, CancellationToken ctk = new()) + public async Task UnlikeProvidableItemAsync(string inProviderId, string? targetId, CancellationToken ctk = default) { if (inProviderId.StartsWith(NeteaseTypeIds.SingleSong)) { @@ -323,10 +369,56 @@ await RequestAsync(NeteaseApis.PlaylistSubscribeApi, PlaylistId = inProviderId.Substring(2) }, ctk); } - // TODO + + else if (inProviderId.StartsWith(NeteaseTypeIds.Artist)) + { + var id = inProviderId.Substring(2); + if (long.TryParse(id, out var lid)) + { + await RequestAsync(NeteaseApis.ArtistUnsubscribeApi, + new ArtistUnsubscribeRequest() + { + ArtistIds = [lid] + }, ctk); + } + } + else if (inProviderId.StartsWith(NeteaseTypeIds.Album)) + { + await RequestAsync(NeteaseApis.AlbumSubscribeApi, + new AlbumSubscribeRequest() + { + Id = inProviderId.Substring(2), + IsSubscribe = false + }, ctk); + } + else if (inProviderId.StartsWith(NeteaseTypeIds.Mv)) + { + await RequestAsync(NeteaseApis.VideoUnsubscribeApi, + new VideoUnsubscribeRequest() + { + IdList = [ inProviderId.Substring(2)] + }, ctk); + } + else if (inProviderId.StartsWith(NeteaseTypeIds.RadioChannel)) + { + await RequestAsync(NeteaseApis.DjChannelSubscribeApi, + new DjChannelSubscribeRequest() + { + Id = inProviderId.Substring(2), + IsSubscribe = false + }, ctk); + } + else if (inProviderId.StartsWith(NeteaseTypeIds.User)) + { + await RequestAsync(NeteaseApis.UserUnfollowApi, + new UserUnfollowRequest() + { + Id = inProviderId.Substring(2) + }, ctk); + } } - public async Task> GetLikedProvidableIdsAsync(string typeId, CancellationToken ctk = new()) + public async Task> GetLikedProvidableIdsAsync(string typeId, CancellationToken ctk = default) { var result = await RequestAsync(NeteaseApis.LikelistApi, new LikelistRequest() { @@ -339,7 +431,7 @@ await RequestAsync(NeteaseApis.PlaylistSubscribeApi, public async Task GetProvidableItemByIdAsync(string inProviderId, - CancellationToken ctk = new()) + CancellationToken ctk = default) { var typeId = inProviderId.Substring(0, 2); var actualId = inProviderId.Substring(2); @@ -355,7 +447,7 @@ await RequestAsync(NeteaseApis.PlaylistSubscribeApi, } public async Task> GetProvidableItemsRangeAsync( - List inProviderIds, CancellationToken ctk = new()) + List inProviderIds, CancellationToken ctk = default) { if (inProviderIds.Count == 0) return new List(); var grouped = inProviderIds.GroupBy(t => t.Substring(0, 2)).ToList(); @@ -434,7 +526,7 @@ public async Task> GetPlaylistRangeByIds(List idLi #endregion public Task SearchProvidableItemsAsync(string keyword, string typeId, - CancellationToken ctk = new()) + CancellationToken ctk = default) { return Task.FromResult(new NeteaseSearchContainer { @@ -445,7 +537,7 @@ public Task SearchProvidableItemsAsync(string keyword, string typ } as ContainerBase); } - public Task GetStoredItemsAsync(string typeId, CancellationToken ctk = new()) + public Task GetStoredItemsAsync(string typeId, CancellationToken ctk = default) { switch (typeId) { @@ -456,7 +548,7 @@ public Task SearchProvidableItemsAsync(string keyword, string typ } } - public Task GetRecommendationAsync(string? typeId = null, CancellationToken ctk = new()) + public Task GetRecommendationAsync(string? typeId = null, CancellationToken ctk = default) { // ReSharper disable once ConvertIfStatementToSwitchStatement if (typeId == NeteaseTypeIds.Playlist) // 推荐歌单 diff --git a/README.md b/README.md new file mode 100644 index 0000000..f1f6c84 --- /dev/null +++ b/README.md @@ -0,0 +1,104 @@ +# HyPlayer.NeteaseProvider + +[![NuGet Publish](https://github.com/HyPlayer/HyPlayer.NeteaseProvider/actions/workflows/nuget-push.yml/badge.svg)](https://github.com/HyPlayer/HyPlayer.NeteaseProvider/actions/workflows/nuget-push.yml) +[![License](https://img.shields.io/github/license/HyPlayer/HyPlayer.NeteaseProvider)](LICENSE) + +A comprehensive .NET provider for Netease Cloud Music API integration with HyPlayer ecosystem. + +## Overview + +HyPlayer.NeteaseProvider is a modern, type-safe provider library for integrating Netease Cloud Music services with the HyPlayer music player framework. It consists of two main components: + +- **HyPlayer.NeteaseApi** - Low-level API wrapper for Netease Cloud Music endpoints +- **HyPlayer.NeteaseProvider** - High-level provider implementation for HyPlayer integration + +## Features + +- Multi-target support: `.NET Standard 2.0` and `.NET 9.0` +- Type-safe API contracts with automatic JSON serialization +- AOT (Ahead-of-Time) compatible for .NET 9.0+ +- Async/await support throughout +- Comprehensive Netease API coverage +- Integration with HyPlayer.PlayCore abstraction layer +- Entity caching with Depository abstraction + + +## Getting Started + +### Installation + +Install the NuGet package: + +` dotnet add package HyPlayer.NeteaseProvider ` + +This will automatically include the `HyPlayer.NeteaseApi` dependency. + +### Prerequisites + +- `.NET Standard 2.0` or higher +- `.NET 9.0` or higher (for latest features and AOT support) + +## Components + +### HyPlayer.NeteaseApi (v0.1.0) + +Low-level API wrapper providing direct access to Netease Cloud Music endpoints. + +**Key Features:** +- RESTful API contract definitions +- Automatic JSON serialization with source-generated serialization context +- Support for multiple authentication methods +- Comprehensive error handling + +**Dependencies:** +- System.Text.Json v10.0.1 + +### HyPlayer.NeteaseProvider (v0.0.11) + +High-level provider implementing HyPlayer provider abstraction for seamless integration. + +**Key Features:** +- HyPlayer.PlayCore abstraction implementation +- Entity repository pattern with Depository.Abstraction +- Radio channel APIs support +- Song, playlist, and album management + +**Dependencies:** +- HyPlayer.PlayCore.Abstraction v0.1.4 +- Depository.Abstraction v3.2.0 +- HyPlayer.NeteaseApi + +## Building + +Requires `.NET SDK 10.0.0` or later (as specified in `global.json`). + +``` +# Build all projects +dotnet build + +# Build specific project +dotnet build HyPlayer.NeteaseProvider/HyPlayer.NeteaseProvider.csproj + +# Run tests +dotnet test +``` + +## Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +## License + +This project is licensed under the [License](LICENSE) - see the LICENSE file for details. + +## Related Projects + +- [HyPlayer](https://github.com/HyPlayer/HyPlayer) - Main music player application +- [HyPlayer.PlayCore](https://github.com/HyPlayer/HyPlayer.PlayCore) - Core playback abstraction +- [Depository](https://github.com/HyPlayer/Depository) - Entity repository framework + +## Support + +For issues, feature requests, or questions, please visit the [GitHub Issues](https://github.com/HyPlayer/HyPlayer.NeteaseProvider/issues) page. + +--- \ No newline at end of file