diff --git a/src/main/kotlin/app/revanced/api/configuration/repository/BackendRepository.kt b/src/main/kotlin/app/revanced/api/configuration/repository/BackendRepository.kt index 85d10bb..6bf6d52 100644 --- a/src/main/kotlin/app/revanced/api/configuration/repository/BackendRepository.kt +++ b/src/main/kotlin/app/revanced/api/configuration/repository/BackendRepository.kt @@ -135,12 +135,14 @@ abstract class BackendRepository internal constructor( * @property tag The tag of the release. * @property assets The assets of the release. * @property createdAt The date and time the release was created. + * @property prerelease Whether the release is a prerelease. * @property releaseNote The release note of the release. */ class BackendRelease( val tag: String, val releaseNote: String, val createdAt: LocalDateTime, + val prerelease: Boolean, // Using a list instead of a set because set semantics are unnecessary here. val assets: List, ) { @@ -180,13 +182,13 @@ abstract class BackendRepository internal constructor( * * @param owner The owner of the repository. * @param repository The name of the repository. - * @param tag The tag of the release. If null, the latest release is returned. + * @param prerelease Whether to get a prerelease. * @return The release. */ abstract suspend fun release( owner: String, repository: String, - tag: String? = null, + prerelease: Boolean, ): BackendOrganization.BackendRepository.BackendRelease /** diff --git a/src/main/kotlin/app/revanced/api/configuration/repository/GitHubBackendRepository.kt b/src/main/kotlin/app/revanced/api/configuration/repository/GitHubBackendRepository.kt index 420ccaf..0afe8d1 100644 --- a/src/main/kotlin/app/revanced/api/configuration/repository/GitHubBackendRepository.kt +++ b/src/main/kotlin/app/revanced/api/configuration/repository/GitHubBackendRepository.kt @@ -24,10 +24,10 @@ class GitHubBackendRepository : BackendRepository("https://api.github.com", "htt override suspend fun release( owner: String, repository: String, - tag: String?, + prerelease: Boolean, ): BackendRelease { - val release: GitHubRelease = if (tag != null) { - client.get(Releases.Tag(owner, repository, tag)).body() + val release: GitHubRelease = if (prerelease) { + client.get(Releases(owner, repository)).body>().first { it.prerelease } } else { client.get(Releases.Latest(owner, repository)).body() } @@ -36,6 +36,7 @@ class GitHubBackendRepository : BackendRepository("https://api.github.com", "htt tag = release.tagName, releaseNote = release.body, createdAt = release.createdAt.toLocalDateTime(TimeZone.UTC), + prerelease = release.prerelease, assets = release.assets.map { BackendAsset( name = it.name, @@ -163,6 +164,7 @@ class GitHubOrganization { // Using a list instead of a set because set semantics are unnecessary here. val assets: List, val createdAt: Instant, + val prerelease: Boolean, val body: String, ) { @Serializable @@ -200,10 +202,8 @@ class Organization { @Resource("/repos/{owner}/{repo}/contributors") class Contributors(val owner: String, val repo: String, @SerialName("per_page") val perPage: Int = 100) - class Releases { - @Resource("/repos/{owner}/{repo}/releases/tags/{tag}") - class Tag(val owner: String, val repo: String, val tag: String) - + @Resource("/repos/{owner}/{repo}/releases") + class Releases(val owner: String, val repo: String) { @Resource("/repos/{owner}/{repo}/releases/latest") class Latest(val owner: String, val repo: String) } diff --git a/src/main/kotlin/app/revanced/api/configuration/routes/ManagerRoute.kt b/src/main/kotlin/app/revanced/api/configuration/routes/ManagerRoute.kt index c82c0fb..e3ef9c9 100644 --- a/src/main/kotlin/app/revanced/api/configuration/routes/ManagerRoute.kt +++ b/src/main/kotlin/app/revanced/api/configuration/routes/ManagerRoute.kt @@ -5,6 +5,8 @@ import app.revanced.api.configuration.ApiReleaseVersion import app.revanced.api.configuration.installNotarizedRoute import app.revanced.api.configuration.services.ManagerService import io.bkbn.kompendium.core.metadata.GetInfo +import io.bkbn.kompendium.json.schema.definition.TypeDefinition +import io.bkbn.kompendium.oas.payload.Parameter import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.plugins.ratelimit.* @@ -19,25 +21,38 @@ internal fun Route.managerRoute() = route("manager") { rateLimit(RateLimitName("weak")) { get { - call.respond(managerService.latestRelease()) + val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false + + call.respond(managerService.latestRelease(prerelease)) } route("version") { installManagerVersionRouteDocumentation() get { - call.respond(managerService.latestVersion()) + val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false + + call.respond(managerService.latestVersion(prerelease)) } } } } +private val prereleaseParameter = Parameter( + name = "prerelease", + `in` = Parameter.Location.query, + schema = TypeDefinition.STRING, + description = "Whether to get the current manager prerelease", + required = false, +) + private fun Route.installManagerRouteDocumentation() = installNotarizedRoute { tags = setOf("Manager") get = GetInfo.builder { description("Get the current manager release") summary("Get current manager release") + parameters(prereleaseParameter) response { description("The latest manager release") mediaTypes("application/json") @@ -53,6 +68,7 @@ private fun Route.installManagerVersionRouteDocumentation() = installNotarizedRo get = GetInfo.builder { description("Get the current manager release version") summary("Get current manager release version") + parameters(prereleaseParameter) response { description("The current manager release version") mediaTypes("application/json") diff --git a/src/main/kotlin/app/revanced/api/configuration/routes/PatchesRoute.kt b/src/main/kotlin/app/revanced/api/configuration/routes/PatchesRoute.kt index 9672d9e..9c5b5b5 100644 --- a/src/main/kotlin/app/revanced/api/configuration/routes/PatchesRoute.kt +++ b/src/main/kotlin/app/revanced/api/configuration/routes/PatchesRoute.kt @@ -7,6 +7,8 @@ import app.revanced.api.configuration.installCache import app.revanced.api.configuration.installNotarizedRoute import app.revanced.api.configuration.services.PatchesService import io.bkbn.kompendium.core.metadata.GetInfo +import io.bkbn.kompendium.json.schema.definition.TypeDefinition +import io.bkbn.kompendium.oas.payload.Parameter import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.plugins.ratelimit.* @@ -22,14 +24,18 @@ internal fun Route.patchesRoute() = route("patches") { rateLimit(RateLimitName("weak")) { get { - call.respond(patchesService.latestRelease()) + val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false + + call.respond(patchesService.latestRelease(prerelease)) } route("version") { installPatchesVersionRouteDocumentation() get { - call.respond(patchesService.latestVersion()) + val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false + + call.respond(patchesService.latestVersion(prerelease)) } } } @@ -39,7 +45,9 @@ internal fun Route.patchesRoute() = route("patches") { installPatchesListRouteDocumentation() get { - call.respondBytes(ContentType.Application.Json) { patchesService.list() } + val prerelease = call.parameters["prerelease"]?.toBoolean() ?: false + + call.respondBytes(ContentType.Application.Json) { patchesService.list(prerelease) } } } } @@ -57,12 +65,21 @@ internal fun Route.patchesRoute() = route("patches") { } } +private val prereleaseParameter = Parameter( + name = "prerelease", + `in` = Parameter.Location.query, + schema = TypeDefinition.STRING, + description = "Whether to get the current patches prerelease", + required = false, +) + private fun Route.installPatchesRouteDocumentation() = installNotarizedRoute { tags = setOf("Patches") get = GetInfo.builder { description("Get the current patches release") summary("Get current patches release") + parameters(prereleaseParameter) response { description("The current patches release") mediaTypes("application/json") @@ -78,6 +95,7 @@ private fun Route.installPatchesVersionRouteDocumentation() = installNotarizedRo get = GetInfo.builder { description("Get the current patches release version") summary("Get current patches release version") + parameters(prereleaseParameter) response { description("The current patches release version") mediaTypes("application/json") @@ -93,6 +111,7 @@ private fun Route.installPatchesListRouteDocumentation() = installNotarizedRoute get = GetInfo.builder { description("Get the list of patches from the current patches release") summary("Get list of patches from current patches release") + parameters(prereleaseParameter) response { description("The list of patches") mediaTypes("application/json") diff --git a/src/main/kotlin/app/revanced/api/configuration/services/ManagerService.kt b/src/main/kotlin/app/revanced/api/configuration/services/ManagerService.kt index af53621..2bf0703 100644 --- a/src/main/kotlin/app/revanced/api/configuration/services/ManagerService.kt +++ b/src/main/kotlin/app/revanced/api/configuration/services/ManagerService.kt @@ -10,10 +10,11 @@ internal class ManagerService( private val backendRepository: BackendRepository, private val configurationRepository: ConfigurationRepository, ) { - suspend fun latestRelease(): ApiRelease { + suspend fun latestRelease(prerelease: Boolean): ApiRelease { val managerRelease = backendRepository.release( configurationRepository.organization, configurationRepository.manager.repository, + prerelease, ) return ApiRelease( @@ -24,10 +25,11 @@ internal class ManagerService( ) } - suspend fun latestVersion(): ApiReleaseVersion { + suspend fun latestVersion(prerelease: Boolean): ApiReleaseVersion { val managerRelease = backendRepository.release( configurationRepository.organization, configurationRepository.manager.repository, + prerelease, ) return ApiReleaseVersion(managerRelease.tag) diff --git a/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt b/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt index b9d3608..563509a 100644 --- a/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt +++ b/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt @@ -19,10 +19,11 @@ internal class PatchesService( private val backendRepository: BackendRepository, private val configurationRepository: ConfigurationRepository, ) { - suspend fun latestRelease(): ApiRelease { + suspend fun latestRelease(prerelease: Boolean): ApiRelease { val patchesRelease = backendRepository.release( configurationRepository.organization, configurationRepository.patches.repository, + prerelease, ) return ApiRelease( @@ -34,10 +35,11 @@ internal class PatchesService( ) } - suspend fun latestVersion(): ApiReleaseVersion { + suspend fun latestVersion(prerelease: Boolean): ApiReleaseVersion { val patchesRelease = backendRepository.release( configurationRepository.organization, configurationRepository.patches.repository, + prerelease, ) return ApiReleaseVersion(patchesRelease.tag) @@ -48,10 +50,11 @@ internal class PatchesService( .maximumSize(1) .build() - suspend fun list(): ByteArray { + suspend fun list(prerelease: Boolean): ByteArray { val patchesRelease = backendRepository.release( configurationRepository.organization, configurationRepository.patches.repository, + prerelease, ) return withContext(Dispatchers.IO) { diff --git a/src/main/kotlin/app/revanced/api/configuration/services/SignatureService.kt b/src/main/kotlin/app/revanced/api/configuration/services/SignatureService.kt index fc69005..9f65109 100644 --- a/src/main/kotlin/app/revanced/api/configuration/services/SignatureService.kt +++ b/src/main/kotlin/app/revanced/api/configuration/services/SignatureService.kt @@ -12,7 +12,7 @@ import java.security.MessageDigest internal class SignatureService { private val signatureCache = Caffeine .newBuilder() - .maximumSize(1) // 1 because currently only the latest patches is needed. + .maximumSize(2) // 2 because currently only the latest release and prerelease patches are needed. .build() // Hash -> Verified. fun verify(