Use kotlinx.serialization for ip requests

This commit is contained in:
Jakob K
2021-05-15 18:32:37 +02:00
parent d4e8e11bf5
commit 8d59c3fd2e
6 changed files with 91 additions and 60 deletions

View File

@@ -1,9 +1,11 @@
package net.axay.kspigot.ipaddress package net.axay.kspigot.ipaddress
import kotlinx.serialization.SerializationException
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import net.axay.kspigot.ipaddress.badipdetectionservices.GetIPIntel import net.axay.kspigot.ipaddress.badipdetectionservices.GetIPIntel
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.json.JSONException
import org.json.JSONObject
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
@@ -47,7 +49,7 @@ fun Player.checkIP(
* - [net.axay.kspigot.ipaddress.badipdetectionservices.VPNBlocker] * - [net.axay.kspigot.ipaddress.badipdetectionservices.VPNBlocker]
*/ */
class BadIPDetector( class BadIPDetector(
val services: List<BadIPDetectionService>, private val services: List<BadIPDetectionService>,
) { ) {
/** /**
* Alternative constructor. * Alternative constructor.
@@ -91,7 +93,9 @@ abstract class BadIPDetectionService(
) { ) {
protected abstract fun requestString(ip: String): String protected abstract fun requestString(ip: String): String
protected open fun requestHeaders() = emptyMap<String, String>() protected open fun requestHeaders() = emptyMap<String, String>()
protected abstract fun interpreteResult(result: JSONObject): BadIPDetectionResult
protected abstract fun interpreteResult(result: JsonObject): BadIPDetectionResult
fun isBad(ip: String): BadIPDetectionResult { fun isBad(ip: String): BadIPDetectionResult {
val con = URL(requestString(ip)).openConnection() as HttpURLConnection val con = URL(requestString(ip)).openConnection() as HttpURLConnection
con.requestMethod = "GET" con.requestMethod = "GET"
@@ -102,8 +106,8 @@ abstract class BadIPDetectionService(
return BadIPDetectionResult.LIMIT return BadIPDetectionResult.LIMIT
else { else {
val result = try { val result = try {
con.inputStream.use { JSONObject(it.readAllBytes().decodeToString()) } con.inputStream.use { Json.decodeFromString<JsonObject>(it.readAllBytes().decodeToString()) }
} catch (exc: JSONException) { } catch (exc: SerializationException) {
null null
} ?: return BadIPDetectionResult.ERROR } ?: return BadIPDetectionResult.ERROR
@@ -114,4 +118,4 @@ abstract class BadIPDetectionService(
} }
} }
} }
} }

View File

@@ -2,15 +2,34 @@
package net.axay.kspigot.ipaddress package net.axay.kspigot.ipaddress
import com.google.gson.JsonObject import kotlinx.serialization.decodeFromString
import net.axay.kspigot.languageextensions.fromUrlJson import kotlinx.serialization.json.Json
import net.axay.kspigot.languageextensions.getStringOrNull import kotlinx.serialization.json.JsonObject
import net.axay.kspigot.main.ValueHolder import kotlinx.serialization.json.jsonPrimitive
import org.bukkit.entity.Player import org.bukkit.entity.Player
@Suppress("HttpUrlsUsage")
private const val IP_API = "http://ip-api.com/json/" private const val IP_API = "http://ip-api.com/json/"
private const val IP_API_FIELDS = private val IP_API_FIELDS = listOf(
"status,message,continent,continentCode,country,countryCode,region,regionName,city,district,zip,lat,lon,timezone,currency,isp,org,query" "status",
"message",
"continent",
"continentCode",
"country",
"countryCode",
"region",
"regionName",
"city",
"district",
"zip",
"lat",
"lon",
"timezone",
"currency",
"isp",
"org",
"query"
).joinToString(",")
/** /**
* @return The players ip address. * @return The players ip address.
@@ -30,11 +49,11 @@ val Player.ipAddressData get() = ipAddressData()
fun Player.ipAddressData(language: IPAddressDataLanguage = IPAddressDataLanguage.ENGLISH): IPAddressData? { fun Player.ipAddressData(language: IPAddressDataLanguage = IPAddressDataLanguage.ENGLISH): IPAddressData? {
return try { return try {
val hostString = address?.hostString ?: return null val hostString = address?.hostString ?: return null
val jsonObject = ValueHolder.getGson().fromUrlJson( val jsonObject = Json.decodeFromString<JsonObject>(
"$IP_API${hostString}?fields=${IP_API_FIELDS}?lang=${language.code}" "$IP_API${hostString}?fields=${IP_API_FIELDS}?lang=${language.code}"
) ?: return null )
if (jsonObject["status"].toString() == "fail") return null if (jsonObject["status"]?.jsonPrimitive?.toString() == "fail") return null
IPAddressData(jsonObject) IPAddressData(jsonObject)
} catch (exc: Exception) { } catch (exc: Exception) {
@@ -54,25 +73,25 @@ enum class IPAddressDataLanguage(val code: String) {
} }
class IPAddressData(private val json: JsonObject) { class IPAddressData(private val json: JsonObject) {
val ip get() = json.getStringOrNull("query") val ip by lazy { json["query"]?.jsonPrimitive?.toString() }
// region // region
val continent get() = json.getStringOrNull("continent") val continent by lazy { json["continent"]?.jsonPrimitive?.toString() }
val continentCode get() = json.getStringOrNull("continentCode") val continentCode by lazy { json["continentCode"]?.jsonPrimitive?.toString() }
val country get() = json.getStringOrNull("country") val country by lazy { json["country"]?.jsonPrimitive?.toString() }
val countryCode get() = json.getStringOrNull("countryCode") val countryCode by lazy { json["countryCode"]?.jsonPrimitive?.toString() }
val region get() = json.getStringOrNull("regionName") val region by lazy { json["regionName"]?.jsonPrimitive?.toString() }
val regionCode get() = json.getStringOrNull("region") val regionCode by lazy { json["region"]?.jsonPrimitive?.toString() }
val city get() = json.getStringOrNull("city") val city by lazy { json["city"]?.jsonPrimitive?.toString() }
val district get() = json.getStringOrNull("district") val district by lazy { json["district"]?.jsonPrimitive?.toString() }
val postalCode get() = json.getStringOrNull("zip") val postalCode by lazy { json["zip"]?.jsonPrimitive?.toString() }
val timezone get() = json.getStringOrNull("timezone") val timezone by lazy { json["timezone"]?.jsonPrimitive?.toString() }
// position // position
val latitude get() = json.getStringOrNull("lat") val latitude by lazy { json["lat"]?.jsonPrimitive?.toString() }
val longitude get() = json.getStringOrNull("lon") val longitude by lazy { json["lon"]?.jsonPrimitive?.toString() }
// information // information
val internetServiceProvider get() = json.getStringOrNull("isp") val internetServiceProvider by lazy { json["isp"]?.jsonPrimitive?.toString() }
val organisation get() = json.getStringOrNull("org") val organisation by lazy { json["org"]?.jsonPrimitive?.toString() }
} }

View File

@@ -2,21 +2,22 @@
package net.axay.kspigot.ipaddress.badipdetectionservices package net.axay.kspigot.ipaddress.badipdetectionservices
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.floatOrNull
import kotlinx.serialization.json.jsonPrimitive
import net.axay.kspigot.ipaddress.BadIPDetectionResult import net.axay.kspigot.ipaddress.BadIPDetectionResult
import net.axay.kspigot.ipaddress.BadIPDetectionService import net.axay.kspigot.ipaddress.BadIPDetectionService
import net.axay.kspigot.languageextensions.getStringOrNull
import org.json.JSONObject
class GetIPIntel( class GetIPIntel(
private val intensity: Float = 0.99f, private val intensity: Float = 0.99f,
private val contactEmail: String = "foo@bar.com", private val contactEmail: String = "foo@bar.com",
) : BadIPDetectionService("getipintel.net") { ) : BadIPDetectionService("getipintel.net") {
override fun requestString(ip: String) = override fun requestString(ip: String) =
"http://check.getipintel.net/check.php?ip=$ip&contact=$contactEmail&format=json" "https://check.getipintel.net/check.php?ip=$ip&contact=$contactEmail&format=json"
override fun interpreteResult(result: JSONObject): BadIPDetectionResult { override fun interpreteResult(result: JsonObject): BadIPDetectionResult {
val probability = result.getStringOrNull("result")?.toFloatOrNull() val probability = result["result"]?.jsonPrimitive?.floatOrNull
?: return BadIPDetectionResult.ERROR ?: return BadIPDetectionResult.ERROR
return if (probability >= intensity) BadIPDetectionResult.GENERAL_BAD else BadIPDetectionResult.GOOD return if (probability >= intensity) BadIPDetectionResult.GENERAL_BAD else BadIPDetectionResult.GOOD
} }
} }

View File

@@ -2,19 +2,21 @@
package net.axay.kspigot.ipaddress.badipdetectionservices package net.axay.kspigot.ipaddress.badipdetectionservices
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonPrimitive
import net.axay.kspigot.ipaddress.BadIPDetectionResult import net.axay.kspigot.ipaddress.BadIPDetectionResult
import net.axay.kspigot.ipaddress.BadIPDetectionService import net.axay.kspigot.ipaddress.BadIPDetectionService
import net.axay.kspigot.languageextensions.getStringOrNull
import org.json.JSONObject
class IPHub( class IPHub(
private val apiKey: String, private val apiKey: String,
private val ifStrict: Boolean = false, private val ifStrict: Boolean = false,
) : BadIPDetectionService("iphub.info") { ) : BadIPDetectionService("iphub.info") {
override fun requestString(ip: String) = "http://v2.api.iphub.info/ip/$ip" override fun requestString(ip: String) = "https://v2.api.iphub.info/ip/$ip"
override fun requestHeaders() = mapOf("X-Key" to apiKey) override fun requestHeaders() = mapOf("X-Key" to apiKey)
override fun interpreteResult(result: JSONObject): BadIPDetectionResult {
val ifBlock = result.getStringOrNull("block")?.toInt() ?: return BadIPDetectionResult.ERROR override fun interpreteResult(result: JsonObject): BadIPDetectionResult {
val ifBlock = result["block"]?.jsonPrimitive?.intOrNull ?: return BadIPDetectionResult.ERROR
return if (ifBlock == 1 || (ifStrict && ifBlock == 2)) BadIPDetectionResult.GENERAL_BAD else BadIPDetectionResult.GOOD return if (ifBlock == 1 || (ifStrict && ifBlock == 2)) BadIPDetectionResult.GENERAL_BAD else BadIPDetectionResult.GOOD
} }
} }

View File

@@ -1,21 +1,23 @@
package net.axay.kspigot.ipaddress.badipdetectionservices package net.axay.kspigot.ipaddress.badipdetectionservices
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.jsonPrimitive
import net.axay.kspigot.ipaddress.BadIPDetectionResult import net.axay.kspigot.ipaddress.BadIPDetectionResult
import net.axay.kspigot.ipaddress.BadIPDetectionService import net.axay.kspigot.ipaddress.BadIPDetectionService
import net.axay.kspigot.languageextensions.getStringOrNull
import org.json.JSONObject
class IPInfo( class IPInfo(
private val token: String, private val token: String,
) : BadIPDetectionService("ipinfo.io") { ) : BadIPDetectionService("ipinfo.io") {
override fun requestString(ip: String) = "https://ipinfo.io/$ip/privacy?token=$token" override fun requestString(ip: String) = "https://ipinfo.io/$ip/privacy?token=$token"
override fun interpreteResult(result: JSONObject): BadIPDetectionResult {
override fun interpreteResult(result: JsonObject): BadIPDetectionResult {
return when { return when {
result.getStringOrNull("vpn").toBoolean() -> BadIPDetectionResult.VPN result["vpn"]?.jsonPrimitive?.boolean == true -> BadIPDetectionResult.VPN
result.getStringOrNull("proxy").toBoolean() -> BadIPDetectionResult.PROXY result["proxy"]?.jsonPrimitive?.boolean == true -> BadIPDetectionResult.PROXY
result.getStringOrNull("tor").toBoolean() -> BadIPDetectionResult.TOR result["tor"]?.jsonPrimitive?.boolean == true -> BadIPDetectionResult.TOR
result.getStringOrNull("hosting").toBoolean() -> BadIPDetectionResult.HOSTING result["hosting"]?.jsonPrimitive?.boolean == true -> BadIPDetectionResult.HOSTING
else -> BadIPDetectionResult.GOOD else -> BadIPDetectionResult.GOOD
} }
} }
} }

View File

@@ -1,21 +1,24 @@
package net.axay.kspigot.ipaddress.badipdetectionservices package net.axay.kspigot.ipaddress.badipdetectionservices
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonPrimitive
import net.axay.kspigot.ipaddress.BadIPDetectionResult import net.axay.kspigot.ipaddress.BadIPDetectionResult
import net.axay.kspigot.ipaddress.BadIPDetectionService import net.axay.kspigot.ipaddress.BadIPDetectionService
import net.axay.kspigot.languageextensions.getStringOrNull
import org.json.JSONObject
class VPNBlocker : BadIPDetectionService("vpnblocker.net") { class VPNBlocker : BadIPDetectionService("vpnblocker.net") {
override fun requestString(ip: String) = "http://api.vpnblocker.net/v2/json/$ip" override fun requestString(ip: String) = "https://api.vpnblocker.net/v2/json/$ip"
override fun interpreteResult(result: JSONObject): BadIPDetectionResult {
val isBad = result.getStringOrNull("host-ip") override fun interpreteResult(result: JsonObject): BadIPDetectionResult {
val isBad = result["host-ip"]?.jsonPrimitive
return when { return when {
isBad != null -> if (isBad.toBoolean()) BadIPDetectionResult.GENERAL_BAD else BadIPDetectionResult.GOOD isBad != null -> if (isBad.boolean) BadIPDetectionResult.GENERAL_BAD else BadIPDetectionResult.GOOD
else -> { else -> {
val remaining = result.getStringOrNull("remaining_requests")?.toIntOrNull() val remaining = result["remaining_requests"]?.jsonPrimitive?.intOrNull
?: return BadIPDetectionResult.ERROR ?: return BadIPDetectionResult.ERROR
if (remaining <= 0) BadIPDetectionResult.LIMIT else BadIPDetectionResult.ERROR if (remaining <= 0) BadIPDetectionResult.LIMIT else BadIPDetectionResult.ERROR
} }
} }
} }
} }