From 435beae3831fc8ce161aec676ff20f253b1caf66 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 15 Jul 2024 01:52:16 +0200 Subject: [PATCH 1/4] fix: Don't encode public keys & instead send them raw --- .../api/configuration/services/PatchesService.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 618fc335..a1e7608c 100644 --- a/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt +++ b/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt @@ -7,7 +7,6 @@ import app.revanced.api.configuration.schema.* import app.revanced.library.PatchUtils import app.revanced.patcher.PatchBundleLoader import com.github.benmanes.caffeine.cache.Caffeine -import io.ktor.util.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.ByteArrayOutputStream @@ -113,12 +112,13 @@ internal class PatchesService( } fun publicKeys(): APIAssetPublicKeys { - fun publicKeyBase64(getSignedAssetConfiguration: ConfigurationRepository.() -> ConfigurationRepository.SignedAssetConfiguration) = - configurationRepository.getSignedAssetConfiguration().publicKeyFile.readBytes().encodeBase64() + fun readPublicKey( + getSignedAssetConfiguration: ConfigurationRepository.() -> ConfigurationRepository.SignedAssetConfiguration, + ) = configurationRepository.getSignedAssetConfiguration().publicKeyFile.readText() return APIAssetPublicKeys( - publicKeyBase64 { patches }, - publicKeyBase64 { integrations }, + readPublicKey { patches }, + readPublicKey { integrations }, ) } } From 39d0b78c7919f684439b6f052ab3f064159c2a70 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 15 Jul 2024 02:30:21 +0200 Subject: [PATCH 2/4] feat: Add static file paths to remove env specific files in resources --- .gitignore | 3 +- configuration.example.toml | 2 + docker-compose.example.yml | 1 + .../revanced/api/configuration/Extensions.kt | 15 ++++ .../app/revanced/api/configuration/Routing.kt | 7 +- .../repository/ConfigurationRepository.kt | 17 ++++ .../api/configuration/routes/ApiRoute.kt | 7 +- .../api/configuration/services/ApiService.kt | 2 + .../app/revanced/api/static/root/robots.txt | 2 - .../revanced/api/static/versioned/about.json | 83 ------------------- 10 files changed, 42 insertions(+), 97 deletions(-) delete mode 100644 src/main/resources/app/revanced/api/static/root/robots.txt delete mode 100644 src/main/resources/app/revanced/api/static/versioned/about.json diff --git a/.gitignore b/.gitignore index 674971bb..39008635 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ configuration.toml docker-compose.yml patches-public-key.asc integrations-public-key.asc -node_modules/ \ No newline at end of file +node_modules/ +static/ \ No newline at end of file diff --git a/configuration.example.toml b/configuration.example.toml index 0ad3059d..c380e156 100644 --- a/configuration.example.toml +++ b/configuration.example.toml @@ -17,3 +17,5 @@ cors-allowed-hosts = [ ] endpoint = "https://api.revanced.app" old-api-endpoint = "https://old-api.revanced.app" +static-files-path = "static/root" +versioned-static-files-path = "static/versioned" \ No newline at end of file diff --git a/docker-compose.example.yml b/docker-compose.example.yml index a82e58e8..49b9d546 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -8,6 +8,7 @@ services: - /data/revanced-api/configuration.toml:/app/configuration.toml - /data/revanced-api/patches-public-key.asc:/app/patches-public-key.asc - /data/revanced-api/integrations-public-key.asc:/app/integrations-public-key.asc + - /data/revanced-api/static:/app/static environment: - COMMAND=start ports: diff --git a/src/main/kotlin/app/revanced/api/configuration/Extensions.kt b/src/main/kotlin/app/revanced/api/configuration/Extensions.kt index d7546939..4d387216 100644 --- a/src/main/kotlin/app/revanced/api/configuration/Extensions.kt +++ b/src/main/kotlin/app/revanced/api/configuration/Extensions.kt @@ -4,8 +4,12 @@ import io.bkbn.kompendium.core.plugin.NotarizedRoute import io.ktor.http.* import io.ktor.http.content.* import io.ktor.server.application.* +import io.ktor.server.http.content.* import io.ktor.server.plugins.cachingheaders.* import io.ktor.server.response.* +import io.ktor.server.routing.* +import java.io.File +import java.nio.file.Path import kotlin.time.Duration internal suspend fun ApplicationCall.respondOrNotFound(value: Any?) = respond(value ?: HttpStatusCode.NotFound) @@ -25,3 +29,14 @@ internal fun ApplicationCallPipeline.installCache(cacheControl: CacheControl) = internal fun ApplicationCallPipeline.installNotarizedRoute(configure: NotarizedRoute.Config.() -> Unit = {}) = install(NotarizedRoute(), configure) + +internal fun Route.staticFiles( + remotePath: String, + dir: Path, + block: StaticContentConfig.() -> Unit = { + contentType { + ContentType.Application.Json + } + extensions("json") + }, +) = staticFiles(remotePath, dir.toFile(), null, block) diff --git a/src/main/kotlin/app/revanced/api/configuration/Routing.kt b/src/main/kotlin/app/revanced/api/configuration/Routing.kt index fe60ebc0..91018a97 100644 --- a/src/main/kotlin/app/revanced/api/configuration/Routing.kt +++ b/src/main/kotlin/app/revanced/api/configuration/Routing.kt @@ -8,9 +8,7 @@ import app.revanced.api.configuration.routes.oldApiRoute import app.revanced.api.configuration.routes.patchesRoute import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.swagger -import io.ktor.http.* import io.ktor.server.application.* -import io.ktor.server.http.content.* import io.ktor.server.routing.* import kotlin.time.Duration.Companion.minutes import org.koin.ktor.ext.get as koinGet @@ -27,10 +25,7 @@ internal fun Application.configureRouting() = routing { apiRoute() } - staticResources("/", "/app/revanced/api/static/root") { - contentType { ContentType.Application.Json } - extensions("json") - } + staticFiles("/", configuration.staticFilesPath) swagger(pageTitle = "ReVanced API", path = "/") redoc(pageTitle = "ReVanced API", path = "/redoc") diff --git a/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt b/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt index 4e13cf64..6325b3cc 100644 --- a/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt +++ b/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt @@ -11,6 +11,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import java.io.File +import java.nio.file.Path /** * The repository storing the configuration for the API. @@ -24,6 +25,8 @@ import java.io.File * @property corsAllowedHosts The hosts allowed to make requests to the API. * @property endpoint The endpoint of the API. * @property oldApiEndpoint The endpoint of the old API to proxy requests to. + * @property staticFilesPath The path to the static files to be served under the root path. + * @property versionedStaticFilesPath The path to the static files to be served under a versioned path. */ @Serializable internal class ConfigurationRepository( @@ -40,6 +43,12 @@ internal class ConfigurationRepository( val endpoint: String, @SerialName("old-api-endpoint") val oldApiEndpoint: String, + @Serializable(with = PathSerializer::class) + @SerialName("static-files-path") + val staticFilesPath: Path, + @Serializable(with = PathSerializer::class) + @SerialName("versioned-static-files-path") + val versionedStaticFilesPath: Path, ) { /** * Am asset configuration whose asset is signed. @@ -108,3 +117,11 @@ private object FileSerializer : KSerializer { override fun deserialize(decoder: Decoder) = File(decoder.decodeString()) } + +private object PathSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Path", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: Path) = encoder.encodeString(value.toString()) + + override fun deserialize(decoder: Decoder) = Path.of(decoder.decodeString()) +} diff --git a/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt b/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt index 5152d654..7c6c5809 100644 --- a/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt +++ b/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt @@ -1,5 +1,6 @@ package app.revanced.api.configuration.routes +import app.revanced.api.configuration.* import app.revanced.api.configuration.installCache import app.revanced.api.configuration.installNoCache import app.revanced.api.configuration.installNotarizedRoute @@ -13,7 +14,6 @@ import io.bkbn.kompendium.core.metadata.* import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.auth.* -import io.ktor.server.http.content.* import io.ktor.server.plugins.ratelimit.* import io.ktor.server.response.* import io.ktor.server.routing.* @@ -75,10 +75,7 @@ internal fun Route.apiRoute() { } } - staticResources("/", "/app/revanced/api/static/versioned") { - contentType { ContentType.Application.Json } - extensions("json") - } + staticFiles("/", apiService.versionedStaticFilesPath) } } diff --git a/src/main/kotlin/app/revanced/api/configuration/services/ApiService.kt b/src/main/kotlin/app/revanced/api/configuration/services/ApiService.kt index 0a73fff9..cac63e61 100644 --- a/src/main/kotlin/app/revanced/api/configuration/services/ApiService.kt +++ b/src/main/kotlin/app/revanced/api/configuration/services/ApiService.kt @@ -12,6 +12,8 @@ internal class ApiService( private val backendRepository: BackendRepository, private val configurationRepository: ConfigurationRepository, ) { + val versionedStaticFilesPath = configurationRepository.versionedStaticFilesPath + suspend fun contributors() = withContext(Dispatchers.IO) { configurationRepository.contributorsRepositoryNames.map { async { diff --git a/src/main/resources/app/revanced/api/static/root/robots.txt b/src/main/resources/app/revanced/api/static/root/robots.txt deleted file mode 100644 index 77470cb3..00000000 --- a/src/main/resources/app/revanced/api/static/root/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: / \ No newline at end of file diff --git a/src/main/resources/app/revanced/api/static/versioned/about.json b/src/main/resources/app/revanced/api/static/versioned/about.json deleted file mode 100644 index a947c48a..00000000 --- a/src/main/resources/app/revanced/api/static/versioned/about.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "ReVanced", - "about": "ReVanced was born out of Vanced's discontinuation and it is our goal to continue the legacy of what Vanced left behind. Thanks to ReVanced Patcher, it's possible to create long-lasting patches for nearly any Android app. ReVanced's patching system is designed to allow patches to work on new versions of the apps automatically with bare minimum maintenance.", - "branding": { - "logo": "https://raw.githubusercontent.com/ReVanced/revanced-branding/main/assets/revanced-logo/revanced-logo.svg" - }, - "contact": { - "email": "contact@revanced.app" - }, - "socials": [ - { - "name": "Website", - "url": "https://revanced.app", - "preferred": true - }, - { - "name": "GitHub", - "url": "https://github.com/revanced" - }, - { - "name": "Twitter", - "url": "https://twitter.com/revancedapp" - }, - { - "name": "Discord", - "url": "https://revanced.app/discord", - "preferred": true - }, - { - "name": "Reddit", - "url": "https://www.reddit.com/r/revancedapp" - }, - { - "name": "Telegram", - "url": "https://t.me/app_revanced" - }, - { - "name": "YouTube", - "url": "https://www.youtube.com/@ReVanced" - } - ], - "donations": { - "wallets": [ - { - "network": "Bitcoin", - "currency_code": "BTC", - "address": "bc1q4x8j6mt27y5gv0q625t8wkr87ruy8fprpy4v3f" - }, - { - "network": "Dogecoin", - "currency_code": "DOGE", - "address": "D8GH73rNjudgi6bS2krrXWEsU9KShedLXp", - "preferred": true - }, - { - "network": "Ethereum", - "currency_code": "ETH", - "address": "0x7ab4091e00363654bf84B34151225742cd92FCE5" - }, - { - "network": "Litecoin", - "currency_code": "LTC", - "address": "LbJi8EuoDcwaZvykcKmcrM74jpjde23qJ2" - }, - { - "network": "Monero", - "currency_code": "XMR", - "address": "46YwWDbZD6jVptuk5mLHsuAmh1BnUMSjSNYacozQQEraWSQ93nb2yYVRHoMR6PmFYWEHsLHg9tr1cH5M8Rtn7YaaGQPCjSh" - } - ], - "links": [ - { - "name": "Open Collective", - "url": "https://opencollective.com/revanced", - "preferred": true - }, - { - "name": "GitHub Sponsors", - "url": "https://github.com/sponsors/ReVanced" - } - ] - } -} From dfe6df3ef6006d06681673bcfaf87c44c40ad446 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 15 Jul 2024 03:12:39 +0200 Subject: [PATCH 3/4] feat: Convert static about file to documented route & add key parameter to about route --- .gitignore | 3 +- about.example.json | 84 +++++++++++++++++++ configuration.example.toml | 7 +- docker-compose.example.yml | 1 + .../app/revanced/api/configuration/Routing.kt | 28 ++++++- .../repository/ConfigurationRepository.kt | 24 +++++- .../api/configuration/routes/ApiRoute.kt | 26 ++++++ .../api/configuration/schema/APISchema.kt | 52 ++++++++++++ .../api/configuration/services/ApiService.kt | 1 + 9 files changed, 220 insertions(+), 6 deletions(-) create mode 100644 about.example.json diff --git a/.gitignore b/.gitignore index 39008635..d376259d 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,5 @@ docker-compose.yml patches-public-key.asc integrations-public-key.asc node_modules/ -static/ \ No newline at end of file +static/ +about.json \ No newline at end of file diff --git a/about.example.json b/about.example.json new file mode 100644 index 00000000..f452fe48 --- /dev/null +++ b/about.example.json @@ -0,0 +1,84 @@ +{ + "name": "ReVanced", + "about": "ReVanced was born out of Vanced's discontinuation and it is our goal to continue the legacy of what Vanced left behind. Thanks to ReVanced Patcher, it's possible to create long-lasting patches for nearly any Android app. ReVanced's patching system is designed to allow patches to work on new versions of the apps automatically with bare minimum maintenance.", + "keys": "https://api.revanced.app/keys", + "branding": { + "logo": "https://raw.githubusercontent.com/ReVanced/revanced-branding/main/assets/revanced-logo/revanced-logo.svg" + }, + "contact": { + "email": "contact@revanced.app" + }, + "socials": [ + { + "name": "Website", + "url": "https://revanced.app", + "preferred": true + }, + { + "name": "GitHub", + "url": "https://github.com/revanced" + }, + { + "name": "Twitter", + "url": "https://twitter.com/revancedapp" + }, + { + "name": "Discord", + "url": "https://revanced.app/discord", + "preferred": true + }, + { + "name": "Reddit", + "url": "https://www.reddit.com/r/revancedapp" + }, + { + "name": "Telegram", + "url": "https://t.me/app_revanced" + }, + { + "name": "YouTube", + "url": "https://www.youtube.com/@ReVanced" + } + ], + "donations": { + "wallets": [ + { + "network": "Bitcoin", + "currency_code": "BTC", + "address": "bc1q4x8j6mt27y5gv0q625t8wkr87ruy8fprpy4v3f" + }, + { + "network": "Dogecoin", + "currency_code": "DOGE", + "address": "D8GH73rNjudgi6bS2krrXWEsU9KShedLXp", + "preferred": true + }, + { + "network": "Ethereum", + "currency_code": "ETH", + "address": "0x7ab4091e00363654bf84B34151225742cd92FCE5" + }, + { + "network": "Litecoin", + "currency_code": "LTC", + "address": "LbJi8EuoDcwaZvykcKmcrM74jpjde23qJ2" + }, + { + "network": "Monero", + "currency_code": "XMR", + "address": "46YwWDbZD6jVptuk5mLHsuAmh1BnUMSjSNYacozQQEraWSQ93nb2yYVRHoMR6PmFYWEHsLHg9tr1cH5M8Rtn7YaaGQPCjSh" + } + ], + "links": [ + { + "name": "Open Collective", + "url": "https://opencollective.com/revanced", + "preferred": true + }, + { + "name": "GitHub Sponsors", + "url": "https://github.com/sponsors/ReVanced" + } + ] + } +} diff --git a/configuration.example.toml b/configuration.example.toml index c380e156..fec352cc 100644 --- a/configuration.example.toml +++ b/configuration.example.toml @@ -1,6 +1,6 @@ organization = "revanced" -patches = { repository = "revanced-patches", asset-regex = "jar$", signature-asset-regex = "asc$", public-key-file = "patches-public-key.asc" } -integrations = { repository = "revanced-integrations", asset-regex = "apk$", signature-asset-regex = "asc$", public-key-file = "integrations-public-key.asc" } +patches = { repository = "revanced-patches", asset-regex = "jar$", signature-asset-regex = "asc$", public-key-file = "patches-public-key.asc", public-key-id = 0 } +integrations = { repository = "revanced-integrations", asset-regex = "apk$", signature-asset-regex = "asc$", public-key-file = "integrations-public-key.asc", public-key-id = 0 } manager = { repository = "revanced-manager", asset-regex = "apk$" } contributors-repositories = [ "revanced-patcher", @@ -18,4 +18,5 @@ cors-allowed-hosts = [ endpoint = "https://api.revanced.app" old-api-endpoint = "https://old-api.revanced.app" static-files-path = "static/root" -versioned-static-files-path = "static/versioned" \ No newline at end of file +versioned-static-files-path = "static/versioned" +about-json-file-path = "about.json" diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 49b9d546..8034e332 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -9,6 +9,7 @@ services: - /data/revanced-api/patches-public-key.asc:/app/patches-public-key.asc - /data/revanced-api/integrations-public-key.asc:/app/integrations-public-key.asc - /data/revanced-api/static:/app/static + - /data/revanced-api/about.json:/app/about.json environment: - COMMAND=start ports: diff --git a/src/main/kotlin/app/revanced/api/configuration/Routing.kt b/src/main/kotlin/app/revanced/api/configuration/Routing.kt index 91018a97..1e0f4679 100644 --- a/src/main/kotlin/app/revanced/api/configuration/Routing.kt +++ b/src/main/kotlin/app/revanced/api/configuration/Routing.kt @@ -8,6 +8,7 @@ import app.revanced.api.configuration.routes.oldApiRoute import app.revanced.api.configuration.routes.patchesRoute import io.bkbn.kompendium.core.routes.redoc import io.bkbn.kompendium.core.routes.swagger +import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.routing.* import kotlin.time.Duration.Companion.minutes @@ -25,7 +26,32 @@ internal fun Application.configureRouting() = routing { apiRoute() } - staticFiles("/", configuration.staticFilesPath) + staticFiles("/", configuration.staticFilesPath) { + contentType { + when (it.extension) { + "json" -> ContentType.Application.Json + "asc" -> ContentType.Text.Plain + "ico" -> ContentType.Image.XIcon + "svg" -> ContentType.Image.SVG + "jpg", "jpeg" -> ContentType.Image.JPEG + "png" -> ContentType.Image.PNG + "gif" -> ContentType.Image.GIF + "mp4" -> ContentType.Video.MP4 + "ogg" -> ContentType.Video.OGG + "mp3" -> ContentType.Audio.MPEG + "css" -> ContentType.Text.CSS + "js" -> ContentType.Application.JavaScript + "html" -> ContentType.Text.Html + "xml" -> ContentType.Application.Xml + "pdf" -> ContentType.Application.Pdf + "zip" -> ContentType.Application.Zip + "gz" -> ContentType.Application.GZip + else -> ContentType.Application.OctetStream + } + } + + extensions("json", "asc") + } swagger(pageTitle = "ReVanced API", path = "/") redoc(pageTitle = "ReVanced API", path = "/redoc") diff --git a/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt b/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt index 6325b3cc..22a654e5 100644 --- a/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt +++ b/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt @@ -1,7 +1,9 @@ package app.revanced.api.configuration.repository +import app.revanced.api.configuration.schema.APIAbout import app.revanced.api.configuration.services.ManagerService import app.revanced.api.configuration.services.PatchesService +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -10,6 +12,9 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonNamingStrategy +import kotlinx.serialization.json.decodeFromStream import java.io.File import java.nio.file.Path @@ -27,6 +32,8 @@ import java.nio.file.Path * @property oldApiEndpoint The endpoint of the old API to proxy requests to. * @property staticFilesPath The path to the static files to be served under the root path. * @property versionedStaticFilesPath The path to the static files to be served under a versioned path. + * @property about The path to the json file deserialized to [APIAbout] + * (because com.akuleshov7.ktoml.Toml does not support nested tables). */ @Serializable internal class ConfigurationRepository( @@ -49,6 +56,9 @@ internal class ConfigurationRepository( @Serializable(with = PathSerializer::class) @SerialName("versioned-static-files-path") val versionedStaticFilesPath: Path, + @Serializable(with = AboutSerializer::class) + @SerialName("about-json-file-path") + val about: APIAbout, ) { /** * Am asset configuration whose asset is signed. @@ -123,5 +133,17 @@ private object PathSerializer : KSerializer { override fun serialize(encoder: Encoder, value: Path) = encoder.encodeString(value.toString()) - override fun deserialize(decoder: Decoder) = Path.of(decoder.decodeString()) + override fun deserialize(decoder: Decoder): Path = Path.of(decoder.decodeString()) +} + +private object AboutSerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("APIAbout", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: APIAbout) = error("Serializing APIAbout is not supported") + + @OptIn(ExperimentalSerializationApi::class) + val json = Json { namingStrategy = JsonNamingStrategy.SnakeCase } + + override fun deserialize(decoder: Decoder): APIAbout = + json.decodeFromStream(File(decoder.decodeString()).inputStream()) } diff --git a/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt b/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt index 7c6c5809..834f8573 100644 --- a/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt +++ b/src/main/kotlin/app/revanced/api/configuration/routes/ApiRoute.kt @@ -5,6 +5,7 @@ import app.revanced.api.configuration.installCache import app.revanced.api.configuration.installNoCache import app.revanced.api.configuration.installNotarizedRoute import app.revanced.api.configuration.respondOrNotFound +import app.revanced.api.configuration.schema.APIAbout import app.revanced.api.configuration.schema.APIContributable import app.revanced.api.configuration.schema.APIMember import app.revanced.api.configuration.schema.APIRateLimit @@ -56,6 +57,16 @@ internal fun Route.apiRoute() { } } + route("about") { + installCache(1.days) + + installAboutRouteDocumentation() + + get { + call.respond(apiService.about) + } + } + route("ping") { installNoCache() @@ -79,6 +90,21 @@ internal fun Route.apiRoute() { } } +private fun Route.installAboutRouteDocumentation() = installNotarizedRoute { + tags = setOf("API") + + get = GetInfo.builder { + description("Get information about the API") + summary("Get about") + response { + description("Information about the API") + mediaTypes("application/json") + responseCode(HttpStatusCode.OK) + responseType() + } + } +} + private fun Route.installRateLimitRouteDocumentation() = installNotarizedRoute { tags = setOf("API") diff --git a/src/main/kotlin/app/revanced/api/configuration/schema/APISchema.kt b/src/main/kotlin/app/revanced/api/configuration/schema/APISchema.kt index d6d28ef3..b48af9af 100644 --- a/src/main/kotlin/app/revanced/api/configuration/schema/APISchema.kt +++ b/src/main/kotlin/app/revanced/api/configuration/schema/APISchema.kt @@ -120,3 +120,55 @@ class APIAssetPublicKeys( val patchesPublicKey: String, val integrationsPublicKey: String, ) + +@Serializable +class APIAbout( + val name: String, + val about: String, + val keys: String, + val branding: Branding?, + val contact: Contact?, + // Using a list instead of a set because set semantics are unnecessary here. + val socials: List?, + val donations: Donations?, +) { + @Serializable + class Branding( + val logo: String, + ) + + @Serializable + class Contact( + val email: String, + ) + + @Serializable + class Social( + val name: String, + val url: String, + val preferred: Boolean? = false, + ) + + @Serializable + class Wallet( + val network: String, + val currencyCode: String, + val address: String, + val preferred: Boolean? = false, + ) + + @Serializable + class Link( + val name: String, + val url: String, + val preferred: Boolean? = false, + ) + + @Serializable + class Donations( + // Using a list instead of a set because set semantics are unnecessary here. + val wallets: List?, + // Using a list instead of a set because set semantics are unnecessary here. + val links: List?, + ) +} diff --git a/src/main/kotlin/app/revanced/api/configuration/services/ApiService.kt b/src/main/kotlin/app/revanced/api/configuration/services/ApiService.kt index cac63e61..5dc9f432 100644 --- a/src/main/kotlin/app/revanced/api/configuration/services/ApiService.kt +++ b/src/main/kotlin/app/revanced/api/configuration/services/ApiService.kt @@ -13,6 +13,7 @@ internal class ApiService( private val configurationRepository: ConfigurationRepository, ) { val versionedStaticFilesPath = configurationRepository.versionedStaticFilesPath + val about = configurationRepository.about suspend fun contributors() = withContext(Dispatchers.IO) { configurationRepository.contributorsRepositoryNames.map { From 665de7bcd02bed0a001f19603d793879e2ea3209 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 15 Jul 2024 01:15:03 +0000 Subject: [PATCH 4/4] chore(release): 1.1.0-dev.1 [skip ci] # [1.1.0-dev.1](https://github.com/ReVanced/revanced-api/compare/v1.0.0...v1.1.0-dev.1) (2024-07-15) ### Bug Fixes * Don't encode public keys & instead send them raw ([435beae](https://github.com/ReVanced/revanced-api/commit/435beae3831fc8ce161aec676ff20f253b1caf66)) ### Features * Add static file paths to remove env specific files in resources ([39d0b78](https://github.com/ReVanced/revanced-api/commit/39d0b78c7919f684439b6f052ab3f064159c2a70)) * Convert static about file to documented route & add key parameter to about route ([dfe6df3](https://github.com/ReVanced/revanced-api/commit/dfe6df3ef6006d06681673bcfaf87c44c40ad446)) --- CHANGELOG.md | 13 +++++++++++++ gradle.properties | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4760a0e..145adc5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# [1.1.0-dev.1](https://github.com/ReVanced/revanced-api/compare/v1.0.0...v1.1.0-dev.1) (2024-07-15) + + +### Bug Fixes + +* Don't encode public keys & instead send them raw ([435beae](https://github.com/ReVanced/revanced-api/commit/435beae3831fc8ce161aec676ff20f253b1caf66)) + + +### Features + +* Add static file paths to remove env specific files in resources ([39d0b78](https://github.com/ReVanced/revanced-api/commit/39d0b78c7919f684439b6f052ab3f064159c2a70)) +* Convert static about file to documented route & add key parameter to about route ([dfe6df3](https://github.com/ReVanced/revanced-api/commit/dfe6df3ef6006d06681673bcfaf87c44c40ad446)) + # 1.0.0 (2024-07-13) diff --git a/gradle.properties b/gradle.properties index 0cfc02d1..7b01b069 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true kotlin.code.style = official -version = 1.0.0 +version = 1.1.0-dev.1