aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/moe/nea/firmament')
-rw-r--r--src/main/kotlin/moe/nea/firmament/apis/Profiles.kt6
-rw-r--r--src/main/kotlin/moe/nea/firmament/apis/Routes.kt109
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/profileviewer/ProfileViewer.kt54
3 files changed, 128 insertions, 41 deletions
diff --git a/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt b/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
index 4fd5704..7132147 100644
--- a/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
+++ b/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
@@ -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"
) {
diff --git a/src/main/kotlin/moe/nea/firmament/apis/Routes.kt b/src/main/kotlin/moe/nea/firmament/apis/Routes.kt
new file mode 100644
index 0000000..7785d90
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/apis/Routes.kt
@@ -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()
+ }
+
+}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/profileviewer/ProfileViewer.kt b/src/main/kotlin/moe/nea/firmament/gui/profileviewer/ProfileViewer.kt
index 63cb5a8..98e9489 100644
--- a/src/main/kotlin/moe/nea/firmament/gui/profileviewer/ProfileViewer.kt
+++ b/src/main/kotlin/moe/nea/firmament/gui/profileviewer/ProfileViewer.kt
@@ -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)
- }
- }.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)
- }
- }.body<Profiles>()
- val profile = profiles.profiles.find { it.selected }
+ val uuid = Routes.getUUIDForPlayerName(name)
+ if (uuid == null) {
+ source.sendError(Text.translatable("firmament.pv.noplayer", name))
+ return@launch
+ }
+ 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
+ }
+ 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)))
}
}
}