Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
kotlin.code.style=official
kotlin.stdlib.default.dependency=false
org.gradle.parallel=true
version=2.4.5
version=2.4.6
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies {
tasks.jar {
manifest {
attributes["Main-Class"] = "dev.slne.surf.core.launcher.server.CoreLauncherKt"
attributes["Implementation-Version"] = project.version
Comment thread
TheBjoRedCraft marked this conversation as resolved.
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ object CoreLauncher {
serverOnline.value = true
println("$LOG_PREFIX Server is now online.")
printStartupErrorReport()
launch {
PluginUpdater.gitHubClient.checkForCoreLauncherUpdate()
}
Comment thread
TheBjoRedCraft marked this conversation as resolved.
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,39 @@ package dev.slne.surf.core.launcher.server.updater.github

import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import dev.slne.surf.core.launcher.server.updater.UpdatablePlugin
import dev.slne.surf.core.launcher.api.LauncherConstants
import dev.slne.surf.core.launcher.server.CoreLauncher
import dev.slne.surf.core.launcher.server.LOG_PREFIX
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.net.HttpURLConnection
import java.net.URI
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.StandardCopyOption

private const val CORE_REPOSITORY =
"https://api.github.com/repos/SLNE-Development/surf-core/releases/latest"

class GitHubClient(private val token: String?) {
private val mapper = jacksonObjectMapper()

fun fetchLatestRelease(plugin: UpdatablePlugin): Map<String, Any>? = runCatching {
val connection = openConnection(plugin.latestReleaseUrl, "application/vnd.github+json")
connection.setRequestProperty("X-GitHub-Api-Version", "2022-11-28")
connection.connect()
suspend fun fetchLatestRelease(url: String): Map<String, Any>? = runCatching {
withContext(Dispatchers.IO) {
val connection = openConnection(url, "application/vnd.github+json")
connection.setRequestProperty("X-GitHub-Api-Version", "2022-11-28")
connection.connect()

Comment thread
TheBjoRedCraft marked this conversation as resolved.
if (connection.responseCode != 200) {
return null
}
if (connection.responseCode != 200) {
if (CoreLauncher.config.logGithubReleaseFetchFailures) {
println("$LOG_PREFIX (GitHubClient) Failed to fetch latest release from $url, response code: ${connection.responseCode}")
}
return@withContext null
}

connection.inputStream.use { input ->
mapper.readValue(input, object : TypeReference<Map<String, Any>>() {})
connection.inputStream.use {
mapper.readValue(it, object : TypeReference<Map<String, Any>>() {})
}
}
}.getOrNull()

Expand All @@ -44,4 +56,57 @@ class GitHubClient(private val token: String?) {
token?.let { connection.setRequestProperty("Authorization", "Bearer $it") }
return connection
}

suspend fun checkForCoreLauncherUpdate() = withContext(Dispatchers.IO) {
val currentVersion = LauncherConstants::class.java.`package`?.implementationVersion
?: return@withContext
Comment thread
TheBjoRedCraft marked this conversation as resolved.

val release = fetchLatestRelease(CORE_REPOSITORY) ?: return@withContext
val latestVersion = release["tag_name"] as? String ?: return@withContext

if (!isNewerVersion(currentVersion, latestVersion)) {
return@withContext
}

val asset = (release["assets"] as? List<*>)
?.filterIsInstance<Map<String, Any>>()
?.firstOrNull {
(it["name"] as? String)
?.startsWith("surf-core-launcher-server-") == true
}

val userUrl = asset?.get("html_url") as? String
?: release["html_url"] as? String
?: return@withContext

println("$LOG_PREFIX " + "*".repeat(80))
println("$LOG_PREFIX There is a new version of CoreLauncher available (v$currentVersion -> $latestVersion).")
println("$LOG_PREFIX Download here: $userUrl")
println("$LOG_PREFIX " + "*".repeat(80))
}

private fun isNewerVersion(current: String, latest: String): Boolean {
fun normalize(version: String) = version
.removePrefix("v")
.substringBefore('-')
.split('.')
.map { it.toIntOrNull() ?: 0 }

val currentParts = normalize(current)
val latestParts = normalize(latest)

val max = maxOf(currentParts.size, latestParts.size)

for (i in 0 until max) {
val currentPart = currentParts.getOrElse(i) { 0 }
val latestPart = latestParts.getOrElse(i) { 0 }

when {
latestPart > currentPart -> return true
latestPart < currentPart -> return false
}
}

return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object PluginUpdater {
private val oldPath = pluginsPath.resolve(".old")

private val scanner = PluginScanner(pluginsPath)
private val gitHubClient = GitHubClient(CoreLauncher.config.personalAccessToken)
internal val gitHubClient = GitHubClient(CoreLauncher.config.personalAccessToken)
Comment thread
TheBjoRedCraft marked this conversation as resolved.
private val cooldownTracker = UpdateCooldownTracker(pluginsPath.resolve(".last-updates"))

suspend fun start() {
Expand Down Expand Up @@ -48,12 +48,15 @@ object PluginUpdater {
println("$LOG_PREFIX (Updater) Update check completed in ${duration}ms")
}


private val assetMappings = mapOf("surf-paper-paper" to "surf-api-paper")

private suspend fun checkAndUpdate(plugin: UpdatablePlugin) = withContext(Dispatchers.IO) {
if (cooldownTracker.isOnCooldown(plugin.name)) {
return@withContext
}

val release = gitHubClient.fetchLatestRelease(plugin)
val release = gitHubClient.fetchLatestRelease(plugin.latestReleaseUrl)
val latestVersion = release?.get("tag_name")?.toString()?.trimStart('v')

if (latestVersion == null) {
Expand All @@ -70,7 +73,7 @@ object PluginUpdater {
@Suppress("UNCHECKED_CAST")
val assets = release["assets"] as? List<Map<String, Any>> ?: return@withContext

val expectedPrefix = buildString {
val buildedPrefix = buildString {
append("surf-")
append(plugin.findPluginName(false))

Expand All @@ -80,13 +83,15 @@ object PluginUpdater {
}
}

val mappedPrefix = assetMappings[buildedPrefix] ?: buildedPrefix

val matchingAsset = assets.firstOrNull { asset ->
val assetName = asset["name"]?.toString() ?: return@firstOrNull false

assetName.endsWith(".jar") &&
assetName.startsWith(expectedPrefix)
assetName.startsWith(mappedPrefix)
} ?: run {
println("$LOG_PREFIX (Updater) No matching asset found for ${plugin.name}: $expectedPrefix in release $latestVersion")
println("$LOG_PREFIX (Updater) No matching asset found for ${plugin.name}: $mappedPrefix in release $latestVersion")
return@withContext
}

Expand Down