blob: bea039212c1af55634a1c0b02cbe48d388eb0f17 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.ProfileApiDataLoadedEvent
import at.hannibal2.skyhanni.events.ProfileJoinEvent
import at.hannibal2.skyhanni.utils.APIUtil
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.StringUtils.toDashlessUUID
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.minecraft.client.Minecraft
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.common.gameevent.TickEvent
import java.io.File
import java.util.*
class ApiDataLoader {
private var currentProfileName = ""
private var nextApiCallTime = -1L
private var currentProfileId = ""
@SubscribeEvent
fun onTick(event: TickEvent.ClientTickEvent) {
val thePlayer = Minecraft.getMinecraft().thePlayer ?: return
thePlayer.worldObj ?: return
if (nextApiCallTime != -1L && System.currentTimeMillis() > nextApiCallTime) {
nextApiCallTime = System.currentTimeMillis() + 60_000 * 5
SkyHanniMod.coroutineScope.launch {
val apiKey = SkyHanniMod.feature.hidden.apiKey
val uuid = Minecraft.getMinecraft().thePlayer.uniqueID.toDashlessUUID()
loadProfileData(apiKey, uuid, currentProfileId)
}
}
}
@SubscribeEvent
fun onStatusBar(event: LorenzChatEvent) {
val message = event.message
if (message.startsWith("§aYour new API key is §r§b")) {
SkyHanniMod.feature.hidden.apiKey = message.substring(26)
LorenzUtils.chat("§b[SkyHanni] A new API Key has been detected and installed")
if (currentProfileName != "") {
updateApiData()
}
}
}
@SubscribeEvent
fun onStatusBar(event: ProfileJoinEvent) {
currentProfileName = event.name
updateApiData()
}
private suspend fun tryUpdateProfileDataAndVerifyKey(apiKey: String): Boolean {
val uuid = Minecraft.getMinecraft().thePlayer.uniqueID.toDashlessUUID()
val url = "https://api.hypixel.net/player?key=$apiKey&uuid=$uuid"
val jsonObject = withContext(Dispatchers.IO) { APIUtil.getJSONResponse(url) }
if (jsonObject["success"]?.asBoolean == false) {
if (jsonObject["throttle"]?.asBoolean == true) return true // 429 Too Many Requests does not make an invalid key.
val cause = jsonObject["cause"].asString
if (cause == "Invalid API key") {
return false
} else {
throw RuntimeException("API error for url '$url': $cause")
}
}
val player = jsonObject["player"].asJsonObject
val stats = player["stats"].asJsonObject
val skyBlock = stats["SkyBlock"].asJsonObject
val profiles = skyBlock["profiles"].asJsonObject
for (entry in profiles.entrySet()) {
val asJsonObject = entry.value.asJsonObject
val name = asJsonObject["cute_name"].asString
if (currentProfileName == name.lowercase()) {
currentProfileId = asJsonObject["profile_id"].asString
loadProfileData(apiKey, uuid, currentProfileId)
}
}
return true
}
private fun updateApiData() {
nextApiCallTime = -1
SkyHanniMod.coroutineScope.launch {
val oldApiKey = SkyHanniMod.feature.hidden.apiKey
if (oldApiKey.isNotEmpty() && tryUpdateProfileDataAndVerifyKey(oldApiKey)) {
return@launch
}
findApiCandidatesFromOtherMods().forEach { (modName, newApiKey) ->
if (tryUpdateProfileDataAndVerifyKey(newApiKey)) {
SkyHanniMod.feature.hidden.apiKey = newApiKey
LorenzUtils.chat("§e[SkyHanni] Imported valid new API key from $modName.")
return@launch
} else {
LorenzUtils.error("§c[SkyHanni] Invalid API key from $modName")
}
}
LorenzUtils.error("§c[SkyHanni] SkyHanni has no API key set. Please run /api new")
}
}
private fun findApiCandidatesFromOtherMods(): Map<String, String> {
LorenzUtils.consoleLog("Trying to find the API Key from the config of other mods..")
val candidates = mutableMapOf<String, String>()
for (mod in OtherMod.values()) {
val modName = mod.modName
val file = File(mod.configPath)
if (file.exists()) {
val reader = APIUtil.readFile(file)
try {
val key = mod.readKey(reader).replace("\n", "").replace(" ", "")
UUID.fromString(key)
candidates[modName] = key
} catch (e: Throwable) {
LorenzUtils.consoleLog("- $modName: wrong config format! (" + e.message + ")")
continue
}
} else {
LorenzUtils.consoleLog("- $modName: no config found!")
}
}
return candidates
}
private suspend fun loadProfileData(apiKey: String, playerUuid: String, profileId: String) {
val url = "https://api.hypixel.net/skyblock/profile?key=$apiKey&profile=$profileId"
val jsonObject = withContext(Dispatchers.IO) { APIUtil.getJSONResponse(url) }
val profile = jsonObject["profile"]?.asJsonObject ?: return
val members = profile["members"]?.asJsonObject ?: return
for (entry in members.entrySet()) {
if (entry.key == playerUuid) {
val profileData = entry.value.asJsonObject
ProfileApiDataLoadedEvent(profileData).postAndCatch()
nextApiCallTime = System.currentTimeMillis() + 60_000 * 3
}
}
}
}
|