Skip to content

Commit f23e137

Browse files
author
bsdayo
committed
feat: support image/user/* apis
1 parent 73201d8 commit f23e137

7 files changed

Lines changed: 207 additions & 23 deletions

File tree

‎UnofficialArcaeaAPI.Lib/Core/UaaAssetsApi.cs‎

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,6 @@ internal UaaAssetsApi(HttpClient client)
1515
_client = client;
1616
}
1717

18-
private static async Task<byte[]> EnsureSuccess(HttpResponseMessage resp)
19-
{
20-
if (resp.StatusCode != HttpStatusCode.OK)
21-
{
22-
var errJson = JsonSerializer.Deserialize<UaaResponse>(await resp.Content.ReadAsStringAsync())!;
23-
throw new UaaRequestException(errJson.Status, errJson.Message!);
24-
}
25-
26-
return await resp.Content.ReadAsByteArrayAsync();
27-
}
28-
2918
#region /assets/icon
3019

3120
private async Task<byte[]> GetIconAsyncCore(int partner, bool awakened)
@@ -34,7 +23,7 @@ private async Task<byte[]> GetIconAsyncCore(int partner, bool awakened)
3423
.Add("partner", partner.ToString())
3524
.Add("awakened", awakened.ToString());
3625
var resp = await _client.GetAsync("assets/icon" + qb.Build());
37-
return await EnsureSuccess(resp);
26+
return await resp.EnsureDataSuccess();
3827
}
3928

4029
/// <summary>
@@ -56,7 +45,7 @@ private async Task<byte[]> GetCharAsyncCore(int partner, bool awakened)
5645
.Add("partner", partner.ToString())
5746
.Add("awakened", awakened.ToString());
5847
var resp = await _client.GetAsync("assets/char" + qb.Build());
59-
return await EnsureSuccess(resp);
48+
return await resp.EnsureDataSuccess();
6049
}
6150

6251
/// <summary>
@@ -88,7 +77,7 @@ private async Task<byte[]> GetSongAsyncCore(string songNameOrFileName, AuaSongQu
8877
qb.Add("difficulty", ((int)difficulty).ToString());
8978

9079
var resp = await _client.GetAsync("assets/song" + qb.Build());
91-
return await EnsureSuccess(resp);
80+
return await resp.EnsureDataSuccess();
9281
}
9382

9483
/// <summary>
@@ -172,7 +161,7 @@ private async Task<byte[]> GetPreviewAsyncCore(string songName, AuaSongQueryType
172161
qb.Add("difficulty", ((int)difficulty).ToString());
173162

174163
var resp = await _client.GetAsync("assets/preview" + qb.Build());
175-
return await EnsureSuccess(resp);
164+
return await resp.EnsureDataSuccess();
176165
}
177166

178167
/// <summary>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace UnofficialArcaeaAPI.Lib.Core;
2+
3+
public sealed class UaaImageApi
4+
{
5+
public UaaImageUserApi User { get; }
6+
7+
internal UaaImageApi(HttpClient client)
8+
{
9+
User = new UaaImageUserApi(client);
10+
}
11+
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
using System.Text.Json;
2+
using UnofficialArcaeaAPI.Lib.Models;
3+
using UnofficialArcaeaAPI.Lib.Responses;
4+
using UnofficialArcaeaAPI.Lib.Utils;
5+
6+
namespace UnofficialArcaeaAPI.Lib.Core;
7+
8+
public sealed class UaaImageUserApi
9+
{
10+
private readonly HttpClient _client;
11+
12+
internal UaaImageUserApi(HttpClient client)
13+
{
14+
_client = client;
15+
}
16+
17+
#region /user/info
18+
19+
private async Task<byte[]> GetInfoAsyncCore(string? user, int? userCode, int recent,
20+
AuaReplyWith replyWith)
21+
{
22+
var qb = new QueryBuilder()
23+
.Add("recent", recent.ToString());
24+
25+
if (user is not null)
26+
qb.Add("user_name", user);
27+
else
28+
qb.Add("user_code", userCode.ToString()!);
29+
30+
if (replyWith.HasFlag(AuaReplyWith.SongInfo))
31+
qb.Add("with_song_info", "true");
32+
var resp = await _client.GetAsync("image/user/info" + qb.Build());
33+
return await resp.EnsureDataSuccess();
34+
}
35+
36+
/// <summary>
37+
/// Get user info image.
38+
/// </summary>
39+
/// <param name="user">User name or 9-digit user code</param>
40+
/// <param name="recent">The number of recently played songs expected, range 0-7</param>
41+
/// <param name="replyWith">Additional information to reply with. Supports songinfo only.</param>
42+
/// <returns>User info image</returns>
43+
public Task<byte[]> GetInfoAsync(string user, int recent = 0,
44+
AuaReplyWith replyWith = AuaReplyWith.None)
45+
=> GetInfoAsyncCore(user, null, recent, replyWith);
46+
47+
/// <summary>
48+
/// Get user info image.
49+
/// </summary>
50+
/// <param name="userCode">9-digit user code</param>
51+
/// <param name="recent">The number of recently played songs expected, range 0-7</param>
52+
/// <param name="replyWith">Additional information to reply with. Supports songinfo only.</param>
53+
/// <returns>User info image</returns>
54+
public Task<byte[]> GetInfoAsync(int userCode, int recent = 0,
55+
AuaReplyWith replyWith = AuaReplyWith.None)
56+
=> GetInfoAsyncCore(null, userCode, recent, replyWith);
57+
58+
/// <summary>
59+
/// Get user info image.
60+
/// </summary>
61+
/// <param name="user">User name or 9-digit user code</param>
62+
/// <param name="replyWith">Additional information to reply with. Supports songinfo only.</param>
63+
/// <returns>User info image</returns>
64+
public Task<byte[]> GetInfoAsync(string user, AuaReplyWith replyWith)
65+
=> GetInfoAsyncCore(user, null, 0, replyWith);
66+
67+
/// <summary>
68+
/// Get user info image.
69+
/// </summary>
70+
/// <param name="userCode">9-digit user code</param>
71+
/// <param name="replyWith">Additional information to reply with. Supports songinfo only.</param>
72+
/// <returns>User info image</returns>
73+
public Task<byte[]> GetInfoAsync(int userCode, AuaReplyWith replyWith)
74+
=> GetInfoAsyncCore(null, userCode, 0, replyWith);
75+
76+
#endregion /user/info
77+
78+
#region /user/best
79+
80+
private async Task<byte[]> GetBestAsyncCore(string? user, int? userCode, string songname,
81+
AuaSongQueryType queryType, ArcaeaDifficulty difficulty, AuaReplyWith replyWith)
82+
{
83+
var qb = new QueryBuilder()
84+
.Add(queryType == AuaSongQueryType.SongId ? "song_id" : "song_name", songname)
85+
.Add("difficulty", ((int)difficulty).ToString());
86+
87+
if (user is not null)
88+
qb.Add("user_name", user);
89+
else
90+
qb.Add("user_code", userCode.ToString()!);
91+
92+
if (replyWith.HasFlag(AuaReplyWith.Recent))
93+
qb.Add("with_recent", "true");
94+
if (replyWith.HasFlag(AuaReplyWith.SongInfo))
95+
qb.Add("with_song_info", "true");
96+
97+
var resp = await _client.GetAsync("user/best" + qb.Build());
98+
return await resp.EnsureDataSuccess();
99+
}
100+
101+
/// <summary>
102+
/// Get user best score image.
103+
/// </summary>
104+
/// <param name="user">User name or 9-digit user code</param>
105+
/// <param name="songName">Any song name for fuzzy querying or sid in Arcaea songlist</param>
106+
/// <param name="queryType">Specify the query type between songname and songid</param>
107+
/// <param name="difficulty">Song difficulty</param>
108+
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
109+
/// <returns>User best image</returns>
110+
public Task<byte[]> GetBestAsync(string user, string songName,
111+
AuaSongQueryType queryType = AuaSongQueryType.SongName, ArcaeaDifficulty difficulty = ArcaeaDifficulty.Future,
112+
AuaReplyWith replyWith = AuaReplyWith.None)
113+
=> GetBestAsyncCore(user, null, songName, queryType, difficulty, replyWith);
114+
115+
/// <summary>
116+
/// Get user best score image.
117+
/// </summary>
118+
/// <param name="userCode">9-digit user code</param>
119+
/// <param name="songName">Any song name for fuzzy querying or sid in Arcaea songlist</param>
120+
/// <param name="queryType">Specify the query type between songname and songid</param>
121+
/// <param name="difficulty">Song difficulty</param>
122+
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
123+
/// <returns>User best image</returns>
124+
public Task<byte[]> GetBestAsync(int userCode, string songName,
125+
AuaSongQueryType queryType = AuaSongQueryType.SongName, ArcaeaDifficulty difficulty = ArcaeaDifficulty.Future,
126+
AuaReplyWith replyWith = AuaReplyWith.None)
127+
=> GetBestAsyncCore(null, userCode, songName, queryType, difficulty, replyWith);
128+
129+
/// <summary>
130+
/// Get user best score image.
131+
/// </summary>
132+
/// <param name="user">User name or 9-digit user code</param>
133+
/// <param name="songName">Any song name for fuzzy querying</param>
134+
/// <param name="difficulty">Song difficulty</param>
135+
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
136+
/// <returns>User best image</returns>
137+
public Task<byte[]> GetBestAsync(string user, string songName,
138+
ArcaeaDifficulty difficulty,
139+
AuaReplyWith replyWith = AuaReplyWith.None)
140+
=> GetBestAsyncCore(user, null, songName, AuaSongQueryType.SongName, difficulty, replyWith);
141+
142+
/// <summary>
143+
/// Get user best score image.
144+
/// </summary>
145+
/// <param name="userCode">9-digit user code</param>
146+
/// <param name="songName">Any song name for fuzzy querying</param>
147+
/// <param name="difficulty">Song difficulty</param>
148+
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
149+
/// <returns>User best image</returns>
150+
public Task<byte[]> GetBestAsync(int userCode, string songName,
151+
ArcaeaDifficulty difficulty,
152+
AuaReplyWith replyWith = AuaReplyWith.None)
153+
=> GetBestAsyncCore(null, userCode, songName, AuaSongQueryType.SongName, difficulty, replyWith);
154+
155+
/// <summary>
156+
/// Get user best score image.
157+
/// </summary>
158+
/// <param name="user">User name or 9-digit user code</param>
159+
/// <param name="songName">Any song name for fuzzy querying</param>
160+
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
161+
/// <returns>User best image</returns>
162+
public Task<byte[]> GetBestAsync(string user, string songName, AuaReplyWith replyWith)
163+
=> GetBestAsyncCore(user, null, songName, AuaSongQueryType.SongName, ArcaeaDifficulty.Future, replyWith);
164+
165+
/// <summary>
166+
/// Get user best score image.
167+
/// </summary>
168+
/// <param name="userCode">9-digit user code</param>
169+
/// <param name="songName">Any song name for fuzzy querying</param>
170+
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
171+
/// <returns>User best image</returns>
172+
public Task<byte[]> GetBestAsync(int userCode, string songName,
173+
AuaReplyWith replyWith)
174+
=> GetBestAsyncCore(null, userCode, songName, AuaSongQueryType.SongName, ArcaeaDifficulty.Future, replyWith);
175+
176+
#endregion /user/best
177+
}

‎UnofficialArcaeaAPI.Lib/Responses/UaaSongListContent.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ namespace UnofficialArcaeaAPI.Lib.Responses;
55
public class UaaSongListContent
66
{
77
[JsonPropertyName("songs")]
8-
public UaaSongInfoContent[] Songs { get; set; }
8+
public UaaSongInfoContent[] Songs { get; set; } = null!;
99
}

‎UnofficialArcaeaAPI.Lib/UaaClient.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public sealed class UaaClient
88
public UaaSongApi Song { get; }
99
public UaaAssetsApi Assets { get; }
1010
public UaaDataApi Data { get; }
11+
public UaaImageApi Image { get; }
1112

1213
public UaaClient(UaaClientOptions options)
1314
{
@@ -40,5 +41,6 @@ public UaaClient(UaaClientOptions options)
4041
Song = new UaaSongApi(client);
4142
Assets = new UaaAssetsApi(client);
4243
Data = new UaaDataApi(client);
44+
Image = new UaaImageApi(client);
4345
}
4446
}

‎UnofficialArcaeaAPI.Lib/UnofficialArcaeaAPI.Lib.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<Title>UnofficialArcaeaAPI.Lib</Title>
5-
<PackageVersion>3.0.0</PackageVersion>
5+
<PackageVersion>3.1.0</PackageVersion>
66
<Authors>bsdayo</Authors>
77
<Description>API wrapper for UnofficialArcaeaAPI.</Description>
88
<PackageTags>arcaea;api</PackageTags>
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
using UnofficialArcaeaAPI.Lib.Responses;
1+
using System.Net;
2+
using System.Text.Json;
3+
using UnofficialArcaeaAPI.Lib.Responses;
24

35
namespace UnofficialArcaeaAPI.Lib.Utils;
46

57
internal static class ResponseExtensions
68
{
7-
/// <summary>
8-
/// Because these status code has additional data, we should
9-
/// </summary>
10-
internal static bool HasAdditionalData(this UaaResponse response)
9+
internal static async Task<byte[]> EnsureDataSuccess(this HttpResponseMessage resp)
1110
{
12-
return response.Status is <= -31 and >= -33;
11+
if (resp.StatusCode != HttpStatusCode.OK)
12+
{
13+
var errJson = JsonSerializer.Deserialize<UaaResponse>(await resp.Content.ReadAsStringAsync())!;
14+
throw new UaaRequestException(errJson.Status, errJson.Message!);
15+
}
16+
17+
return await resp.Content.ReadAsByteArrayAsync();
1318
}
1419
}

0 commit comments

Comments
 (0)