Skip to content

Commit

Permalink
switched to https connection, improved disableProxySecurity function,…
Browse files Browse the repository at this point in the history
… merged simple and advanced validators
  • Loading branch information
SpoilerRules committed Mar 23, 2024
1 parent 4d9a376 commit 6181fab
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 303 deletions.
5 changes: 2 additions & 3 deletions config/detekt/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
<ID>MaxLineLength:ElementValue.kt$ElementValue$"-fx-background-color: ${ColorPalette.controlColor}; -fx-text-fill: ${ColorPalette.textColor}; -fx-font-family: '${ResourceHandler.comfortaaSemiBold.family}'; -fx-font-size: 15; -fx-background-radius: 12;"</ID>
<ID>MaxLineLength:GeneratorBean.kt$GeneratorBean$"Nitro generation was skipped because ${CEnum.UNDERLINE}the Proxy File path was empty${CEnum.RESET}, even though Custom Proxy mode was set to 'One File' and enabled. Please check your proxy settings."</ID>
<ID>MaxLineLength:Main.kt$"${CEnum.RED}An update is available!${CEnum.RESET} Please visit https://github.com/SpoilerRules/nitro-generator/releases/latest to download the latest version (${CEnum.BRIGHT_PURPLE}$remoteVersion${CEnum.RESET})."</ID>
<ID>MaxLineLength:NitroValidationWrapper.kt$NitroValidationWrapper$"${threadIdentity?.let { "${CEnum.RESET}[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$it${CEnum.RESET}] " } ?: ""}Retrying validation of $nitroCode in ${CEnum.ORANGE}${configuration.generalSettings.retryDelay - index}${CEnum.RESET} seconds."</ID>
<ID>MaxLineLength:NitroValidatorAdvancedMt.kt$NitroValidatorAdvancedMt$Logger.printDebug("[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$threadIdentity${CEnum.RESET}] Using proxy: ${CEnum.CYAN}${proxyInfo.first}:${proxyInfo.second}${CEnum.RESET}")</ID>
<ID>MaxLineLength:NitroValidatorAdvancedMt.kt$NitroValidatorAdvancedMt$throw ConnectException("[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$threadIdentity${CEnum.RESET}] Failed to establish a connection to validate the nitro code because the next proxy is null.")</ID>
<ID>MaxLineLength:NitroValidatorConcurrent.kt$NitroValidatorConcurrent$Logger.printDebug("[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$threadIdentity${CEnum.RESET}] Using proxy: ${CEnum.CYAN}${proxyInfo.first}:${proxyInfo.second}${CEnum.RESET}")</ID>
<ID>MaxLineLength:NitroValidatorConcurrent.kt$NitroValidatorConcurrent$throw ConnectException("[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$threadIdentity${CEnum.RESET}] Failed to establish a connection to validate the nitro code because the next proxy is null.")</ID>
<ID>MaxLineLength:TabProxy.kt$TabProxy$if (BaseConfigurationFactory.getInstance().proxySettings.rawContentSeparator == "\n") "\\n" else BaseConfigurationFactory.getInstance().proxySettings.rawContentSeparator</ID>
</CurrentIssues>
</SmellBaseline>
30 changes: 13 additions & 17 deletions config/klint/baseline.xml
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<baseline version="1.0">
<file name="src/main/kotlin/com/spoiligaming/generator/GeneratorBean.kt">
<error line="50" column="1" source="standard:max-line-length" />
<error line="49" column="1" source="standard:max-line-length" />
</file>
<file name="src/main/kotlin/com/spoiligaming/generator/Main.kt">
<error line="40" column="1" source="standard:max-line-length" />
</file>
<file name="src/main/kotlin/com/spoiligaming/generator/NitroValidationWrapper.kt">
<error line="80" column="1" source="standard:max-line-length" />
<error line="146" column="1" source="standard:max-line-length" />
<error line="213" column="1" source="standard:max-line-length" />
<error line="219" column="1" source="standard:max-line-length" />
<error line="268" column="1" source="standard:max-line-length" />
<error line="271" column="1" source="standard:max-line-length" />
<error line="275" column="1" source="standard:max-line-length" />
<error line="277" column="1" source="standard:max-line-length" />
</file>
<file name="src/main/kotlin/com/spoiligaming/generator/NitroValidatorAdvancedMt.kt">
<error line="84" column="1" source="standard:max-line-length" />
<error line="150" column="1" source="standard:max-line-length" />
<error line="191" column="1" source="standard:max-line-length" />
<error line="192" column="1" source="standard:max-line-length" />
<error line="195" column="1" source="standard:max-line-length" />
<error line="266" column="1" source="standard:max-line-length" />
<error line="272" column="1" source="standard:max-line-length" />
<error line="323" column="1" source="standard:max-line-length" />
<error line="324" column="1" source="standard:max-line-length" />
<error line="330" column="1" source="standard:max-line-length" />
</file>
<file name="src/main/kotlin/com/spoiligaming/generator/NitroValidatorConcurrent.kt">
<error line="68" column="1" source="standard:max-line-length" />
<error line="117" column="1" source="standard:max-line-length" />
<error line="127" column="1" source="standard:max-line-length" />
</file>
<file name="src/main/kotlin/com/spoiligaming/generator/NitroValidatorOrdinary.kt">
<error line="125" column="1" source="standard:max-line-length" />
</file>
<file name="src/main/kotlin/com/spoiligaming/generator/NitroValidatorSimpleMt.kt">
<error line="91" column="1" source="standard:max-line-length" />
</file>
<file name="src/main/kotlin/com/spoiligaming/generator/ProxyHandler.kt">
<error line="59" column="1" source="standard:max-line-length" />
<error line="79" column="1" source="standard:max-line-length" />
Expand Down
13 changes: 3 additions & 10 deletions src/main/kotlin/com/spoiligaming/generator/GeneratorBean.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ object GeneratorBean {
) { // very fragile, please do not touch this
when {
config.proxySettings.mode in 1..3 && !config.multithreadingSettings.enabled ->
NitroValidatorOrdinary.validateNitro(nitroCode, 0, config)
NitroValidatorSequential.validateNitro(nitroCode, 0, config)
else ->
handleConcurrentValidation(nitroCode, config)
}
Expand All @@ -56,14 +56,6 @@ object GeneratorBean {
initialNitroCode: String,
config: BaseConfigurationFactory,
) {
val validateNitro: (String, BaseConfigurationFactory, String) -> Unit =
{ nitroCode, configReference, threadIdentifier ->
when (configReference.proxySettings.mode) {
1 -> NitroValidatorSimpleMt.validateNitro(nitroCode, configReference, 0, threadIdentifier)
in 2..3 -> NitroValidatorAdvancedMt.validateNitro(nitroCode, configReference, 0, threadIdentifier)
}
}

val semaphore = Semaphore(config.multithreadingSettings.threadLimit)

runBlocking {
Expand All @@ -74,9 +66,10 @@ object GeneratorBean {
semaphore.acquire()
val nitroCode =
if (index++ == 0) initialNitroCode else generateNitroCode(config.generalSettings.generatePromotionalGiftCode)
validateNitro(
NitroValidatorConcurrent.validateNitro(
nitroCode,
config,
0,
coroutineContext[Job]?.toString()?.substringAfter('@')
?: "UnknownThread".substringBefore(']'),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ package com.spoiligaming.generator
import com.spoiligaming.generator.configuration.BaseConfigurationFactory
import com.spoiligaming.logging.CEnum
import com.spoiligaming.logging.Logger
import java.net.HttpURLConnection
import java.net.Authenticator
import java.net.ConnectException
import java.net.InetSocketAddress
import java.net.PasswordAuthentication
import java.net.Proxy
import java.net.URI
import java.security.SecureRandom
import java.security.cert.X509Certificate
Expand All @@ -17,7 +21,7 @@ import javax.net.ssl.X509TrustManager

object NitroValidationWrapper {
fun setProperties(
connectionInstance: HttpURLConnection,
connectionInstance: HttpsURLConnection,
config: BaseConfigurationFactory,
) {
with(connectionInstance) {
Expand Down Expand Up @@ -91,13 +95,13 @@ object NitroValidationWrapper {
nitroCode: String,
isAutoclaimSucceeded: Boolean?,
) {
var connection: HttpURLConnection? = null
var connection: HttpsURLConnection? = null

runCatching {
val currentDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
connection =
URI.create(BaseConfigurationFactory.getInstance().generalSettings.discordWebhookURL).toURL()
.openConnection() as HttpURLConnection
.openConnection() as HttpsURLConnection
connection?.apply {
requestMethod = "POST"
setRequestProperty("Content-Type", "application/json")
Expand Down Expand Up @@ -140,7 +144,7 @@ object NitroValidationWrapper {
this.flush()
}

connection?.responseCode?.takeIf { it != HttpURLConnection.HTTP_OK && it != HttpURLConnection.HTTP_NO_CONTENT }
connection?.responseCode?.takeIf { it != HttpsURLConnection.HTTP_OK && it != HttpsURLConnection.HTTP_NO_CONTENT }
?.let {
Logger.printError(
"Failed to send Discord webhook. Server responded with code $it: ${connection?.responseMessage ?: "No response message"}",
Expand All @@ -153,6 +157,55 @@ object NitroValidationWrapper {
}
}

fun getConnection(
nitroCode: String,
threadIdentity: String?,
config: BaseConfigurationFactory,
proxyInavailabilityBehavior: (() -> Unit)? = null,
): HttpsURLConnection {
val threadIdentityPrefix =
threadIdentity?.let {
"${CEnum.RESET}[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$it${CEnum.RESET}] "
} ?: ""

val proxy =
when {
!config.proxySettings.enabled -> Proxy.NO_PROXY
config.proxySettings.mode == 1 -> {
val proxyType = config.proxySettings.getProxyType(config.proxySettings.protocol)
if (proxyType == Proxy.Type.SOCKS && config.proxySettings.isAuthenticationRequired) {
Authenticator.setDefault(
object : Authenticator() {
override fun getPasswordAuthentication() =
PasswordAuthentication(
config.proxySettings.username,
config.proxySettings.password.toCharArray(),
)
},
)
}
Proxy(proxyType, InetSocketAddress(config.proxySettings.host, config.proxySettings.port.toInt()))
}
else ->
ProxyHandler.getNextProxy()?.let { proxyInfo ->
Logger.printDebug("${threadIdentityPrefix}Using proxy: ${CEnum.CYAN}${proxyInfo.first}:${proxyInfo.second}${CEnum.RESET}")
Proxy(
config.proxySettings.getProxyType(config.proxySettings.protocol),
InetSocketAddress(proxyInfo.first, proxyInfo.second),
)
} ?: run {
threadIdentity?.let { proxyInavailabilityBehavior?.invoke() }
throw ConnectException("${threadIdentityPrefix}Failed to establish a connection to validate the nitro code because the next proxy is null.")
}
}

disableProxySecurity()

return URI(
"https://discordapp.com/api/v9/entitlements/gift-codes/$nitroCode?with_application=false&with_subscription_plan=true",
).toURL().openConnection(proxy) as HttpsURLConnection
}

@Suppress("EmptyFunctionBlock")
fun disableProxySecurity() {
HttpsURLConnection.setDefaultSSLSocketFactory(
Expand Down Expand Up @@ -180,14 +233,15 @@ object NitroValidationWrapper {
)
}.socketFactory,
)
HttpsURLConnection.setDefaultHostnameVerifier { _, _ -> true }
}

private fun claimValidNitro(
nitroCode: String,
isTokenValidated: Boolean,
config: BaseConfigurationFactory,
): Int {
val setProperties: (HttpURLConnection, BaseConfigurationFactory) -> Unit = { connection, configReference ->
val setProperties: (HttpsURLConnection, BaseConfigurationFactory) -> Unit = { connection, configReference ->
connection.setRequestProperty(
"User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
Expand All @@ -199,13 +253,13 @@ object NitroValidationWrapper {
}

if (!isTokenValidated) {
with(URI("https://discordapp.com/api/v9/users/@me").toURL().openConnection() as HttpURLConnection) {
with(URI("https://discordapp.com/api/v9/users/@me").toURL().openConnection() as HttpsURLConnection) {
setRequestProperty("Content-Type", "application/json")
setProperties(this, config)

disconnect()
when (responseCode) {
HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_NO_CONTENT -> {
HttpsURLConnection.HTTP_OK, HttpsURLConnection.HTTP_NO_CONTENT -> {
val jsonResponse =
inputStream.bufferedReader().use { it.readText() }.split("[{},]".toRegex())
.filter { it.contains(":") }
Expand All @@ -216,7 +270,7 @@ object NitroValidationWrapper {
)
}

HttpURLConnection.HTTP_UNAUTHORIZED -> {
HttpsURLConnection.HTTP_UNAUTHORIZED -> {
Logger.printWarning(
"The token you entered for Auto-Claim is invalid. Auto-Claim functionality will be disrupted until a valid token is provided.",
)
Expand All @@ -233,25 +287,23 @@ object NitroValidationWrapper {

with(
URI("https://discordapp.com/api/v9/entitlements/gift-codes/$nitroCode/redeem").toURL()
.openConnection() as HttpURLConnection,
.openConnection() as HttpsURLConnection,
) {
requestMethod = "POST"
setProperties(this, config)

disconnect()
responseCode.takeIf { it != HttpURLConnection.HTTP_OK && it != HttpURLConnection.HTTP_NO_CONTENT }
responseCode.takeIf { it != HttpsURLConnection.HTTP_OK && it != HttpsURLConnection.HTTP_NO_CONTENT }
?.let {
return when (it) {
HttpURLConnection.HTTP_UNAUTHORIZED -> { // should not be reachable but added, just in case
HttpsURLConnection.HTTP_UNAUTHORIZED -> { // should not be reachable but added, just in case
Logger.printWarning("The token you entered for Auto-Claim is potentially incorrect.")
1
}

HttpURLConnection.HTTP_NOT_FOUND -> {
HttpsURLConnection.HTTP_NOT_FOUND -> {
Logger.printError("The Nitro code ($nitroCode) that was attempted to be claimed has already been claimed.")
1
}

else -> claimValidNitro(nitroCode, true, config)
}
}
Expand All @@ -266,22 +318,28 @@ object NitroValidationWrapper {
threadIdentity: String?,
crossinline validateFunction: (String, BaseConfigurationFactory, Int) -> Unit,
) {
val shouldDelay = configuration.generalSettings.retryDelay > 0 && !(configuration.proxySettings.enabled && configuration.proxySettings.mode in 2..3)
val shouldRetryWithoutDelay = configuration.proxySettings.mode in 2..3 && configuration.proxySettings.enabled || configuration.generalSettings.retryDelay <= 0
val threadIdentityPrefix =
threadIdentity?.let {
"${CEnum.RESET}[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$it${CEnum.RESET}] "
} ?: ""

val shouldDelay =
configuration.generalSettings.retryDelay > 0 && !(configuration.proxySettings.enabled && configuration.proxySettings.mode in 2..3)
val shouldRetryWithoutDelay =
configuration.proxySettings.mode in 2..3 && configuration.proxySettings.enabled || configuration.generalSettings.retryDelay <= 0

when {
shouldDelay -> {
repeat(configuration.generalSettings.retryDelay) { index ->
Logger.printWarning(
"${threadIdentity?.let { "${CEnum.RESET}[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$it${CEnum.RESET}] " } ?: ""}Retrying validation of $nitroCode in ${CEnum.ORANGE}${configuration.generalSettings.retryDelay - index}${CEnum.RESET} seconds.",
"${threadIdentityPrefix}Retrying validation of $nitroCode in ${CEnum.ORANGE}${configuration.generalSettings.retryDelay - index}${CEnum.RESET} seconds.",
)
Thread.sleep(1000)
}
}
shouldRetryWithoutDelay -> {
Logger.printDebug("retrying without delay")
Logger.printWarning(
"${threadIdentity?.let { "${CEnum.RESET}[${CEnum.BLUE}THREAD: ${CEnum.RESET}${CEnum.CYAN}$it${CEnum.RESET}] " } ?: ""}Retrying validation of Nitro code: $nitroCode.",
"${threadIdentityPrefix}Retrying validation of Nitro code: $nitroCode.",
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import com.spoiligaming.logging.CEnum
import com.spoiligaming.logging.Logger
import java.net.Authenticator
import java.net.ConnectException
import java.net.HttpURLConnection
import java.net.InetSocketAddress
import java.net.PasswordAuthentication
import java.net.Proxy
import java.net.URI
import java.util.concurrent.atomic.AtomicBoolean
import javax.net.ssl.HttpsURLConnection

object NitroValidatorAdvancedMt {
object NitroValidatorConcurrent {
var isNextProxyAvailable = AtomicBoolean(true)

fun validateNitro(
Expand All @@ -21,7 +21,7 @@ object NitroValidatorAdvancedMt {
retryCount: Int,
threadIdentity: String,
) {
if (!isNextProxyAvailable.get()) {
if (!isNextProxyAvailable.get() && config.proxySettings.mode in 2..3) {
return
}

Expand Down Expand Up @@ -86,7 +86,7 @@ object NitroValidatorAdvancedMt {
nitroCode: String,
threadIdentity: String,
config: BaseConfigurationFactory,
): HttpURLConnection {
): HttpsURLConnection {
val proxy =
when {
!config.proxySettings.enabled -> Proxy.NO_PROXY
Expand Down Expand Up @@ -134,6 +134,6 @@ object NitroValidatorAdvancedMt {
return URI(
"https://discordapp.com/api/v9/entitlements/gift-codes/$nitroCode?with_application=false&with_subscription_plan=true",
).toURL()
.openConnection(proxy) as HttpURLConnection
.openConnection(proxy) as HttpsURLConnection
}
}
Loading

0 comments on commit 6181fab

Please sign in to comment.