diff --git a/src/main/kotlin/one/devos/osuv2kt/Osu.kt b/src/main/kotlin/one/devos/osuv2kt/Osu.kt index f785762..0206264 100644 --- a/src/main/kotlin/one/devos/osuv2kt/Osu.kt +++ b/src/main/kotlin/one/devos/osuv2kt/Osu.kt @@ -7,12 +7,13 @@ import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import one.devos.osuv2kt.dsl.BeatmapQuery -import one.devos.osuv2kt.dsl.BeatmapQueryBuilder import one.devos.osuv2kt.dsl.OsuUserQuery +import one.devos.osuv2kt.dsl.BeatmapUserScoreQuery import one.devos.osuv2kt.models.RankStatus import one.devos.osuv2kt.models.Scope import one.devos.osuv2kt.models.beatmap.Beatmap import one.devos.osuv2kt.models.beatmap.BeatmapDifficultyAttributes +import one.devos.osuv2kt.models.beatmap.BeatmapUserScore import one.devos.osuv2kt.models.oauth2.TokenResponse import one.devos.osuv2kt.models.user.User import one.devos.osuv2kt.utils.BeatmapDifficultyAttributesDeserializer @@ -153,4 +154,30 @@ public class Osu( } } } + + public fun queryBeatmapUserScore(block: BeatmapUserScoreQuery.() -> Unit): BeatmapUserScore { + val query = BeatmapUserScoreQuery() + .apply(block) + .validateExceptionally() + + val request = Request.Builder() + .url("${BASE_URL}/beatmaps/${query.beatmap}/scores/users/${query.user}?mode=${query.mode?.value}") + .header("Authorization", "Bearer ${token?.accessToken}") + .build() + + val response = client.newCall(request).execute() + return response.use { response -> + if (!response.isSuccessful) { + throw IllegalStateException("Unexpected code $response") + } + + val body = response.body?.string() + + try { + gson.fromJson(body, BeatmapUserScore::class.java) + } catch (t: Throwable) { + throw IllegalStateException("Failed to parse beatmap user score: ${gson.toJson(body)}", t) + } + } + } } diff --git a/src/main/kotlin/one/devos/osuv2kt/dsl/BeatmapUserScoreQuery.kt b/src/main/kotlin/one/devos/osuv2kt/dsl/BeatmapUserScoreQuery.kt new file mode 100644 index 0000000..927c0f3 --- /dev/null +++ b/src/main/kotlin/one/devos/osuv2kt/dsl/BeatmapUserScoreQuery.kt @@ -0,0 +1,27 @@ +package one.devos.osuv2kt.dsl + +import one.devos.osuv2kt.models.Ruleset + +public class BeatmapUserScoreQuery { + + public var beatmap: Int? = null + + public var user: Int? = null + + public var mode: Ruleset? = null + + public fun validateExceptionally(): BeatmapUserScoreQuery = apply { + if (beatmap == null) { + throw IllegalArgumentException("Beatmap must be set") + } + + if (user == null) { + throw IllegalArgumentException("User must be set") + } + + if (mode == null) { + throw IllegalArgumentException("Mode must be set") + } + } + +} diff --git a/src/main/kotlin/one/devos/osuv2kt/models/score/Score.kt b/src/main/kotlin/one/devos/osuv2kt/models/score/Score.kt index 9b3ce21..8937474 100644 --- a/src/main/kotlin/one/devos/osuv2kt/models/score/Score.kt +++ b/src/main/kotlin/one/devos/osuv2kt/models/score/Score.kt @@ -1,5 +1,6 @@ package one.devos.osuv2kt.models.score +import com.google.gson.JsonElement import java.time.OffsetDateTime public data class Score( @@ -10,7 +11,7 @@ public data class Score( public val classicTotalScore: Int, // only for solo_score type public val endedAt: OffsetDateTime, public val hasReplay: Boolean, - public val id: Int, + public val id: Long, public val isPerfectCombo: Boolean, public val legacyPerfect: Boolean, public val legacyScoreId: Int?, @@ -35,7 +36,7 @@ public data class Score( public val beatmap: Any?, public val beatmapset: Any?, - public val currentUserAttributes: Int?, + public val currentUserAttributes: JsonElement?, public val match: Any?, // only for legacy match score public val position: Int?, public val rankCountry: Any?, diff --git a/src/test/kotlin/one/devos/osuv2kt/tests/QueryTests.kt b/src/test/kotlin/one/devos/osuv2kt/tests/QueryTests.kt index f073667..c968b67 100644 --- a/src/test/kotlin/one/devos/osuv2kt/tests/QueryTests.kt +++ b/src/test/kotlin/one/devos/osuv2kt/tests/QueryTests.kt @@ -31,19 +31,28 @@ class QueryTests { startOAuthServer { // Query user val testUser = osu.queryUser { - user = "@asojidev" - mode = Ruleset.STANDARD + this.user = "@asojidev" + this.mode = Ruleset.STANDARD } println("User: $testUser") // Query beatmap val beatmap = osu.queryBeatmap { - value = "1657912" - type = BeatmapQuery.QueryType.ID + this.value = "1657912" + this.type = BeatmapQuery.QueryType.ID } println("Beatmap: $beatmap") + + // Query beatmap user score + val beatmapScore = osu.queryBeatmapUserScore { + this.user = 3178418 + this.beatmap = 870839 + this.mode = Ruleset.STANDARD + } + + println("Beatmap user score: $beatmapScore") } }