Skip to content

Commit

Permalink
feat: support image/user/* apis
Browse files Browse the repository at this point in the history
  • Loading branch information
bsdayo committed May 5, 2023
1 parent 73201d8 commit f23e137
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 23 deletions.
19 changes: 4 additions & 15 deletions UnofficialArcaeaAPI.Lib/Core/UaaAssetsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,6 @@ internal UaaAssetsApi(HttpClient client)
_client = client;
}

private static async Task<byte[]> EnsureSuccess(HttpResponseMessage resp)
{
if (resp.StatusCode != HttpStatusCode.OK)
{
var errJson = JsonSerializer.Deserialize<UaaResponse>(await resp.Content.ReadAsStringAsync())!;
throw new UaaRequestException(errJson.Status, errJson.Message!);
}

return await resp.Content.ReadAsByteArrayAsync();
}

#region /assets/icon

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

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

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

var resp = await _client.GetAsync("assets/song" + qb.Build());
return await EnsureSuccess(resp);
return await resp.EnsureDataSuccess();
}

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

var resp = await _client.GetAsync("assets/preview" + qb.Build());
return await EnsureSuccess(resp);
return await resp.EnsureDataSuccess();
}

/// <summary>
Expand Down
11 changes: 11 additions & 0 deletions UnofficialArcaeaAPI.Lib/Core/UaaImageApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace UnofficialArcaeaAPI.Lib.Core;

public sealed class UaaImageApi
{
public UaaImageUserApi User { get; }

internal UaaImageApi(HttpClient client)
{
User = new UaaImageUserApi(client);
}
}
177 changes: 177 additions & 0 deletions UnofficialArcaeaAPI.Lib/Core/UaaImageUserApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
using System.Text.Json;
using UnofficialArcaeaAPI.Lib.Models;
using UnofficialArcaeaAPI.Lib.Responses;
using UnofficialArcaeaAPI.Lib.Utils;

namespace UnofficialArcaeaAPI.Lib.Core;

public sealed class UaaImageUserApi
{
private readonly HttpClient _client;

internal UaaImageUserApi(HttpClient client)
{
_client = client;
}

#region /user/info

private async Task<byte[]> GetInfoAsyncCore(string? user, int? userCode, int recent,
AuaReplyWith replyWith)
{
var qb = new QueryBuilder()
.Add("recent", recent.ToString());

if (user is not null)
qb.Add("user_name", user);
else
qb.Add("user_code", userCode.ToString()!);

if (replyWith.HasFlag(AuaReplyWith.SongInfo))
qb.Add("with_song_info", "true");
var resp = await _client.GetAsync("image/user/info" + qb.Build());
return await resp.EnsureDataSuccess();
}

/// <summary>
/// Get user info image.
/// </summary>
/// <param name="user">User name or 9-digit user code</param>
/// <param name="recent">The number of recently played songs expected, range 0-7</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo only.</param>
/// <returns>User info image</returns>
public Task<byte[]> GetInfoAsync(string user, int recent = 0,
AuaReplyWith replyWith = AuaReplyWith.None)
=> GetInfoAsyncCore(user, null, recent, replyWith);

/// <summary>
/// Get user info image.
/// </summary>
/// <param name="userCode">9-digit user code</param>
/// <param name="recent">The number of recently played songs expected, range 0-7</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo only.</param>
/// <returns>User info image</returns>
public Task<byte[]> GetInfoAsync(int userCode, int recent = 0,
AuaReplyWith replyWith = AuaReplyWith.None)
=> GetInfoAsyncCore(null, userCode, recent, replyWith);

/// <summary>
/// Get user info image.
/// </summary>
/// <param name="user">User name or 9-digit user code</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo only.</param>
/// <returns>User info image</returns>
public Task<byte[]> GetInfoAsync(string user, AuaReplyWith replyWith)
=> GetInfoAsyncCore(user, null, 0, replyWith);

/// <summary>
/// Get user info image.
/// </summary>
/// <param name="userCode">9-digit user code</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo only.</param>
/// <returns>User info image</returns>
public Task<byte[]> GetInfoAsync(int userCode, AuaReplyWith replyWith)
=> GetInfoAsyncCore(null, userCode, 0, replyWith);

#endregion /user/info

#region /user/best

private async Task<byte[]> GetBestAsyncCore(string? user, int? userCode, string songname,
AuaSongQueryType queryType, ArcaeaDifficulty difficulty, AuaReplyWith replyWith)
{
var qb = new QueryBuilder()
.Add(queryType == AuaSongQueryType.SongId ? "song_id" : "song_name", songname)
.Add("difficulty", ((int)difficulty).ToString());

if (user is not null)
qb.Add("user_name", user);
else
qb.Add("user_code", userCode.ToString()!);

if (replyWith.HasFlag(AuaReplyWith.Recent))
qb.Add("with_recent", "true");
if (replyWith.HasFlag(AuaReplyWith.SongInfo))
qb.Add("with_song_info", "true");

var resp = await _client.GetAsync("user/best" + qb.Build());
return await resp.EnsureDataSuccess();
}

/// <summary>
/// Get user best score image.
/// </summary>
/// <param name="user">User name or 9-digit user code</param>
/// <param name="songName">Any song name for fuzzy querying or sid in Arcaea songlist</param>
/// <param name="queryType">Specify the query type between songname and songid</param>
/// <param name="difficulty">Song difficulty</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
/// <returns>User best image</returns>
public Task<byte[]> GetBestAsync(string user, string songName,
AuaSongQueryType queryType = AuaSongQueryType.SongName, ArcaeaDifficulty difficulty = ArcaeaDifficulty.Future,
AuaReplyWith replyWith = AuaReplyWith.None)
=> GetBestAsyncCore(user, null, songName, queryType, difficulty, replyWith);

/// <summary>
/// Get user best score image.
/// </summary>
/// <param name="userCode">9-digit user code</param>
/// <param name="songName">Any song name for fuzzy querying or sid in Arcaea songlist</param>
/// <param name="queryType">Specify the query type between songname and songid</param>
/// <param name="difficulty">Song difficulty</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
/// <returns>User best image</returns>
public Task<byte[]> GetBestAsync(int userCode, string songName,
AuaSongQueryType queryType = AuaSongQueryType.SongName, ArcaeaDifficulty difficulty = ArcaeaDifficulty.Future,
AuaReplyWith replyWith = AuaReplyWith.None)
=> GetBestAsyncCore(null, userCode, songName, queryType, difficulty, replyWith);

/// <summary>
/// Get user best score image.
/// </summary>
/// <param name="user">User name or 9-digit user code</param>
/// <param name="songName">Any song name for fuzzy querying</param>
/// <param name="difficulty">Song difficulty</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
/// <returns>User best image</returns>
public Task<byte[]> GetBestAsync(string user, string songName,
ArcaeaDifficulty difficulty,
AuaReplyWith replyWith = AuaReplyWith.None)
=> GetBestAsyncCore(user, null, songName, AuaSongQueryType.SongName, difficulty, replyWith);

/// <summary>
/// Get user best score image.
/// </summary>
/// <param name="userCode">9-digit user code</param>
/// <param name="songName">Any song name for fuzzy querying</param>
/// <param name="difficulty">Song difficulty</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
/// <returns>User best image</returns>
public Task<byte[]> GetBestAsync(int userCode, string songName,
ArcaeaDifficulty difficulty,
AuaReplyWith replyWith = AuaReplyWith.None)
=> GetBestAsyncCore(null, userCode, songName, AuaSongQueryType.SongName, difficulty, replyWith);

/// <summary>
/// Get user best score image.
/// </summary>
/// <param name="user">User name or 9-digit user code</param>
/// <param name="songName">Any song name for fuzzy querying</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
/// <returns>User best image</returns>
public Task<byte[]> GetBestAsync(string user, string songName, AuaReplyWith replyWith)
=> GetBestAsyncCore(user, null, songName, AuaSongQueryType.SongName, ArcaeaDifficulty.Future, replyWith);

/// <summary>
/// Get user best score image.
/// </summary>
/// <param name="userCode">9-digit user code</param>
/// <param name="songName">Any song name for fuzzy querying</param>
/// <param name="replyWith">Additional information to reply with. Supports songinfo and recent.</param>
/// <returns>User best image</returns>
public Task<byte[]> GetBestAsync(int userCode, string songName,
AuaReplyWith replyWith)
=> GetBestAsyncCore(null, userCode, songName, AuaSongQueryType.SongName, ArcaeaDifficulty.Future, replyWith);

#endregion /user/best
}
2 changes: 1 addition & 1 deletion UnofficialArcaeaAPI.Lib/Responses/UaaSongListContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ namespace UnofficialArcaeaAPI.Lib.Responses;
public class UaaSongListContent
{
[JsonPropertyName("songs")]
public UaaSongInfoContent[] Songs { get; set; }
public UaaSongInfoContent[] Songs { get; set; } = null!;
}
2 changes: 2 additions & 0 deletions UnofficialArcaeaAPI.Lib/UaaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public sealed class UaaClient
public UaaSongApi Song { get; }
public UaaAssetsApi Assets { get; }
public UaaDataApi Data { get; }
public UaaImageApi Image { get; }

public UaaClient(UaaClientOptions options)
{
Expand Down Expand Up @@ -40,5 +41,6 @@ public UaaClient(UaaClientOptions options)
Song = new UaaSongApi(client);
Assets = new UaaAssetsApi(client);
Data = new UaaDataApi(client);
Image = new UaaImageApi(client);
}
}
2 changes: 1 addition & 1 deletion UnofficialArcaeaAPI.Lib/UnofficialArcaeaAPI.Lib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<Title>UnofficialArcaeaAPI.Lib</Title>
<PackageVersion>3.0.0</PackageVersion>
<PackageVersion>3.1.0</PackageVersion>
<Authors>bsdayo</Authors>
<Description>API wrapper for UnofficialArcaeaAPI.</Description>
<PackageTags>arcaea;api</PackageTags>
Expand Down
17 changes: 11 additions & 6 deletions UnofficialArcaeaAPI.Lib/Utils/ResponseExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
using UnofficialArcaeaAPI.Lib.Responses;
using System.Net;
using System.Text.Json;
using UnofficialArcaeaAPI.Lib.Responses;

namespace UnofficialArcaeaAPI.Lib.Utils;

internal static class ResponseExtensions
{
/// <summary>
/// Because these status code has additional data, we should
/// </summary>
internal static bool HasAdditionalData(this UaaResponse response)
internal static async Task<byte[]> EnsureDataSuccess(this HttpResponseMessage resp)
{
return response.Status is <= -31 and >= -33;
if (resp.StatusCode != HttpStatusCode.OK)
{
var errJson = JsonSerializer.Deserialize<UaaResponse>(await resp.Content.ReadAsStringAsync())!;
throw new UaaRequestException(errJson.Status, errJson.Message!);
}

return await resp.Content.ReadAsByteArrayAsync();
}
}

0 comments on commit f23e137

Please sign in to comment.