Add more caching and fix some models
This commit is contained in:
@@ -21,7 +21,7 @@ import moe.nea.firmament.util.json.InstantAsLongSerializer
|
||||
@Serializable
|
||||
data class Profiles(
|
||||
val success: Boolean,
|
||||
val profiles: List<Profile>
|
||||
val profiles: List<Profile>?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
@@ -120,12 +120,12 @@ data class PlayerResponse(
|
||||
data class PlayerData(
|
||||
val uuid: UUID,
|
||||
val firstLogin: Instant,
|
||||
val lastLogin: Instant,
|
||||
val lastLogin: Instant? = null,
|
||||
@SerialName("playername")
|
||||
val playerName: String,
|
||||
val achievementsOneTime: List<String> = listOf(),
|
||||
@SerialName("newPackageRank")
|
||||
val packageRank: String?,
|
||||
val packageRank: String? = null,
|
||||
val monthlyPackageRank: String? = null,
|
||||
val rankPlusColor: String = "GOLD"
|
||||
) {
|
||||
|
||||
109
src/main/kotlin/moe/nea/firmament/apis/Routes.kt
Normal file
109
src/main/kotlin/moe/nea/firmament/apis/Routes.kt
Normal file
@@ -0,0 +1,109 @@
|
||||
package moe.nea.firmament.apis
|
||||
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.http.URLProtocol
|
||||
import io.ktor.http.isSuccess
|
||||
import io.ktor.http.path
|
||||
import io.ktor.util.CaseInsensitiveMap
|
||||
import java.util.UUID
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.util.MinecraftDispatcher
|
||||
|
||||
object Routes {
|
||||
val apiKey = "e721a103-96e0-400f-af2a-73b2a91007b1"
|
||||
private val nameToUUID: MutableMap<String, Deferred<UUID?>> = CaseInsensitiveMap()
|
||||
private val profiles: MutableMap<UUID, Deferred<Profiles?>> = mutableMapOf()
|
||||
private val accounts: MutableMap<UUID, Deferred<PlayerData?>> = mutableMapOf()
|
||||
private val UUIDToName: MutableMap<UUID, Deferred<String?>> = mutableMapOf()
|
||||
|
||||
suspend fun getPlayerNameForUUID(uuid: UUID): String? {
|
||||
return withContext(MinecraftDispatcher) {
|
||||
UUIDToName.computeIfAbsent(uuid) {
|
||||
async(Firmament.coroutineScope.coroutineContext) {
|
||||
val response = Firmament.httpClient.get("https://api.ashcon.app/mojang/v2/user/$uuid")
|
||||
if (!response.status.isSuccess()) return@async null
|
||||
val data = response.body<AshconNameLookup>()
|
||||
launch(MinecraftDispatcher) {
|
||||
nameToUUID[data.username] = async { data.uuid }
|
||||
}
|
||||
data.username
|
||||
}
|
||||
}
|
||||
}.await()
|
||||
}
|
||||
|
||||
suspend fun getUUIDForPlayerName(name: String): UUID? {
|
||||
return withContext(MinecraftDispatcher) {
|
||||
nameToUUID.computeIfAbsent(name) {
|
||||
async(Firmament.coroutineScope.coroutineContext) {
|
||||
val response = Firmament.httpClient.get("https://api.ashcon.app/mojang/v2/user/$name")
|
||||
if (!response.status.isSuccess()) return@async null
|
||||
val data = response.body<AshconNameLookup>()
|
||||
launch(MinecraftDispatcher) {
|
||||
UUIDToName[data.uuid] = async { data.username }
|
||||
}
|
||||
data.uuid
|
||||
}
|
||||
}
|
||||
}.await()
|
||||
}
|
||||
|
||||
suspend fun getAccountData(uuid: UUID): PlayerData? {
|
||||
return withContext(MinecraftDispatcher) {
|
||||
accounts.computeIfAbsent(uuid) {
|
||||
async(Firmament.coroutineScope.coroutineContext) {
|
||||
val response = Firmament.httpClient.get {
|
||||
url {
|
||||
protocol = URLProtocol.HTTPS
|
||||
host = "api.hypixel.net"
|
||||
path("player")
|
||||
parameter("key", apiKey)
|
||||
parameter("uuid", uuid)
|
||||
}
|
||||
}
|
||||
if (!response.status.isSuccess()) {
|
||||
launch(MinecraftDispatcher) {
|
||||
@Suppress("DeferredResultUnused")
|
||||
accounts.remove(uuid)
|
||||
}
|
||||
return@async null
|
||||
}
|
||||
response.body<PlayerResponse>().player
|
||||
}
|
||||
}
|
||||
}.await()
|
||||
}
|
||||
|
||||
suspend fun getProfiles(uuid: UUID): Profiles? {
|
||||
return withContext(MinecraftDispatcher) {
|
||||
profiles.computeIfAbsent(uuid) {
|
||||
async(Firmament.coroutineScope.coroutineContext) {
|
||||
val response = Firmament.httpClient.get {
|
||||
url {
|
||||
protocol = URLProtocol.HTTPS
|
||||
host = "api.hypixel.net"
|
||||
path("skyblock", "profiles")
|
||||
parameter("key", apiKey)
|
||||
parameter("uuid", uuid)
|
||||
}
|
||||
}
|
||||
if (!response.status.isSuccess()) {
|
||||
launch(MinecraftDispatcher) {
|
||||
@Suppress("DeferredResultUnused")
|
||||
profiles.remove(uuid)
|
||||
}
|
||||
return@async null
|
||||
}
|
||||
response.body<Profiles>()
|
||||
}
|
||||
}
|
||||
}.await()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,22 +3,15 @@ package moe.nea.firmament.gui.profileviewer
|
||||
import io.github.cottonmc.cotton.gui.client.CottonClientScreen
|
||||
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
|
||||
import io.github.cottonmc.cotton.gui.widget.WTabPanel
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.http.URLProtocol
|
||||
import io.ktor.http.path
|
||||
import java.util.UUID
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
|
||||
import kotlinx.coroutines.launch
|
||||
import net.minecraft.text.Text
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.apis.AshconNameLookup
|
||||
import moe.nea.firmament.apis.Member
|
||||
import moe.nea.firmament.apis.PlayerData
|
||||
import moe.nea.firmament.apis.PlayerResponse
|
||||
import moe.nea.firmament.apis.Profile
|
||||
import moe.nea.firmament.apis.Profiles
|
||||
import moe.nea.firmament.apis.Routes
|
||||
import moe.nea.firmament.util.ScreenUtil
|
||||
|
||||
class ProfileViewer(
|
||||
@@ -48,40 +41,25 @@ class ProfileViewer(
|
||||
fun onCommand(source: FabricClientCommandSource, name: String) {
|
||||
source.sendFeedback(Text.translatable("firmament.pv.lookingup", name))
|
||||
Firmament.coroutineScope.launch {
|
||||
val nameData = Firmament.httpClient.get("https://api.ashcon.app/mojang/v2/user/$name").body<AshconNameLookup>()
|
||||
val names = mapOf(nameData.uuid to nameData.username)
|
||||
val data = Firmament.httpClient.get {
|
||||
url {
|
||||
protocol = URLProtocol.HTTPS
|
||||
host = "api.hypixel.net"
|
||||
path("player")
|
||||
parameter("key", "e721a103-96e0-400f-af2a-73b2a91007b1")
|
||||
parameter("uuid", nameData.uuid)
|
||||
val uuid = Routes.getUUIDForPlayerName(name)
|
||||
if (uuid == null) {
|
||||
source.sendError(Text.translatable("firmament.pv.noplayer", name))
|
||||
return@launch
|
||||
}
|
||||
}.body<PlayerResponse>()
|
||||
val accountData = mapOf(data.player.uuid to data.player)
|
||||
val playerUuid = data.player.uuid
|
||||
val profiles = Firmament.httpClient.get {
|
||||
url {
|
||||
protocol = URLProtocol.HTTPS
|
||||
host = "api.hypixel.net"
|
||||
path("skyblock", "profiles")
|
||||
parameter("key", "e721a103-96e0-400f-af2a-73b2a91007b1")
|
||||
parameter("uuid", playerUuid)
|
||||
val names = mapOf(uuid to (Routes.getPlayerNameForUUID(uuid) ?: name))
|
||||
val data = Routes.getAccountData(uuid)
|
||||
if (data == null) {
|
||||
source.sendError(Text.translatable("firmament.pv.nohypixel", name))
|
||||
return@launch
|
||||
}
|
||||
}.body<Profiles>()
|
||||
val profile = profiles.profiles.find { it.selected }
|
||||
val accountData = mapOf(data.uuid to data)
|
||||
val profiles = Routes.getProfiles(uuid)
|
||||
val profile = profiles?.profiles?.find { it.selected }
|
||||
if (profile == null) {
|
||||
source.sendFeedback(Text.translatable("firmament.pv.noprofile", name))
|
||||
return@launch
|
||||
}
|
||||
ScreenUtil.setScreenLater(
|
||||
CottonClientScreen(
|
||||
ProfileViewer(
|
||||
playerUuid, names, accountData, profile
|
||||
)
|
||||
)
|
||||
)
|
||||
ScreenUtil.setScreenLater(CottonClientScreen(ProfileViewer(uuid, names, accountData, profile)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user