package dev.solsynth.snConnect.services import kotlinx.datetime.Instant import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import okhttp3.Request import java.io.IOException @Serializable data class DraslPlayer( @SerialName("userUuid") val userUuid: String, val name: String, val uuid: String, @SerialName("offlineUuid") val offlineUuid: String, @SerialName("fallbackPlayer") val fallbackPlayer: String, @SerialName("skinModel") val skinModel: String, @SerialName("skinUrl") val skinUrl: String?, @SerialName("capeUrl") val capeUrl: String?, @SerialName("createdAt") val createdAt: String, // ISO string @SerialName("nameLastChangedAt") val nameLastChangedAt: String ) @Serializable data class DraslOIDCIdentity( @SerialName("userUuid") val userUuid: String, @SerialName("oidcProviderName") val oidcProviderName: String, val issuer: String, val subject: String ) @Serializable data class DraslUser( @SerialName("isAdmin") val isAdmin: Boolean, @SerialName("isLocked") val isLocked: Boolean, val uuid: String, val username: String, @SerialName("preferredLanguage") val preferredLanguage: String, @SerialName("maxPlayerCount") val maxPlayerCount: Int, val players: List, @SerialName("oidcIdentities") val oidcIdentities: List ) @Serializable data class APILoginRequest( val username: String, val password: String ) @Serializable data class APILoginResponse( val user: DraslUser, val token: String, @SerialName("expires_at") val expiresAt: Instant ) @Serializable data class APIOIDCTokenRequest( @SerialName("provider") val provider: String, val code: String, val state: String ) @Serializable data class APIOIDCTokenResponse( val user: DraslUser, val token: String, @SerialName("expires_at") val expiresAt: Instant ) class AuthUserService(private val sn: AuthService) { private val json = Json { ignoreUnknownKeys = true } private fun addAuthHeader(builder: Request.Builder): Request.Builder { sn.siteSecret?.let { builder.header("Authorization", "Bearer $it") } return builder } fun getUser(id: String): DraslUser { val requestBuilder = Request.Builder() .url(sn.getUrl("/drasl/api/v2/users/$id")) .get() sn.client.newCall(addAuthHeader(requestBuilder).build()).execute().use { response -> if (!response.isSuccessful) throw IOException("Unexpected code $response") val responseBody = response.body!!.string() return json.decodeFromString(responseBody) } } fun getPlayerByUuid(uuid: String): DraslPlayer { val requestBuilder = Request.Builder() .url(sn.getUrl("/drasl/api/v2/players/$uuid")) .get() sn.client.newCall(addAuthHeader(requestBuilder).build()).execute().use { response -> if (!response.isSuccessful) throw IOException("Unexpected code $response") val responseBody = response.body!!.string() return json.decodeFromString(responseBody) } } fun getSnByPlayer(playerUuid: String): String? { return try { val player = getPlayerByUuid(playerUuid) val user = getUser(player.userUuid) user.oidcIdentities.find { it.oidcProviderName == "Solarpass" }?.subject } catch (e: IOException) { null } } }