mirror of
https://github.com/ReVanced/revanced-api.git
synced 2026-01-29 22:21:04 +00:00
chore: Move files to correct folders
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
package app.revanced.api.configuration.services
|
||||
|
||||
import app.revanced.api.configuration.repository.AnnouncementRepository
|
||||
import app.revanced.api.configuration.schema.APIAnnouncement
|
||||
import app.revanced.api.configuration.schema.APILatestAnnouncement
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
|
||||
internal class AnnouncementService(
|
||||
private val announcementRepository: AnnouncementRepository,
|
||||
) {
|
||||
fun latestId(channel: String): APILatestAnnouncement? = announcementRepository.latestId(channel)
|
||||
fun latestId(): APILatestAnnouncement? = announcementRepository.latestId()
|
||||
|
||||
fun latest(channel: String) = announcementRepository.latest(channel)
|
||||
fun latest() = announcementRepository.latest()
|
||||
|
||||
fun all(channel: String) = announcementRepository.all(channel)
|
||||
fun all() = announcementRepository.all()
|
||||
|
||||
fun new(new: APIAnnouncement) {
|
||||
announcementRepository.new(new)
|
||||
}
|
||||
fun archive(id: Int, archivedAt: LocalDateTime?) {
|
||||
announcementRepository.archive(id, archivedAt)
|
||||
}
|
||||
fun unarchive(id: Int) {
|
||||
announcementRepository.unarchive(id)
|
||||
}
|
||||
fun update(id: Int, new: APIAnnouncement) {
|
||||
announcementRepository.update(id, new)
|
||||
}
|
||||
fun delete(id: Int) {
|
||||
announcementRepository.delete(id)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package app.revanced.api.configuration.services
|
||||
|
||||
import app.revanced.api.configuration.repository.ConfigurationRepository
|
||||
import app.revanced.api.configuration.repository.backend.BackendRepository
|
||||
import app.revanced.api.configuration.schema.APIContributable
|
||||
import app.revanced.api.configuration.schema.APIContributor
|
||||
import app.revanced.api.configuration.schema.APIMember
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
internal class ApiService(
|
||||
private val backendRepository: BackendRepository,
|
||||
private val configurationRepository: ConfigurationRepository,
|
||||
) {
|
||||
suspend fun contributors() = withContext(Dispatchers.IO) {
|
||||
configurationRepository.contributorsRepositoryNames.map {
|
||||
async {
|
||||
APIContributable(
|
||||
it,
|
||||
backendRepository.contributors(configurationRepository.organization, it).map {
|
||||
APIContributor(it.name, it.avatarUrl, it.url, it.contributions)
|
||||
}.toSet(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}.awaitAll()
|
||||
|
||||
suspend fun team() = backendRepository.members(configurationRepository.organization).map {
|
||||
APIMember(it.name, it.avatarUrl, it.url, it.gpgKeysUrl)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package app.revanced.api.configuration.services
|
||||
|
||||
import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.auth.jwt.*
|
||||
import java.util.*
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
internal class AuthService(
|
||||
private val issuer: String,
|
||||
private val validityInMin: Int,
|
||||
private val jwtSecret: String,
|
||||
private val basicUsername: String,
|
||||
private val basicPassword: String,
|
||||
) {
|
||||
val configureSecurity: Application.() -> Unit = {
|
||||
install(Authentication) {
|
||||
jwt("jwt") {
|
||||
verifier(
|
||||
JWT.require(Algorithm.HMAC256(jwtSecret))
|
||||
.withIssuer(issuer)
|
||||
.build(),
|
||||
)
|
||||
validate { credential -> JWTPrincipal(credential.payload) }
|
||||
}
|
||||
|
||||
basic("basic") {
|
||||
validate { credentials ->
|
||||
if (credentials.name == basicUsername && credentials.password == basicPassword) {
|
||||
UserIdPrincipal(credentials.name)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun newToken(): String = JWT.create()
|
||||
.withIssuer(issuer)
|
||||
.withExpiresAt(Date(System.currentTimeMillis() + validityInMin.minutes.inWholeMilliseconds))
|
||||
.sign(Algorithm.HMAC256(jwtSecret))
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package app.revanced.api.configuration.services
|
||||
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.http.content.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.util.*
|
||||
import io.ktor.utils.io.*
|
||||
|
||||
internal class OldApiService(private val client: HttpClient) {
|
||||
@OptIn(InternalAPI::class)
|
||||
suspend fun proxy(call: ApplicationCall) {
|
||||
val channel = call.request.receiveChannel()
|
||||
val size = channel.availableForRead
|
||||
val byteArray = ByteArray(size)
|
||||
channel.readFully(byteArray)
|
||||
|
||||
val response: HttpResponse = client.request(call.request.uri) {
|
||||
method = call.request.httpMethod
|
||||
|
||||
headers {
|
||||
appendAll(
|
||||
call.request.headers.filter { key, _ ->
|
||||
!key.equals(
|
||||
HttpHeaders.ContentType,
|
||||
ignoreCase = true,
|
||||
) &&
|
||||
!key.equals(
|
||||
HttpHeaders.ContentLength,
|
||||
ignoreCase = true,
|
||||
) &&
|
||||
!key.equals(HttpHeaders.Host, ignoreCase = true)
|
||||
},
|
||||
)
|
||||
}
|
||||
if (call.request.httpMethod == HttpMethod.Post) {
|
||||
body = ByteArrayContent(byteArray, call.request.contentType())
|
||||
}
|
||||
}
|
||||
|
||||
val headers = response.headers
|
||||
|
||||
call.respond(object : OutgoingContent.WriteChannelContent() {
|
||||
override val contentLength: Long? = headers[HttpHeaders.ContentLength]?.toLong()
|
||||
override val contentType = headers[HttpHeaders.ContentType]?.let { ContentType.parse(it) }
|
||||
override val headers: Headers = Headers.build {
|
||||
appendAll(
|
||||
headers.filter { key, _ ->
|
||||
!key.equals(
|
||||
HttpHeaders.ContentType,
|
||||
ignoreCase = true,
|
||||
) &&
|
||||
!key.equals(HttpHeaders.ContentLength, ignoreCase = true)
|
||||
},
|
||||
)
|
||||
}
|
||||
override val status = response.status
|
||||
|
||||
override suspend fun writeTo(channel: ByteWriteChannel) {
|
||||
response.content.copyAndClose(channel)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package app.revanced.api.configuration.services
|
||||
|
||||
import app.revanced.api.configuration.repository.ConfigurationRepository
|
||||
import app.revanced.api.configuration.repository.backend.BackendRepository
|
||||
import app.revanced.api.configuration.schema.APIAsset
|
||||
import app.revanced.api.configuration.schema.APIRelease
|
||||
import app.revanced.api.configuration.schema.APIReleaseVersion
|
||||
import app.revanced.library.PatchUtils
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.net.URL
|
||||
|
||||
internal class PatchesService(
|
||||
private val backendRepository: BackendRepository,
|
||||
private val configurationRepository: ConfigurationRepository,
|
||||
) {
|
||||
private val patchesListCache = Caffeine
|
||||
.newBuilder()
|
||||
.maximumSize(1)
|
||||
.build<String, ByteArray>()
|
||||
|
||||
suspend fun latestRelease(): APIRelease {
|
||||
val patchesRelease = backendRepository.release(
|
||||
configurationRepository.organization,
|
||||
configurationRepository.patchesRepository,
|
||||
)
|
||||
val integrationsReleases = withContext(Dispatchers.Default) {
|
||||
configurationRepository.integrationsRepositoryNames.map {
|
||||
async { backendRepository.release(configurationRepository.organization, it) }
|
||||
}
|
||||
}.awaitAll()
|
||||
|
||||
val assets = (patchesRelease.assets + integrationsReleases.flatMap { it.assets })
|
||||
.map { APIAsset(it.downloadUrl) }
|
||||
.filter { it.type != APIAsset.Type.UNKNOWN }
|
||||
.toSet()
|
||||
|
||||
return APIRelease(
|
||||
patchesRelease.tag,
|
||||
patchesRelease.createdAt,
|
||||
patchesRelease.releaseNote,
|
||||
assets,
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun latestVersion(): APIReleaseVersion {
|
||||
val patchesRelease = backendRepository.release(
|
||||
configurationRepository.organization,
|
||||
configurationRepository.patchesRepository,
|
||||
)
|
||||
|
||||
return APIReleaseVersion(patchesRelease.tag)
|
||||
}
|
||||
|
||||
suspend fun list(): ByteArray {
|
||||
val patchesRelease = backendRepository.release(
|
||||
configurationRepository.organization,
|
||||
configurationRepository.patchesRepository,
|
||||
)
|
||||
|
||||
return patchesListCache.getIfPresent(patchesRelease.tag) ?: run {
|
||||
val downloadUrl = patchesRelease.assets
|
||||
.map { APIAsset(it.downloadUrl) }
|
||||
.find { it.type == APIAsset.Type.PATCHES }
|
||||
?.downloadUrl
|
||||
|
||||
val patches = kotlin.io.path.createTempFile().toFile().apply {
|
||||
outputStream().use { URL(downloadUrl).openStream().copyTo(it) }
|
||||
}.let { file ->
|
||||
PatchBundleLoader.Jar(file).also { file.delete() }
|
||||
}
|
||||
|
||||
ByteArrayOutputStream().use { stream ->
|
||||
PatchUtils.Json.serialize(patches, outputStream = stream)
|
||||
|
||||
stream.toByteArray()
|
||||
}.also {
|
||||
patchesListCache.put(patchesRelease.tag, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user