diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index 089c611a9ee..ddfd01671e6 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -44,6 +44,7 @@ LongMethod:FontRenderer.kt$FontRenderer$private fun drawInternal( text: String, x0: Float, y0: Float, defaultColor: Color4b, shadow: Boolean, obfuscatedSeed: Long, z: Float, scale: Float ): Float LongMethod:ModuleManager.kt$ModuleManager$fun registerInbuilt() LongMethod:ModuleTrajectories.kt$ModuleTrajectories$private fun drawTrajectoryForProjectile( motion: Vec3d, trajectoryInfo: TrajectoryInfo, pos: Vec3d, player: Entity, interpolatedOffset: Vec3, color: Color4b, matrixStack: MatrixStack ): HitResult? + LongMethod:ProxyRest.kt$internal fun RestNode.proxyRest() LongMethod:SessionRest.kt$private fun RestNode.setupAccountManagerRest() LongMethod:Value.kt$Value$open fun setByString(string: String) LongParameterList:AimPlan.kt$AimPlan$( val rotation: Rotation, smootherMode: SmootherMode, baseTurnSpeed: ClosedFloatingPointRange<Float>, val ticksUntilReset: Int, /** * The reset threshold defines the threshold at which we are going to reset the aim plan. * The threshold is being calculated by the distance between the current rotation and the rotation we want to aim. */ val resetThreshold: Float, /** * Consider if the inventory is open or not. If the inventory is open, we might not want to continue updating. */ val considerInventory: Boolean, val applyVelocityFix: Boolean, val changeLook: Boolean ) diff --git a/src-theme/src/client/api.svelte b/src-theme/src/client/api.svelte index 009ed422ac1..4e7b1952568 100644 --- a/src-theme/src/client/api.svelte +++ b/src-theme/src/client/api.svelte @@ -371,66 +371,126 @@ }) } - /** - * internal fun RestNode.setupProxyRestApi() { - * get("/proxy") { - * val proxyObject = JsonObject() - * - * ProxyManager.currentProxy?.let { - * proxyObject.addProperty("host", it.host) - * proxyObject.addProperty("port", it.port) - * proxyObject.addProperty("username", it.credentials?.username) - * proxyObject.addProperty("password", it.credentials?.password) - * } - * - * httpOk(proxyObject) - * } - * - * post("/proxy") { - * data class ProxyRequest(val host: String, val port: Int, val username: String, val password: String) - * - * val body = decode(it.content) - * - * if (body.host.isBlank()) - * return@post httpForbidden("No host") - * - * if (body.port <= 0) - * return@post httpForbidden("No port") - * - * ProxyManager.setProxy(body.host, body.port, body.username, body.password) - * - * httpOk(JsonObject()) - * } - * - * delete("/proxy") { - * ProxyManager.unsetProxy() - * httpOk(JsonObject()) - * } - * } - */ + // get("/proxy") { + // val proxyObject = JsonObject() + // + // ProxyManager.currentProxy?.let { + // proxyObject.addProperty("host", it.host) + // proxyObject.addProperty("port", it.port) + // proxyObject.addProperty("username", it.credentials?.username) + // proxyObject.addProperty("password", it.credentials?.password) + // } + // + // httpOk(proxyObject) + // } + // + // delete("/proxy") { + // ProxyManager.unsetProxy() + // httpOk(JsonObject()) + // } + // + // get("/proxies") { + // val proxiesArray = JsonArray() + // + // ProxyManager.proxies.forEachIndexed { index, proxy -> + // val proxyObject = JsonObject() + // proxyObject.addProperty("id", index) + // proxyObject.addProperty("host", proxy.host) + // proxyObject.addProperty("port", proxy.port) + // proxyObject.addProperty("username", proxy.credentials?.username) + // proxyObject.addProperty("password", proxy.credentials?.password) + // proxiesArray.add(proxyObject) + // } + // + // httpOk(proxiesArray) + // } + // + // post("/proxies") { + // data class ProxyRequest(val host: String, val port: Int, val username: String, val password: String) + // + // val body = decode(it.content) + // + // if (body.host.isBlank()) { + // return@post httpForbidden("No host") + // } + // + // if (body.port <= 0) { + // return@post httpForbidden("No port") + // } + // + // ProxyManager.addProxy(body.host, body.port, body.username, body.password) + // httpOk(JsonObject()) + // } + // + // delete("/proxies") { + // data class ProxyRequest(val id: Int) + // val body = decode(it.content) + // + // if (body.id < 0 || body.id >= ProxyManager.proxies.size) { + // return@delete httpForbidden("Invalid id") + // } + // + // ProxyManager.removeProxy(body.id) + // httpOk(JsonObject()) + // } + // + // put("/proxies") { + // data class ProxyRequest(val id: Int) + // val body = decode(it.content) + // + // if (body.id < 0 || body.id >= ProxyManager.proxies.size) { + // return@put httpForbidden("Invalid id") + // } + // + // ProxyManager.setProxy(body.id) + // httpOk(JsonObject()) + // } export function getProxy() { return request("/proxy") } - export function setProxy(host, port, username, password) { + export function unsetProxy() { return request("/proxy", { + method: "DELETE", + headers: { + "Content-Type": "application/json" + } + }) + } + + export function getProxies() { + return request("/proxies") + } + + export function addProxy(proxy) { + return request("/proxies", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ "host": host, "port": port, "username": username, "password": password }) + body: JSON.stringify({ "host": proxy.host, "port": proxy.port, "username": proxy.username, "password": proxy.password }) }) } - export function unsetProxy() { - return request("/proxy", { + export function removeProxy(id) { + return request("/proxies", { method: "DELETE", headers: { "Content-Type": "application/json" - } + }, + body: JSON.stringify({ "id": id }) }) } + export function setProxy(id) { + return request("/proxies", { + method: "PUT", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ "id": id }) + }) + } export function getPersistentStorage(key) { const searchParams = new URLSearchParams({ key }) diff --git a/src-theme/src/routes/proxymanager/ProxyManager.svelte b/src-theme/src/routes/proxymanager/ProxyManager.svelte index 80a452b032f..51de75b3238 100644 --- a/src-theme/src/routes/proxymanager/ProxyManager.svelte +++ b/src-theme/src/routes/proxymanager/ProxyManager.svelte @@ -1,233 +1,214 @@ - - - Proxy Manager - - - -
-
-

