From 26bf4bfd97c868b6a666d1960094dec8384c6e99 Mon Sep 17 00:00:00 2001
From: Neu <38368299+Neuheit@users.noreply.github.com>
Date: Mon, 9 Dec 2024 21:52:34 -0500
Subject: [PATCH 1/3] add plugin checker
---
LavalinkServer/build.gradle.kts | 1 +
.../server/bootstrap/PluginManager.kt | 33 +++++++++++++++++++
settings.gradle.kts | 1 +
3 files changed, 35 insertions(+)
diff --git a/LavalinkServer/build.gradle.kts b/LavalinkServer/build.gradle.kts
index ddb62b35a..c9eaea080 100644
--- a/LavalinkServer/build.gradle.kts
+++ b/LavalinkServer/build.gradle.kts
@@ -65,6 +65,7 @@ dependencies {
implementation(libs.kotlin.reflect)
implementation(libs.logback)
implementation(libs.sentry.logback)
+ implementation(libs.semver)
implementation(libs.oshi) {
// This version of SLF4J does not recognise Logback 1.2.3
exclude(group = "org.slf4j", module = "slf4j-api")
diff --git a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
index c3ed4cb73..be432ae2d 100644
--- a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
+++ b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
@@ -9,9 +9,11 @@ import java.io.FileOutputStream
import java.io.InputStream
import java.net.URL
import java.net.URLClassLoader
+import java.net.HttpURLConnection
import java.nio.channels.Channels
import java.util.*
import java.util.jar.JarFile
+import io.github.z4kn4fein.semver.toVersion
@SpringBootApplication
class PluginManager(val config: PluginsConfig) {
@@ -83,6 +85,37 @@ class PluginManager(val config: PluginsConfig) {
val file = File(directory, declaration.canonicalJarName)
downloadJar(file, url)
}
+
+ checkPluginForUpdates(declaration)
+ }
+ }
+
+ private fun checkPluginForUpdates(declaration: Declaration) {
+ val splitPath = declaration.url.split('/')
+
+ val baseSplitPath = splitPath.dropLast(2)
+ val basePath = baseSplitPath.joinToString("/") + "/maven-metadata.xml"
+
+ val connection = URL(basePath).openConnection() as HttpURLConnection
+ connection.inputStream.bufferedReader().use {
+ val lines = it.readLines()
+ for (line in lines) {
+ val regex = "(.*?)".toRegex()
+ val match = regex.find(line)
+ val latest = match?.groups?.get(1)?.value
+ if (latest != null) {
+ val latestVersion = latest.toVersion()
+ val currentVersion = declaration.version.toVersion()
+
+ if(latestVersion > currentVersion) {
+ log.warn("A newer version of ${declaration.name} was found: $latestVersion. " +
+ "The current version is $currentVersion.")
+ } else {
+ log.info("Plugin ${declaration.name} is up to date")
+ }
+ break
+ }
+ }
}
}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 14cbf4aa8..68eb7f315 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -76,6 +76,7 @@ fun VersionCatalogBuilder.common() {
library("logback", "ch.qos.logback", "logback-classic").version("1.5.6")
library("sentry-logback", "io.sentry", "sentry-logback").version("7.10.0")
library("oshi", "com.github.oshi", "oshi-core").version("6.4.11")
+ library("semver", "io.github.z4kn4fein", "semver").version("2.0.0")
}
fun VersionCatalogBuilder.other() {
From a7e27d145044a3c42315d12615385177bf576e7a Mon Sep 17 00:00:00 2001
From: Neu <38368299+Neuheit@users.noreply.github.com>
Date: Wed, 25 Dec 2024 17:09:42 -0500
Subject: [PATCH 2/3] remove 3rd party plugin and make semver checks local
---
LavalinkServer/build.gradle.kts | 1 -
.../server/bootstrap/PluginManager.kt | 11 ++--
.../dev/arbjerg/lavalink/protocol/v4/info.kt | 64 +++++++++++++++++++
settings.gradle.kts | 1 -
4 files changed, 69 insertions(+), 8 deletions(-)
diff --git a/LavalinkServer/build.gradle.kts b/LavalinkServer/build.gradle.kts
index c9eaea080..ddb62b35a 100644
--- a/LavalinkServer/build.gradle.kts
+++ b/LavalinkServer/build.gradle.kts
@@ -65,7 +65,6 @@ dependencies {
implementation(libs.kotlin.reflect)
implementation(libs.logback)
implementation(libs.sentry.logback)
- implementation(libs.semver)
implementation(libs.oshi) {
// This version of SLF4J does not recognise Logback 1.2.3
exclude(group = "org.slf4j", module = "slf4j-api")
diff --git a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
index be432ae2d..7958c7e8e 100644
--- a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
+++ b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
@@ -13,7 +13,7 @@ import java.net.HttpURLConnection
import java.nio.channels.Channels
import java.util.*
import java.util.jar.JarFile
-import io.github.z4kn4fein.semver.toVersion
+import dev.arbjerg.lavalink.protocol.v4.Version
@SpringBootApplication
class PluginManager(val config: PluginsConfig) {
@@ -104,12 +104,11 @@ class PluginManager(val config: PluginsConfig) {
val match = regex.find(line)
val latest = match?.groups?.get(1)?.value
if (latest != null) {
- val latestVersion = latest.toVersion()
- val currentVersion = declaration.version.toVersion()
-
+ val latestVersion = Version.fromSemver(latest)
+ val currentVersion = Version.fromSemver(declaration.version)
if(latestVersion > currentVersion) {
- log.warn("A newer version of ${declaration.name} was found: $latestVersion. " +
- "The current version is $currentVersion.")
+ log.warn("A newer version of ${declaration.name} was found: $latestVersion, " +
+ "The current version is $currentVersion")
} else {
log.info("Plugin ${declaration.name} is up to date")
}
diff --git a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/info.kt b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/info.kt
index d739c53e3..2040c25cc 100644
--- a/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/info.kt
+++ b/protocol/src/commonMain/kotlin/dev/arbjerg/lavalink/protocol/v4/info.kt
@@ -62,6 +62,70 @@ data class Version(
return Version(semver, major.toInt(), minor.toInt(), patch.toInt(), preRelease)
}
}
+
+ override fun toString(): String {
+ var baseSemver = "${major}.${minor}.${patch}"
+
+ if(!preRelease.isNullOrEmpty())
+ baseSemver += "-${preRelease}"
+
+ return baseSemver
+ }
+
+ operator fun compareTo(other: Version): Int {
+ // Compare major, minor, and patch
+ val majorDiff = major - other.major
+ if (majorDiff != 0) return majorDiff
+
+ val minorDiff = minor - other.minor
+ if (minorDiff != 0) return minorDiff
+
+ val patchDiff = patch - other.patch
+ if (patchDiff != 0) return patchDiff
+
+ // Compare prerelease (null means no prerelease and is greater)
+ return when {
+ preRelease.isNullOrEmpty() && other.preRelease.isNullOrEmpty() -> 0
+ preRelease.isNullOrEmpty() && !other.preRelease.isNullOrEmpty() -> 1
+ !preRelease.isNullOrEmpty() && other.preRelease.isNullOrEmpty() -> -1
+ !preRelease.isNullOrEmpty() && !other.preRelease.isNullOrEmpty() -> comparePreRelease(preRelease, other.preRelease)
+ else -> 0
+ }
+ }
+
+ private fun comparePreRelease(part1: String, part2: String): Int {
+ val components1 = part1.split(".")
+ val components2 = part2.split(".")
+ val maxLength = maxOf(components1.size, components2.size)
+
+ for (i in 0 until maxLength) {
+ val comp1 = components1.getOrNull(i)
+ val comp2 = components2.getOrNull(i)
+
+ if (comp1 == null) return -1 // `part1` is shorter and considered smaller
+ if (comp2 == null) return 1 // `part2` is shorter and considered smaller
+
+ val isNumeric1 = comp1.all { it.isDigit() }
+ val isNumeric2 = comp2.all { it.isDigit() }
+
+ when {
+ isNumeric1 && isNumeric2 -> {
+ // Compare numerically
+ val diff = comp1.toInt() - comp2.toInt()
+ if (diff != 0) return diff
+ }
+ isNumeric1 -> return -1 // Numeric parts come before string parts
+ isNumeric2 -> return 1 // String parts come after numeric parts
+ else -> {
+ // Compare lexicographically
+ val diff = comp1.compareTo(comp2)
+ if (diff != 0) return diff
+ }
+ }
+ }
+
+ return 0 // Parts are equal
+ }
}
@Serializable
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 68eb7f315..14cbf4aa8 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -76,7 +76,6 @@ fun VersionCatalogBuilder.common() {
library("logback", "ch.qos.logback", "logback-classic").version("1.5.6")
library("sentry-logback", "io.sentry", "sentry-logback").version("7.10.0")
library("oshi", "com.github.oshi", "oshi-core").version("6.4.11")
- library("semver", "io.github.z4kn4fein", "semver").version("2.0.0")
}
fun VersionCatalogBuilder.other() {
From 1dfaddd9d5f59ee12ce825b6b4767dd9b267c32a Mon Sep 17 00:00:00 2001
From: Neu <38368299+Neuheit@users.noreply.github.com>
Date: Wed, 25 Dec 2024 19:35:19 -0500
Subject: [PATCH 3/3] remove regex and use xml parsing
---
.../server/bootstrap/PluginManager.kt | 35 +++++++++----------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
index 7958c7e8e..d6d138e8b 100644
--- a/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
+++ b/LavalinkServer/src/main/java/lavalink/server/bootstrap/PluginManager.kt
@@ -13,6 +13,7 @@ import java.net.HttpURLConnection
import java.nio.channels.Channels
import java.util.*
import java.util.jar.JarFile
+import javax.xml.parsers.DocumentBuilderFactory
import dev.arbjerg.lavalink.protocol.v4.Version
@SpringBootApplication
@@ -95,25 +96,23 @@ class PluginManager(val config: PluginsConfig) {
val baseSplitPath = splitPath.dropLast(2)
val basePath = baseSplitPath.joinToString("/") + "/maven-metadata.xml"
+ val documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
+ val document = documentBuilder.parse(basePath)
- val connection = URL(basePath).openConnection() as HttpURLConnection
- connection.inputStream.bufferedReader().use {
- val lines = it.readLines()
- for (line in lines) {
- val regex = "(.*?)".toRegex()
- val match = regex.find(line)
- val latest = match?.groups?.get(1)?.value
- if (latest != null) {
- val latestVersion = Version.fromSemver(latest)
- val currentVersion = Version.fromSemver(declaration.version)
- if(latestVersion > currentVersion) {
- log.warn("A newer version of ${declaration.name} was found: $latestVersion, " +
- "The current version is $currentVersion")
- } else {
- log.info("Plugin ${declaration.name} is up to date")
- }
- break
- }
+ var elements = document.getElementsByTagName("latest")
+ if(elements.length == 0) {
+ elements = document.getElementsByTagName("release")
+ }
+
+ if (elements.length > 0) {
+ val latest = elements.item(0).textContent
+ val latestVersion = Version.fromSemver(latest)
+ val currentVersion = Version.fromSemver(declaration.version)
+ if(latestVersion > currentVersion) {
+ log.warn("A newer version of ${declaration.name} was found: $latestVersion, " +
+ "The current version is $currentVersion")
+ } else {
+ log.info("Plugin ${declaration.name} is up to date")
}
}
}