blob: c77210ce6ed9cc62140df3cfb30f5e9c954f5ef6 (
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
147
148
149
150
151
152
153
154
|
package at.hannibal2.skyhanni.data
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.LorenzTickEvent
import at.hannibal2.skyhanni.events.ProfileApiDataLoadedEvent
import at.hannibal2.skyhanni.events.ProfileJoinEvent
import at.hannibal2.skyhanni.events.RepositoryReloadEvent
import at.hannibal2.skyhanni.utils.APIUtil
import at.hannibal2.skyhanni.utils.LorenzUtils
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 java.io.File
import java.util.*
class ApiDataLoader {
private var currentProfileName = ""
private var currentProfileId = ""
private var usePlayerApiKey = false
@SubscribeEvent
fun onRepositoryReload(event: RepositoryReloadEvent) {
usePlayerApiKey = false
event.getConstant("DisabledFeatures")?.let {
if (it.asJsonObject["user_api_keys"]?.asBoolean == true) {
usePlayerApiKey = true
}
}
}
@SubscribeEvent
fun onTick(event: LorenzTickEvent) {
val thePlayer = Minecraft.getMinecraft().thePlayer ?: return
thePlayer.worldObj ?: return
if (!usePlayerApiKey) return
if (nextApiCallTime != -1L && System.currentTimeMillis() > nextApiCallTime) {
nextApiCallTime = System.currentTimeMillis() + 60_000 * 5
SkyHanniMod.coroutineScope.launch {
val apiKey = SkyHanniMod.feature.storage.apiKey
val uuid = LorenzUtils.getPlayerUuid()
loadProfileData(apiKey, uuid, currentProfileId)
}
}
}
@SubscribeEvent
fun onProfileJoin(event: ProfileJoinEvent) {
currentProfileName = event.name
if (!usePlayerApiKey) return
updateApiData()
}
private suspend fun tryUpdateProfileDataAndVerifyKey(apiKey: String): Boolean {
val uuid = LorenzUtils.getPlayerUuid()
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 doesn't 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.storage.apiKey
if (oldApiKey.isNotEmpty() && tryUpdateProfileDataAndVerifyKey(oldApiKey)) {
return@launch
}
findApiCandidatesFromOtherMods().forEach { (modName, newApiKey) ->
if (tryUpdateProfileDataAndVerifyKey(newApiKey)) {
SkyHanniMod.feature.storage.apiKey = newApiKey
LorenzUtils.chat("§e[SkyHanni] Imported valid API key from $modName.")
return@launch
}
}
}
}
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.entries) {
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(" ", "")
if (key == "") {
LorenzUtils.consoleLog("- $modName: no api key set!")
continue
}
UUID.fromString(key)
candidates[modName] = key
} catch (e: Throwable) {
LorenzUtils.consoleLog("- $modName: wrong config format! (" + e.message + ")")
continue
}
} else {
LorenzUtils.consoleLog("- $modName: no mod/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
}
}
}
companion object {
private var nextApiCallTime = -1L
fun command(args: Array<String>) {
SkyHanniMod.feature.storage.apiKey = args[0]
LorenzUtils.chat("§e[SkyHanni] Api key set via command!")
nextApiCallTime = -1
}
}
}
|