Add more caching and fix some models
This commit is contained in:
@@ -21,7 +21,7 @@ import moe.nea.firmament.util.json.InstantAsLongSerializer
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class Profiles(
|
data class Profiles(
|
||||||
val success: Boolean,
|
val success: Boolean,
|
||||||
val profiles: List<Profile>
|
val profiles: List<Profile>?
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@@ -120,12 +120,12 @@ data class PlayerResponse(
|
|||||||
data class PlayerData(
|
data class PlayerData(
|
||||||
val uuid: UUID,
|
val uuid: UUID,
|
||||||
val firstLogin: Instant,
|
val firstLogin: Instant,
|
||||||
val lastLogin: Instant,
|
val lastLogin: Instant? = null,
|
||||||
@SerialName("playername")
|
@SerialName("playername")
|
||||||
val playerName: String,
|
val playerName: String,
|
||||||
val achievementsOneTime: List<String> = listOf(),
|
val achievementsOneTime: List<String> = listOf(),
|
||||||
@SerialName("newPackageRank")
|
@SerialName("newPackageRank")
|
||||||
val packageRank: String?,
|
val packageRank: String? = null,
|
||||||
val monthlyPackageRank: String? = null,
|
val monthlyPackageRank: String? = null,
|
||||||
val rankPlusColor: String = "GOLD"
|
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.CottonClientScreen
|
||||||
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
|
import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription
|
||||||
import io.github.cottonmc.cotton.gui.widget.WTabPanel
|
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 java.util.UUID
|
||||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
|
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
import moe.nea.firmament.apis.AshconNameLookup
|
|
||||||
import moe.nea.firmament.apis.Member
|
import moe.nea.firmament.apis.Member
|
||||||
import moe.nea.firmament.apis.PlayerData
|
import moe.nea.firmament.apis.PlayerData
|
||||||
import moe.nea.firmament.apis.PlayerResponse
|
|
||||||
import moe.nea.firmament.apis.Profile
|
import moe.nea.firmament.apis.Profile
|
||||||
import moe.nea.firmament.apis.Profiles
|
import moe.nea.firmament.apis.Routes
|
||||||
import moe.nea.firmament.util.ScreenUtil
|
import moe.nea.firmament.util.ScreenUtil
|
||||||
|
|
||||||
class ProfileViewer(
|
class ProfileViewer(
|
||||||
@@ -48,40 +41,25 @@ class ProfileViewer(
|
|||||||
fun onCommand(source: FabricClientCommandSource, name: String) {
|
fun onCommand(source: FabricClientCommandSource, name: String) {
|
||||||
source.sendFeedback(Text.translatable("firmament.pv.lookingup", name))
|
source.sendFeedback(Text.translatable("firmament.pv.lookingup", name))
|
||||||
Firmament.coroutineScope.launch {
|
Firmament.coroutineScope.launch {
|
||||||
val nameData = Firmament.httpClient.get("https://api.ashcon.app/mojang/v2/user/$name").body<AshconNameLookup>()
|
val uuid = Routes.getUUIDForPlayerName(name)
|
||||||
val names = mapOf(nameData.uuid to nameData.username)
|
if (uuid == null) {
|
||||||
val data = Firmament.httpClient.get {
|
source.sendError(Text.translatable("firmament.pv.noplayer", name))
|
||||||
url {
|
return@launch
|
||||||
protocol = URLProtocol.HTTPS
|
}
|
||||||
host = "api.hypixel.net"
|
val names = mapOf(uuid to (Routes.getPlayerNameForUUID(uuid) ?: name))
|
||||||
path("player")
|
val data = Routes.getAccountData(uuid)
|
||||||
parameter("key", "e721a103-96e0-400f-af2a-73b2a91007b1")
|
if (data == null) {
|
||||||
parameter("uuid", nameData.uuid)
|
source.sendError(Text.translatable("firmament.pv.nohypixel", name))
|
||||||
}
|
return@launch
|
||||||
}.body<PlayerResponse>()
|
}
|
||||||
val accountData = mapOf(data.player.uuid to data.player)
|
val accountData = mapOf(data.uuid to data)
|
||||||
val playerUuid = data.player.uuid
|
val profiles = Routes.getProfiles(uuid)
|
||||||
val profiles = Firmament.httpClient.get {
|
val profile = profiles?.profiles?.find { it.selected }
|
||||||
url {
|
|
||||||
protocol = URLProtocol.HTTPS
|
|
||||||
host = "api.hypixel.net"
|
|
||||||
path("skyblock", "profiles")
|
|
||||||
parameter("key", "e721a103-96e0-400f-af2a-73b2a91007b1")
|
|
||||||
parameter("uuid", playerUuid)
|
|
||||||
}
|
|
||||||
}.body<Profiles>()
|
|
||||||
val profile = profiles.profiles.find { it.selected }
|
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
source.sendFeedback(Text.translatable("firmament.pv.noprofile", name))
|
source.sendFeedback(Text.translatable("firmament.pv.noprofile", name))
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
ScreenUtil.setScreenLater(
|
ScreenUtil.setScreenLater(CottonClientScreen(ProfileViewer(uuid, names, accountData, profile)))
|
||||||
CottonClientScreen(
|
|
||||||
ProfileViewer(
|
|
||||||
playerUuid, names, accountData, profile
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user