Skip to content

Commit

Permalink
Add admin/dimensions API methods
Browse files Browse the repository at this point in the history
  • Loading branch information
PattaFeuFeu committed Nov 26, 2023
1 parent 3b8ee0e commit c1afccd
Show file tree
Hide file tree
Showing 7 changed files with 703 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package social.bigbone.rx.admin

import io.reactivex.rxjava3.core.Single
import social.bigbone.MastodonClient
import social.bigbone.api.entity.admin.AdminDimension
import social.bigbone.api.method.admin.AdminDimensionMethods
import social.bigbone.api.method.admin.RequestDimension
import java.time.Instant

/**
* Reactive implementation of [AdminDimensionMethods].
*
* Obtain qualitative metrics about the server.
* @see <a href="https://docs.joinmastodon.org/methods/admin/dimensions/">Mastodon admin/dimensions API methods</a>
*/
class RxAdminDimensionMethods(client: MastodonClient) {

private val adminDimensionMethods = AdminDimensionMethods(client)

/**
* Obtain information about popularity of certain accounts, servers, languages, etc.
*
* @param dimensions Request specific dimensions. Uses helper wrapper [RequestDimension] to ensure that
* required fields are set for any given [AdminDimension.Key].
* @param startAt The start date for the time period. If a time is provided, it will be ignored.
* @param endAt The end date for the time period. If a time is provided, it will be ignored.
*
* @see <a href="https://docs.joinmastodon.org/methods/admin/dimensions/#get">Mastodon API documentation: admin/dimensions/#get</a>
*/
fun getDimensionalData(
dimensions: List<RequestDimension>,
startAt: Instant,
endAt: Instant
): Single<List<AdminDimension>> = Single.fromCallable {
adminDimensionMethods.getDimensionalData(
dimensions = dimensions,
startAt = startAt,
endAt = endAt
).execute()
}
}
8 changes: 8 additions & 0 deletions bigbone/src/main/kotlin/social/bigbone/MastodonClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import social.bigbone.api.method.StreamingMethods
import social.bigbone.api.method.SuggestionMethods
import social.bigbone.api.method.TagMethods
import social.bigbone.api.method.TimelineMethods
import social.bigbone.api.method.admin.AdminDimensionMethods
import social.bigbone.api.method.admin.AdminMeasureMethods
import social.bigbone.api.method.admin.AdminRetentionMethods
import social.bigbone.extension.emptyRequestBody
Expand Down Expand Up @@ -77,6 +78,13 @@ private constructor(
@get:JvmName("accounts")
val accounts: AccountMethods by lazy { AccountMethods(this) }

/**
* Access API methods under the "admin/dimensions" endpoint.
*/
@Suppress("unused") // public API
@get:JvmName("adminDimensions")
val adminDimensions: AdminDimensionMethods by lazy { AdminDimensionMethods(this) }

/**
* Access API methods under the "admin/measures" endpoint.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package social.bigbone.api.entity.admin

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Represents qualitative data about the server.
* @see <a href="https://docs.joinmastodon.org/entities/Admin_Dimension/>Mastodon API Admin::Dimension documentation</a>
*/
@Serializable
class AdminDimension {

/**
* The unique keystring for the requested dimension.
*/
@SerialName("key")
val key: Key? = null

/**
* The data available for the requested dimension.
*/
@SerialName("data")
val data: List<Data>? = null

/**
* The unique keystring for the requested dimension.
*/
@Serializable
enum class Key {

/**
* Most-used languages on this server.
*/
@SerialName("languages")
LANGUAGES,

/**
* Most-used client apps on this server.
*/
@SerialName("sources")
SOURCES,

/**
* Remote servers with the most statuses.
*/
@SerialName("servers")
SERVERS,

/**
* How much space is used by your software stack.
*/
@SerialName("space_usage")
SPACE_USAGE,

/**
* The version numbers for your software stack.
*/
@SerialName("software_versions")
SOFTWARE_VERSIONS,

/**
* Most-common servers for statuses including a trending tag.
*/
@SerialName("tag_servers")
TAG_SERVERS,

/**
* Most-used languages for statuses including a trending tag.
*/
@SerialName("tag_languages")
TAG_LANGUAGES,

/**
* Most-followed accounts from a remote server.
*/
@SerialName("instance_accounts")
INSTANCE_ACCOUNTS,

/**
* Most-used languages from a remote server.
*/
@SerialName("instance_languages")
INSTANCE_LANGUAGES;

@OptIn(ExperimentalSerializationApi::class)
val apiName: String get() = Key.serializer().descriptor.getElementName(ordinal)
}

/**
* The data available for the requested dimension.
*/
@Serializable
data class Data(
/**
* The unique keystring for this data item.
*/
@SerialName("key")
val key: String? = null,

/**
* A human-readable key for this data item.
*/
@SerialName("human_key")
val humanKey: String? = null,

/**
* The value for this data item.
*/
@SerialName("value")
val value: String? = null,

/**
* The units associated with this data item’s value, if applicable.
*/
@SerialName("unit")
val unit: String? = null,

/**
* A human-readable formatted value for this data item.
*/
@SerialName("human_value")
val humanValue: String? = null
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package social.bigbone.api.method.admin

import social.bigbone.MastodonClient
import social.bigbone.MastodonRequest
import social.bigbone.Parameters
import social.bigbone.api.entity.admin.AdminDimension
import social.bigbone.api.entity.admin.AdminDimension.Key
import java.time.Instant

/**
* Obtain qualitative metrics about the server.
* @see <a href="https://docs.joinmastodon.org/methods/admin/dimensions/">Mastodon admin/dimensions API methods</a>
*/
class AdminDimensionMethods(private val client: MastodonClient) {

private val adminDimensionsEndpoint = "api/v1/admin/dimensions"

/**
* Obtain information about popularity of certain accounts, servers, languages, etc.
*
* @param dimensions Request specific dimensions. Uses helper wrapper [RequestDimension] to ensure that
* required fields are set for any given [Key].
* @param startAt The start date for the time period. If a time is provided, it will be ignored.
* @param endAt The end date for the time period. If a time is provided, it will be ignored.
*
* @see <a href="https://docs.joinmastodon.org/methods/admin/dimensions/#get">Mastodon API documentation: admin/dimensions/#get</a>
*/
fun getDimensionalData(
dimensions: List<RequestDimension>,
startAt: Instant,
endAt: Instant
): MastodonRequest<List<AdminDimension>> {
return client.getMastodonRequestForList(
endpoint = adminDimensionsEndpoint,
method = MastodonClient.Method.POST,
parameters = Parameters().apply {
dimensions
.flatMap(RequestDimension::getRequestKeyValues)
.forEach { (key, value) -> append(key, value) }

append("start_at", startAt.toString())
append("end_at", endAt.toString())
}
)
}
}

/**
* Wrapper class to ensure that required parameters are added when sending a specific [Key] for which to get dimensions.
*/
sealed class RequestDimension(val key: Key, val apiName: String = key.apiName) {

/**
* Get the key=value pairs to request this dimension.
* Can be used to craft a [Parameters] entry from.
* Defaults to [KEYS_NAME] = [apiName] for implementations of [RequestDimension] that do not have additional properties.
*/
open fun getRequestKeyValues(): List<Pair<String, String>> = listOf(
KEYS_NAME to apiName
)

companion object {
private const val KEYS_NAME = "keys[]"
private const val TAG_ID_NAME = "id"
private const val REMOTE_DOMAIN_NAME = "domain"
}

/**
* Requests [Key.LANGUAGES], i.e., Most-used languages on this server.
*/
data object Languages : RequestDimension(key = Key.LANGUAGES)

/**
* Requests [Key.SOURCES], i.e., Most-used client apps on this server.
*/
data object Sources : RequestDimension(key = Key.SOURCES)

/**
* Requests [Key.SERVERS], i.e., Remote servers with the most statuses.
*/
data object Servers : RequestDimension(key = Key.SERVERS)

/**
* Requests [Key.SPACE_USAGE], i.e., How much space is used by your software stack.
*/
data object SpaceUsage : RequestDimension(key = Key.SPACE_USAGE)

/**
* Requests [Key.SOFTWARE_VERSIONS], i.e., The version numbers for your software stack.
*/
data object SoftwareVersions : RequestDimension(key = Key.SOFTWARE_VERSIONS)

/**
* Requests [Key.TAG_SERVERS], i.e., Most-common servers for statuses including a trending tag.
*/
data class TagServers(
/**
* When [Key.TAG_SERVERS] is one of the requested keys, you must provide a trending tag ID
* to obtain information about which servers are posting the tag.
*/
val trendingTagId: String,
/**
* The maximum number of results to return for sources, servers, languages, tag or instance dimensions.
*/
val limit: Int? = null
) : RequestDimension(key = Key.TAG_SERVERS) {
override fun getRequestKeyValues(): List<Pair<String, String>> {
return super.getRequestKeyValues() + buildList {
add("$apiName[$TAG_ID_NAME]" to trendingTagId)
limit?.let { add("limit" to limit.toString()) }
}
}
}

/**
* Requests [Key.TAG_LANGUAGES], i.e., Most-used languages for statuses including a trending tag.
*/
data class TagLanguages(
/**
* When [Key.TAG_LANGUAGES] is one of the requested keys, you must provide a trending tag ID
* to obtain information about which languages are posting the tag.
*/
val trendingTagId: String,
/**
* The maximum number of results to return for sources, servers, languages, tag or instance dimensions.
*/
val limit: Int? = null
) : RequestDimension(key = Key.TAG_LANGUAGES) {
override fun getRequestKeyValues(): List<Pair<String, String>> {
return super.getRequestKeyValues() + buildList {
add("$apiName[$TAG_ID_NAME]" to trendingTagId)
limit?.let { add("limit" to limit.toString()) }
}
}
}

/**
* Requests [Key.INSTANCE_ACCOUNTS], i.e., Most-followed accounts from a remote server.
*/
data class InstanceAccounts(
/**
* When [Key.INSTANCE_ACCOUNTS] is one of the requested keys, you must provide a domain
* to obtain information about popular accounts from that server.
*/
val remoteDomain: String,
/**
* The maximum number of results to return for sources, servers, languages, tag or instance dimensions.
*/
val limit: Int? = null
) : RequestDimension(key = Key.INSTANCE_ACCOUNTS) {
override fun getRequestKeyValues(): List<Pair<String, String>> {
return super.getRequestKeyValues() + buildList {
add("$apiName[$REMOTE_DOMAIN_NAME]" to remoteDomain)
limit?.let { add("limit" to limit.toString()) }
}
}
}

/**
* Requests [Key.INSTANCE_LANGUAGES], i.e., Most-used languages from a remote server.
*/
data class InstanceLanguages(
/**
* When [Key.INSTANCE_LANGUAGES] is one of the requested keys, you must provide a domain
* to obtain information about popular languages from that server.
*/
val remoteDomain: String,
/**
* The maximum number of results to return for sources, servers, languages, tag or instance dimensions.
*/
val limit: Int? = null
) : RequestDimension(key = Key.INSTANCE_LANGUAGES) {
override fun getRequestKeyValues(): List<Pair<String, String>> {
return super.getRequestKeyValues() + buildList {
add("$apiName[$REMOTE_DOMAIN_NAME]" to remoteDomain)
limit?.let { add("limit" to limit.toString()) }
}
}
}
}
Loading

0 comments on commit c1afccd

Please sign in to comment.