feat: Implement more routes and add configuration

This commit is contained in:
oSumAtrIX
2024-01-29 03:18:31 +01:00
parent 8ae50b543e
commit 9999b242ad
15 changed files with 236 additions and 82 deletions

View File

@@ -19,12 +19,12 @@ abstract class Backend(
*
* @property name The name of the user.
* @property avatarUrl The URL to the avatar of the user.
* @property profileUrl The URL to the profile of the user.
* @property url The URL to the profile of the user.
*/
interface User {
interface BackendUser {
val name: String
val avatarUrl: String
val profileUrl: String
val url: String
}
/**
@@ -32,48 +32,50 @@ abstract class Backend(
*
* @property members The members of the organization.
*/
class Organization(
val members: Set<Member>
class BackendOrganization(
val members: Set<BackendMember>
) {
/**
* A member of an organization.
*
* @property name The name of the member.
* @property avatarUrl The URL to the avatar of the member.
* @property profileUrl The URL to the profile of the member.
* @property url The URL to the profile of the member.
* @property bio The bio of the member.
* @property gpgKeysUrl The URL to the GPG keys of the member.
*/
@Serializable
class Member (
class BackendMember (
override val name: String,
override val avatarUrl: String,
override val profileUrl: String,
override val url: String,
val bio: String?,
val gpgKeysUrl: String?
) : User
val gpgKeysUrl: String
) : BackendUser
/**
* A repository of an organization.
*
* @property contributors The contributors of the repository.
*/
class Repository(
val contributors: Set<Contributor>
class BackendRepository(
val contributors: Set<BackendContributor>
) {
/**
* A contributor of a repository.
*
* @property name The name of the contributor.
* @property avatarUrl The URL to the avatar of the contributor.
* @property profileUrl The URL to the profile of the contributor.
* @property url The URL to the profile of the contributor.
* @property contributions The number of contributions of the contributor.
*/
@Serializable
class Contributor(
class BackendContributor(
override val name: String,
override val avatarUrl: String,
override val profileUrl: String
) : User
override val url: String,
val contributions: Int
) : BackendUser
/**
* A release of a repository.
@@ -84,11 +86,11 @@ abstract class Backend(
* @property releaseNote The release note of the release.
*/
@Serializable
class Release(
class BackendRelease(
val tag: String,
val releaseNote: String,
val createdAt: String,
val assets: Set<Asset>
val assets: Set<BackendAsset>
) {
/**
* An asset of a release.
@@ -96,7 +98,7 @@ abstract class Backend(
* @property downloadUrl The URL to download the asset.
*/
@Serializable
class Asset(
class BackendAsset(
val downloadUrl: String
)
}
@@ -109,17 +111,13 @@ abstract class Backend(
* @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 return a pre-release.
* If no pre-release exists, the latest release is returned.
* If tag is not null, this parameter is ignored.
* @return The release.
*/
abstract suspend fun getRelease(
owner: String,
repository: String,
tag: String? = null,
preRelease: Boolean = false
): Organization.Repository.Release
): BackendOrganization.BackendRepository.BackendRelease
/**
* Get the contributors of a repository.
@@ -128,7 +126,7 @@ abstract class Backend(
* @param repository The name of the repository.
* @return The contributors.
*/
abstract suspend fun getContributors(owner: String, repository: String): Set<Organization.Repository.Contributor>
abstract suspend fun getContributors(owner: String, repository: String): Set<BackendOrganization.BackendRepository.BackendContributor>
/**
* Get the members of an organization.
@@ -136,5 +134,5 @@ abstract class Backend(
* @param organization The name of the organization.
* @return The members.
*/
abstract suspend fun getMembers(organization: String): Set<Organization.Member>
abstract suspend fun getMembers(organization: String): Set<BackendOrganization.BackendMember>
}

View File

@@ -9,13 +9,17 @@ 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 app.revanced.api.backend.Backend.BackendOrganization.BackendMember
import app.revanced.api.backend.Backend.BackendOrganization.BackendRepository.BackendRelease
import app.revanced.api.backend.Backend.BackendOrganization.BackendRepository.BackendContributor
import app.revanced.api.backend.Backend.BackendOrganization.BackendRepository.BackendRelease.BackendAsset
import app.revanced.api.backend.github.api.Request.Organization.Repository.Releases
import app.revanced.api.backend.github.api.Request.Organization.Repository.Contributors
import app.revanced.api.backend.github.api.Request.Organization.Members
import app.revanced.api.backend.github.api.Response
import app.revanced.api.backend.github.api.Response.Organization.Repository.Release
import app.revanced.api.backend.github.api.Response.Organization.Repository.Contributor
import app.revanced.api.backend.github.api.Response.Organization.Member
import app.revanced.api.backend.github.api.Response.GitHubOrganization.GitHubRepository.GitHubRelease
import app.revanced.api.backend.github.api.Response.GitHubOrganization.GitHubRepository.GitHubContributor
import app.revanced.api.backend.github.api.Response.GitHubOrganization.GitHubMember
import io.ktor.client.plugins.resources.Resources
import io.ktor.serialization.kotlinx.json.*
import kotlinx.coroutines.*
@@ -55,59 +59,58 @@ class GitHubBackend(token: String? = null) : Backend({
owner: String,
repository: String,
tag: String?,
preRelease: Boolean
): Organization.Repository.Release {
val release = if (preRelease) {
val releases: Set<Release> = client.get(Releases(owner, repository)).body()
releases.firstOrNull { it.preReleases } ?: releases.first() // Latest pre-release or latest release
} else {
client.get(
tag?.let { Releases.Tag(owner, repository, it) }
?: Releases.Latest(owner, repository)
).body()
}
): BackendRelease {
val release: GitHubRelease = if (tag != null)
client.get(Releases.Tag(owner, repository, tag)).body()
else
client.get(Releases.Latest(owner, repository)).body()
return Organization.Repository.Release(
return BackendRelease(
tag = release.tagName,
releaseNote = release.body,
createdAt = release.createdAt,
assets = release.assets.map {
Organization.Repository.Release.Asset(
BackendAsset(
downloadUrl = it.browserDownloadUrl
)
}.toSet()
)
}
override suspend fun getContributors(owner: String, repository: String): Set<Organization.Repository.Contributor> {
val contributors: Set<Contributor> = client.get(Contributors(owner, repository)).body()
override suspend fun getContributors(
owner: String,
repository: String
): Set<BackendContributor> {
val contributors: Set<GitHubContributor> = client.get(Contributors(owner, repository)).body()
return contributors.map {
Organization.Repository.Contributor(
BackendContributor(
name = it.login,
avatarUrl = it.avatarUrl,
profileUrl = it.url
url = it.url,
contributions = it.contributions
)
}.toSet()
}
override suspend fun getMembers(organization: String): Set<Organization.Member> {
override suspend fun getMembers(organization: String): Set<BackendMember> {
// Get the list of members of the organization.
val members: Set<Member> = client.get(Members(organization)).body<Set<Member>>()
val members: Set<GitHubMember> = client.get(Members(organization)).body()
return runBlocking(Dispatchers.Default) {
members.map { member ->
// Map the member to a user in order to get the bio.
async {
client.get(Request.User(member.login)).body<Response.User>()
client.get(Request.User(member.login)).body<Response.GitHubUser>()
}
}
}.awaitAll().map { user ->
// Map the user back to a member.
Organization.Member(
BackendMember(
name = user.login,
avatarUrl = user.avatarUrl,
profileUrl = user.url,
url = user.url,
bio = user.bio,
gpgKeysUrl = "https://github.com/${user.login}.gpg",
)

View File

@@ -1,49 +1,50 @@
package app.revanced.api.backend.github.api
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
class Response {
interface IUser {
interface IGitHubUser {
val login: String
val avatarUrl: String
val url: String
}
@Serializable
class User (
class GitHubUser (
override val login: String,
override val avatarUrl: String,
override val url: String,
val bio: String?,
) : IUser
) : IGitHubUser
class Organization {
class GitHubOrganization {
@Serializable
class Member(
class GitHubMember(
override val login: String,
override val avatarUrl: String,
override val url: String,
) : IUser
) : IGitHubUser
class Repository {
class GitHubRepository {
@Serializable
class Contributor(
class GitHubContributor(
override val login: String,
override val avatarUrl: String,
override val url: String,
) : IUser
val contributions: Int,
) : IGitHubUser
@Serializable
class Release(
class GitHubRelease(
val tagName: String,
val assets: Set<Asset>,
val preReleases: Boolean,
val assets: Set<GitHubAsset>,
val createdAt: String,
val body: String
) {
@Serializable
class Asset(
class GitHubAsset(
val browserDownloadUrl: String
)
}