Proxy Manager

- -
-
-

Proxy Configuration

-
-
-
-
- - -

- - - - -
-
- - -
- -
-

Proxy Details

- -
- -
+ + +
+

Proxy Manager

+

+ ProxyManager only supports SOCKS5 proxies.
+ This is a prototype design for testing purposes and is NOT the final design. +

+ +
+

Proxies

+ + + + + + + + + + + + {#each proxies as proxy (proxy.id)} + + + + {#if proxy.username.length > 0} + + {:else} + + {/if} + + + + {/each} +
HostPortAuthActions
None
{proxy.host}{proxy.port}🔒🔓 + + +
-
-
- -
-
-
- - + +
+

Add New Proxy

+
+ + + + + +
+
+ +
+

Current Proxy

+

{currentProxy ? currentProxy : 'No active proxy'}

+

Location: {currentLocation}

+
+ + + diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/features/misc/ProxyManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/features/misc/ProxyManager.kt index 49c6e3ecc90..0c0d79499be 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/features/misc/ProxyManager.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/features/misc/ProxyManager.kt @@ -23,10 +23,12 @@ import io.netty.handler.proxy.Socks5ProxyHandler import net.ccbluex.liquidbounce.api.IpInfoApi import net.ccbluex.liquidbounce.config.ConfigSystem import net.ccbluex.liquidbounce.config.Configurable +import net.ccbluex.liquidbounce.config.ListValueType import net.ccbluex.liquidbounce.event.Listenable import net.ccbluex.liquidbounce.event.events.PipelineEvent import net.ccbluex.liquidbounce.event.handler -import net.ccbluex.liquidbounce.script.ScriptApi +import net.ccbluex.liquidbounce.features.misc.ProxyManager.Proxy.Companion.NO_PROXY +import net.ccbluex.liquidbounce.features.misc.ProxyManager.ProxyCredentials.Companion.credentialsFromUserInput import java.net.InetSocketAddress /** @@ -36,15 +38,12 @@ import java.net.InetSocketAddress */ object ProxyManager : Configurable("proxy"), Listenable { - private val noProxy = Proxy("", 0, null) - var proxy by value("proxy", noProxy) + var proxy by value("proxy", NO_PROXY) + val proxies by value(name, mutableListOf(), listType = ListValueType.Proxy) /** * The proxy that is set in the current session and used for all server connections - * - * !! DO NOT CHANGE IT TO PRIVATE AS IT IS USED BY THE ULTRALIGHT GUI. !! */ - @ScriptApi val currentProxy get() = proxy.takeIf { it.host.isNotBlank() } @@ -52,24 +51,28 @@ object ProxyManager : Configurable("proxy"), Listenable { ConfigSystem.root(this) } - fun setProxy(host: String, port: Int, username: String, password: String) { - proxy = Proxy(host, port, - if (username.isNotBlank()) - ProxyCredentials(username, password) - else - null - ) + fun addProxy(host: String, port: Int, username: String = "", password: String = "") { + proxies.add(Proxy(host, port, credentialsFromUserInput(username, password))) ConfigSystem.storeConfigurable(this) + } - // Refreshes local IP info when proxy is set - IpInfoApi.refreshLocalIpInfo() + fun removeProxy(index: Int) { + proxies.removeAt(index) + ConfigSystem.storeConfigurable(this) + } + + fun setProxy(index: Int) { + proxy = proxies[index] + sync() } fun unsetProxy() { - proxy = noProxy - ConfigSystem.storeConfigurable(this) + proxy = NO_PROXY + sync() + } - // Refreshes local IP info when proxy is unset + private fun sync() { + ConfigSystem.storeConfigurable(this) IpInfoApi.refreshLocalIpInfo() } @@ -103,11 +106,24 @@ object ProxyManager : Configurable("proxy"), Listenable { data class Proxy(val host: String, val port: Int, val credentials: ProxyCredentials?) { val address get() = InetSocketAddress(host, port) + + companion object { + val NO_PROXY = Proxy("", 0, null) + } + } /** * Contains serializable proxy credentials */ - data class ProxyCredentials(val username: String, val password: String) + data class ProxyCredentials(val username: String, val password: String) { + companion object { + fun credentialsFromUserInput(username: String, password: String) = + if (username.isNotBlank() && password.isNotBlank()) + ProxyCredentials(username, password) + else + null + } + } } diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/web/socket/protocol/rest/client/ProxyRest.kt b/src/main/kotlin/net/ccbluex/liquidbounce/web/socket/protocol/rest/client/ProxyRest.kt index a617d297809..d4e1e888b17 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/web/socket/protocol/rest/client/ProxyRest.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/web/socket/protocol/rest/client/ProxyRest.kt @@ -19,6 +19,7 @@ */ package net.ccbluex.liquidbounce.web.socket.protocol.rest.client +import com.google.gson.JsonArray import com.google.gson.JsonObject import net.ccbluex.liquidbounce.config.util.decode import net.ccbluex.liquidbounce.features.misc.ProxyManager @@ -28,15 +29,13 @@ import net.ccbluex.liquidbounce.web.socket.netty.rest.RestNode /** * Proxy endpoints - * - * TODO: These need to be reworked since we are going to use a proxy pool in the future - * similar to the account pool */ internal fun RestNode.proxyRest() { get("/proxy") { val proxyObject = JsonObject() ProxyManager.currentProxy?.let { + proxyObject.addProperty("id", ProxyManager.proxies.indexOf(it)) proxyObject.addProperty("host", it.host) proxyObject.addProperty("port", it.port) proxyObject.addProperty("username", it.credentials?.username) @@ -46,24 +45,66 @@ internal fun RestNode.proxyRest() { httpOk(proxyObject) } - post("/proxy") { + delete("/proxy") { + ProxyManager.unsetProxy() + httpOk(JsonObject()) + } + + get("/proxies") { + val proxiesArray = JsonArray() + + ProxyManager.proxies.forEachIndexed { index, proxy -> + val proxyObject = JsonObject() + proxyObject.addProperty("id", index) + proxyObject.addProperty("host", proxy.host) + proxyObject.addProperty("port", proxy.port) + proxyObject.addProperty("username", proxy.credentials?.username) + proxyObject.addProperty("password", proxy.credentials?.password) + proxiesArray.add(proxyObject) + } + + httpOk(proxiesArray) + } + + post("/proxies") { data class ProxyRequest(val host: String, val port: Int, val username: String, val password: String) val body = decode(it.content) - if (body.host.isBlank()) + if (body.host.isBlank()) { return@post httpForbidden("No host") + } - if (body.port <= 0) + if (body.port <= 0) { return@post httpForbidden("No port") + } - ProxyManager.setProxy(body.host, body.port, body.username, body.password) + ProxyManager.addProxy(body.host, body.port, body.username, body.password) + httpOk(JsonObject()) + } + + delete("/proxies") { + data class ProxyRequest(val id: Int) + val body = decode(it.content) + if (body.id < 0 || body.id >= ProxyManager.proxies.size) { + return@delete httpForbidden("Invalid id") + } + + ProxyManager.removeProxy(body.id) httpOk(JsonObject()) } - delete("/proxy") { - ProxyManager.unsetProxy() + put("/proxies") { + data class ProxyRequest(val id: Int) + val body = decode(it.content) + + if (body.id < 0 || body.id >= ProxyManager.proxies.size) { + return@put httpForbidden("Invalid id") + } + + ProxyManager.setProxy(body.id) httpOk(JsonObject()) } + }