Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mods and ruleset parameters to GetDifficultyAttributesAsync #2

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
6 changes: 4 additions & 2 deletions OsuSharp/Converters/StringEnumConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer
// Write the description attribute value to the writer.
writer.WriteValue(descriptionAttribute.Description);
}

throw new JsonSerializationException($"{value?.GetType()} is not an enum value or array.");
else
{
throw new JsonSerializationException($"{value?.GetType()} is not an enum value or array.");
}
minisbett marked this conversation as resolved.
Show resolved Hide resolved
}
}
61 changes: 59 additions & 2 deletions OsuSharp/Endpoints/Beatmaps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,67 @@ public async Task<BeatmapExtended[]> GetBeatmapsAsync(params int[] ids)
/// <a href="https://osu.ppy.sh/docs/index.html#get-beatmap"/>
/// </summary>
/// <param name="id">The ID of the beatmap.</param>
/// <param name="ruleset">The ruleset to get the attributes from.</param>
minisbett marked this conversation as resolved.
Show resolved Hide resolved
/// <returns>The difficulty attributes or null, if the beatmap was not found.</returns>
public async Task<DifficultyAttributes?> GetDifficultyAttributesAsync(int id)
public Task<DifficultyAttributes?> GetDifficultyAttributesAsync(int id, Ruleset ruleset = Ruleset.Osu) => GetDifficultyAttributesInternalAsync(id, 0, ruleset);

/// <summary>
/// Gets the difficulty attributes of the beatmap with the specified ID, optionally in the specified ruleset and the specified mods.
/// If the beatmap was not found, null is returned.
/// <br/><br/>
/// API notes:<br/>
/// <a href="https://osu.ppy.sh/docs/index.html#get-beatmap"/>
/// </summary>
/// <param name="id">The ID of the beatmap.</param>
/// <param name="mods">Optional. The mods to consider for the attributes, as an array of the acronyms.</param>
/// <param name="ruleset">Optional. The ruleset to get the attributes from. Defaults to osu!standard.</param>
/// <returns>The difficulty attributes or null, if the beatmap was not found.</returns>
public Task<DifficultyAttributes?> GetDifficultyAttributesAsync(int id, string[] mods, Ruleset ruleset = Ruleset.Osu) => GetDifficultyAttributesInternalAsync(id, mods, ruleset);

/// <summary>
/// Gets the difficulty attributes of the beatmap with the specified ID, optionally in the specified ruleset and the specified mods.
/// If the beatmap was not found, null is returned.
/// <br/><br/>
/// API notes:<br/>
/// <a href="https://osu.ppy.sh/docs/index.html#get-beatmap"/>
/// </summary>
/// <param name="id">The ID of the beatmap.</param>
/// <param name="mods">Optional. The mods to consider for the attributes, as a string with the acronyms, such as "HDHR".</param>
/// <param name="ruleset">Optional. The ruleset to get the attributes from. Defaults to osu!standard.</param>
/// <returns>The difficulty attributes or null, if the beatmap was not found.</returns>
public Task<DifficultyAttributes?> GetDifficultyAttributesAsync(int id, string mods, Ruleset ruleset = Ruleset.Osu) => GetDifficultyAttributesInternalAsync(id, mods.Chunk(2).Select(chunk => new string(chunk)).ToArray(), ruleset);
minisbett marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Gets the difficulty attributes of the beatmap with the specified ID, optionally in the specified ruleset and the specified mods.
/// If the beatmap was not found, null is returned.
/// <br/><br/>
/// API notes:<br/>
/// <a href="https://osu.ppy.sh/docs/index.html#get-beatmap"/>
/// </summary>
/// <param name="id">The ID of the beatmap.</param>
/// <param name="mods">Optional. The mods to consider for the attributes, as the bitset number.</param>
/// <param name="ruleset">Optional. The ruleset to get the attributes from. Defaults to osu!standard.</param>
/// <returns>The difficulty attributes or null, if the beatmap was not found.</returns>
public Task<DifficultyAttributes?> GetDifficultyAttributesAsync(int id, int mods, Ruleset ruleset = Ruleset.Osu) => GetDifficultyAttributesInternalAsync(id, mods, ruleset);

/// <summary>
/// Gets the difficulty attributes of the beatmap with the specified ID, in the specified ruleset and with the specified mods.
/// If the beatmap was not found, null is returned.
/// <br/><br/>
/// API notes:<br/>
/// <a href="https://osu.ppy.sh/docs/index.html#get-beatmap"/>
/// </summary>
/// <param name="id">The ID of the beatmap.</param>
/// <param name="mods">The mods to consider for the attributes, in the raw format passed to the API.</param>
/// <param name="ruleset">The ruleset to get the attributes from.</param>
/// <returns>The difficulty attributes or null, if the beatmap was not found.</returns>
private async Task<DifficultyAttributes?> GetDifficultyAttributesInternalAsync(int id, object mods, Ruleset ruleset)
{
// Send the request and return the difficulty attributes object.
return await GetFromJsonAsync<DifficultyAttributes>($"beatmaps/{id}/attributes", jsonSelector: x => x["attributes"], method: HttpMethod.Post);
return await GetFromJsonAsync<DifficultyAttributes>($"beatmaps/{id}/attributes", new Dictionary<string, object?>()
{
{ "ruleset", ruleset },
{ "mods", mods }
}, x => x["attributes"], method: HttpMethod.Post);
}
}
15 changes: 14 additions & 1 deletion OsuSharp/OsuApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,18 @@ public async Task EnsureAccessTokenAsync()

try
{
// Fallback to GET if nothing else is provided
method ??= HttpMethod.Get;

// Prepare HTTP request
var message = new HttpRequestMessage(method, method == HttpMethod.Get ? $"{url}?{BuildQueryString(parameters)}" : url);

// Append POST body if required
if (method == HttpMethod.Post)
message.Content = new StringContent(JsonConvert.SerializeObject(parameters, _jsonSettings), System.Text.Encoding.UTF8, "application/json");
minisbett marked this conversation as resolved.
Show resolved Hide resolved

// Send the request and validate the response. If 404 is returned, return null.
HttpResponseMessage response = await _http.SendAsync(new HttpRequestMessage(method ?? HttpMethod.Get, $"{url}?{BuildQueryString(parameters)}"));
HttpResponseMessage response = await _http.SendAsync(message);
if (response.StatusCode == HttpStatusCode.NotFound)
return default;

Expand Down Expand Up @@ -165,6 +175,9 @@ private static string BuildQueryString(Dictionary<string, object?> parameters)
else if (kvp.Value is DateTime dt)
// Use the ISO 8601 format for dates.
str += dt.ToString("o");
else if (kvp.Value is bool b)
// Ensure all bools are passed in lower-case.
str += b.ToString().ToLower();
else
str += HttpUtility.HtmlEncode(kvp.Value!.ToString());
}
Expand Down