Skip to content

Commit

Permalink
refactor(legacy): add lock to SettingsCommand (#4969)
Browse files Browse the repository at this point in the history
Prevent users from repeatedly loading configurations
  • Loading branch information
MukjepScarlet authored Dec 19, 2024
1 parent 6298b58 commit 19d59ed
Showing 1 changed file with 89 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
*/
package net.ccbluex.liquidbounce.features.command.commands

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import net.ccbluex.liquidbounce.LiquidBounce
import net.ccbluex.liquidbounce.api.ClientApi
import net.ccbluex.liquidbounce.api.Status
Expand All @@ -20,12 +19,15 @@ import net.ccbluex.liquidbounce.ui.client.hud.HUD.addNotification
import net.ccbluex.liquidbounce.ui.client.hud.element.elements.Notification
import net.ccbluex.liquidbounce.utils.client.ClientUtils.LOGGER
import net.ccbluex.liquidbounce.utils.io.HttpUtils.get
import net.ccbluex.liquidbounce.utils.kotlin.SharedScopes
import net.ccbluex.liquidbounce.utils.kotlin.StringUtils
import java.awt.Toolkit
import java.awt.datatransfer.StringSelection

object SettingsCommand : Command("autosettings", "autosetting", "settings", "setting", "config") {

private val mutex = Mutex()

/**
* Execute commands with provided [args]
*/
Expand All @@ -37,121 +39,120 @@ object SettingsCommand : Command("autosettings", "autosetting", "settings", "set
return
}

GlobalScope.launch {
when (args[1].lowercase()) {
"load" -> loadSettings(args)
"report" -> reportSettings(args)
"upload" -> uploadSettings(args)
"list" -> listSettings()
else -> chatSyntax("$usedAlias <load/list/upload/report>")
if (mutex.isLocked) {
chat("§cPrevious task is not finished!")
return
}

SharedScopes.IO.launch {
mutex.withLock {
when (args[1].lowercase()) {
"load" -> loadSettings(args)
"report" -> reportSettings(args)
"upload" -> uploadSettings(args)
"list" -> listSettings()
else -> chatSyntax("$usedAlias <load/list/upload/report>")
}
}
}
}

// Load subcommand
private suspend fun loadSettings(args: Array<String>) {
withContext(Dispatchers.IO) {
if (args.size < 3) {
chatSyntax("${args[0].lowercase()} load <name/url>")
return@withContext
}

try {
val settings = if (args[2].startsWith("http")) {
val (text, code) = get(args[2])
if (code != 200) {
error(text)
}
private fun loadSettings(args: Array<String>) {
if (args.size < 3) {
chatSyntax("${args[0].lowercase()} load <name/url>")
return
}

text
} else {
ClientApi.requestSettingsScript(args[2])
try {
val settings = if (args[2].startsWith("http")) {
val (text, code) = get(args[2])
if (code != 200) {
error(text)
}

chat("Applying settings...")
SettingsUtils.applyScript(settings)
chat("§6Settings applied successfully")
addNotification(Notification("Updated Settings"))
playEdit()
} catch (e: Exception) {
LOGGER.error("Failed to load settings", e)
chat("Failed to load settings: ${e.message}")
text
} else {
ClientApi.requestSettingsScript(args[2])
}

chat("Applying settings...")
SettingsUtils.applyScript(settings)
chat("§6Settings applied successfully")
addNotification(Notification("Updated Settings"))
playEdit()
} catch (e: Exception) {
LOGGER.error("Failed to load settings", e)
chat("Failed to load settings: ${e.message}")
}
}

// Report subcommand
private suspend fun reportSettings(args: Array<String>) {
withContext(Dispatchers.IO) {
if (args.size < 3) {
chatSyntax("${args[0].lowercase()} report <name>")
return@withContext
}
private fun reportSettings(args: Array<String>) {
if (args.size < 3) {
chatSyntax("${args[0].lowercase()} report <name>")
return
}

try {
val response = ClientApi.reportSettings(args[2])
when (response.status) {
Status.SUCCESS -> chat("§6${response.message}")
Status.ERROR -> chat("§c${response.message}")
}
} catch (e: Exception) {
LOGGER.error("Failed to report settings", e)
chat("Failed to report settings: ${e.message}")
try {
val response = ClientApi.reportSettings(args[2])
when (response.status) {
Status.SUCCESS -> chat("§6${response.message}")
Status.ERROR -> chat("§c${response.message}")
}
} catch (e: Exception) {
LOGGER.error("Failed to report settings", e)
chat("Failed to report settings: ${e.message}")
}
}

// Upload subcommand
private suspend fun uploadSettings(args: Array<String>) {
withContext(Dispatchers.IO) {
val option = if (args.size > 3) StringUtils.toCompleteString(args, 3).lowercase() else "all"
val all = "all" in option
val values = all || "values" in option
val binds = all || "binds" in option
val states = all || "states" in option

if (!values && !binds && !states) {
chatSyntax("${args[0].lowercase()} upload [all/values/binds/states]...")
return@withContext
}

try {
chat("§9Creating settings...")
val settingsScript = SettingsUtils.generateScript(values, binds, states)
chat("§9Uploading settings...")
private fun uploadSettings(args: Array<String>) {
val option = if (args.size > 3) StringUtils.toCompleteString(args, 3).lowercase() else "all"
val all = "all" in option
val values = all || "values" in option
val binds = all || "binds" in option
val states = all || "states" in option

if (!values && !binds && !states) {
chatSyntax("${args[0].lowercase()} upload [all/values/binds/states]...")
return
}

val serverData = mc.currentServerData ?: error("You need to be on a server to upload settings.")
try {
chat("§9Creating settings...")
val settingsScript = SettingsUtils.generateScript(values, binds, states)
chat("§9Uploading settings...")

val name = "${LiquidBounce.clientCommit}-${serverData.serverIP.replace(".", "_")}"
val response = ClientApi.uploadSettings(name, mc.session.username, settingsScript)
val serverData = mc.currentServerData ?: error("You need to be on a server to upload settings.")

when (response.status) {
Status.SUCCESS -> {
chat("§6${response.message}")
chat("§9Token: §6${response.token}")
val name = "${LiquidBounce.clientCommit}-${serverData.serverIP.replace(".", "_")}"
val response = ClientApi.uploadSettings(name, mc.session.username, settingsScript)

// Store token in clipboard
val stringSelection = StringSelection(response.token)
Toolkit.getDefaultToolkit().systemClipboard.setContents(stringSelection, stringSelection)
}
when (response.status) {
Status.SUCCESS -> {
chat("§6${response.message}")
chat("§9Token: §6${response.token}")

Status.ERROR -> chat("§c${response.message}")
// Store token in clipboard
val stringSelection = StringSelection(response.token)
Toolkit.getDefaultToolkit().systemClipboard.setContents(stringSelection, stringSelection)
}
} catch (e: Exception) {
LOGGER.error("Failed to upload settings", e)
chat("Failed to upload settings: ${e.message}")

Status.ERROR -> chat("§c${response.message}")
}
} catch (e: Exception) {
LOGGER.error("Failed to upload settings", e)
chat("Failed to upload settings: ${e.message}")
}
}

// List subcommand
private suspend fun listSettings() {
withContext(Dispatchers.IO) {
chat("Loading settings...")
loadSettings(false) {
for (setting in it) {
chat("> ${setting.settingId} (Last updated: ${setting.date}, Status: ${setting.statusType.displayName})")
}
private fun listSettings() {
chat("Loading settings...")
loadSettings(false) {
for (setting in it) {
chat("> ${setting.settingId} (Last updated: ${setting.date}, Status: ${setting.statusType.displayName})")
}
}
}
Expand Down

0 comments on commit 19d59ed

Please sign in to comment.