package app.revanced.api.configuration import app.revanced.api.configuration.repository.AnnouncementRepository import app.revanced.api.configuration.repository.BackendRepository import app.revanced.api.configuration.repository.ConfigurationRepository import app.revanced.api.configuration.repository.GitHubBackendRepository import app.revanced.api.configuration.services.* import app.revanced.api.configuration.services.AnnouncementService import app.revanced.api.configuration.services.ApiService import app.revanced.api.configuration.services.AuthService import app.revanced.api.configuration.services.OldApiService import app.revanced.api.configuration.services.PatchesService import com.akuleshov7.ktoml.Toml import com.akuleshov7.ktoml.source.decodeFromStream import io.github.cdimascio.dotenv.Dotenv import io.ktor.client.* import io.ktor.client.engine.okhttp.* import io.ktor.client.plugins.* import io.ktor.client.plugins.auth.* import io.ktor.client.plugins.auth.providers.* import io.ktor.client.plugins.cache.* import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.plugins.resources.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonNamingStrategy import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.transactions.TransactionManager import org.koin.core.module.dsl.singleOf import org.koin.core.parameter.parameterArrayOf import org.koin.dsl.module import org.koin.ktor.plugin.Koin import java.io.File @OptIn(ExperimentalSerializationApi::class) fun Application.configureDependencies( configFile: File, ) { val globalModule = module { single { Dotenv.configure().load() } factory { params -> val defaultRequestUri: String = params.get() val configBlock = params.getOrNull<(HttpClientConfig.() -> Unit)>() ?: {} HttpClient(OkHttp) { defaultRequest { url(defaultRequestUri) } configBlock() } } } val repositoryModule = module { single { GitHubBackendRepository( get { val defaultRequestUri = "https://api.github.com" val configBlock: HttpClientConfig.() -> Unit = { install(HttpCache) install(Resources) install(ContentNegotiation) { json( Json { ignoreUnknownKeys = true namingStrategy = JsonNamingStrategy.SnakeCase }, ) } get()["BACKEND_API_TOKEN"]?.let { install(Auth) { bearer { loadTokens { BearerTokens( accessToken = it, refreshToken = "", // Required dummy value ) } sendWithoutRequest { true } } } } } parameterArrayOf(defaultRequestUri, configBlock) }, ) } single { Toml.decodeFromStream(configFile.inputStream()) } single { val dotenv = get() TransactionManager.defaultDatabase = Database.connect( url = dotenv["DB_URL"], user = dotenv["DB_USER"], password = dotenv["DB_PASSWORD"], ) AnnouncementRepository() } } val serviceModule = module { single { val dotenv = get() val jwtSecret = dotenv["JWT_SECRET"] val issuer = dotenv["JWT_ISSUER"] val validityInMin = dotenv["JWT_VALIDITY_IN_MIN"].toInt() val authSHA256DigestString = dotenv["AUTH_SHA256_DIGEST"] AuthService(issuer, validityInMin, jwtSecret, authSHA256DigestString) } single { OldApiService( get { val defaultRequestUri = get()["OLD_API_URL"] parameterArrayOf(defaultRequestUri) }, ) } singleOf(::AnnouncementService) singleOf(::SignatureService) singleOf(::PatchesService) singleOf(::ApiService) } install(Koin) { modules( globalModule, repositoryModule, serviceModule, ) } }