Skip to content

Commit

Permalink
Add admin/retention methods (#334)
Browse files Browse the repository at this point in the history
* Allow parsing of time strings with +00:00 as well as Z

* Add admin/retention methods
  • Loading branch information
PattaFeuFeu authored Nov 6, 2023
1 parent d53bb48 commit fc95f95
Show file tree
Hide file tree
Showing 8 changed files with 371 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package social.bigbone.rx.admin

import io.reactivex.rxjava3.core.Single
import social.bigbone.MastodonClient
import social.bigbone.MastodonRequest
import social.bigbone.api.entity.admin.AdminCohort
import social.bigbone.api.entity.admin.AdminCohort.FrequencyOneOf
import social.bigbone.api.method.admin.AdminRetentionMethods
import java.time.Instant

/**
* Reactive implementation of [AdminRetentionMethods].
*
* Show retention data over time.
* @see <a href="https://docs.joinmastodon.org/methods/admin/retention/">Mastodon admin/retention API methods</a>
*/
class RxAdminRetentionMethods(private val client: MastodonClient) {

private val adminRetentionMethods = AdminRetentionMethods(client)

/**
* Generate a retention data report for a given time period and bucket.
*
* @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.
* @param frequency Specify whether to use [FrequencyOneOf.DAY] or [FrequencyOneOf.MONTH] buckets.
* @see <a href="https://docs.joinmastodon.org/methods/admin/retention/#create">Mastodon API documentation: admin/retention/#create</a>
*/
fun calculateRetentionData(
startAt: Instant,
endAt: Instant,
frequency: FrequencyOneOf
): Single<MastodonRequest<List<AdminCohort>>> = Single.fromCallable {
adminRetentionMethods.calculateRetentionData(
startAt = startAt,
endAt = endAt,
frequency = frequency
)
}
}
8 changes: 7 additions & 1 deletion bigbone/src/main/kotlin/social/bigbone/JsonSerializer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import social.bigbone.PrecisionDateTime.ValidPrecisionDateTime
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException

internal val JSON_SERIALIZER: Json = Json {
Expand Down Expand Up @@ -62,7 +63,12 @@ object DateTimeSerializer : KSerializer<PrecisionDateTime> {
* @param decodedString ISO 8601 string retrieved from JSON
*/
private fun parseExactDateTime(decodedString: String): ValidPrecisionDateTime.ExactTime =
ValidPrecisionDateTime.ExactTime(Instant.parse(decodedString))
ValidPrecisionDateTime.ExactTime(
DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(
decodedString,
Instant::from
)
)

/**
* Attempts to parse an ISO 8601 string into a [LocalDate] and returning an [Instant] at the start of that day in UTC.
Expand Down
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.AdminRetentionMethods
import social.bigbone.extension.emptyRequestBody
import social.bigbone.nodeinfo.NodeInfoClient
import java.io.IOException
Expand Down Expand Up @@ -75,6 +76,13 @@ private constructor(
@get:JvmName("accounts")
val accounts: AccountMethods by lazy { AccountMethods(this) }

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

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

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import social.bigbone.DateTimeSerializer
import social.bigbone.PrecisionDateTime

/**
* Represents a retention metric.
* @see <a href="https://docs.joinmastodon.org/entities/Admin_Cohort/">Mastodon documentation Admin::Cohort</a>
*
*/
@Serializable
data class AdminCohort(

/**
* The timestamp for the start of the period, at midnight.
*/
@SerialName("period")
@Serializable(with = DateTimeSerializer::class)
val period: PrecisionDateTime = PrecisionDateTime.InvalidPrecisionDateTime.Unavailable,

/**
* The size of the bucket for the returned data.
*/
@SerialName("frequency")
val frequency: FrequencyOneOf? = null,

/**
* Retention data for users who registered during the given period.
*/
@SerialName("data")
val data: List<CohortData>? = null
) {
/**
* The size of the bucket for the returned data.
*/
@Serializable
enum class FrequencyOneOf {
/**
* Daily buckets.
*/
@SerialName("day")
DAY,

/**
* Monthly buckets.
*/
@SerialName("month")
MONTH;

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

/**
* Retention data for users who registered during the given period.
*/
@Serializable
data class CohortData(
/**
* The timestamp for the start of the bucket, at midnight.
*/
@SerialName("date")
@Serializable(with = DateTimeSerializer::class)
val date: PrecisionDateTime = PrecisionDateTime.InvalidPrecisionDateTime.Unavailable,

/**
* The percentage rate of users who registered in the specified period and were active for the given date bucket.
*/
@SerialName("rate")
val rate: Float? = null,

/**
* How many users registered in the specified period and were active for the given date bucket.
*/
@SerialName("value")
val value: String? = null
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package social.bigbone.api.method.admin

import social.bigbone.MastodonClient
import social.bigbone.MastodonRequest
import social.bigbone.Parameters
import social.bigbone.api.entity.admin.AdminCohort
import social.bigbone.api.entity.admin.AdminCohort.FrequencyOneOf
import java.time.Instant

/**
* Show retention data over time.
* @see <a href="https://docs.joinmastodon.org/methods/admin/retention/">Mastodon admin/retention API methods</a>
*/
class AdminRetentionMethods(private val client: MastodonClient) {

private val adminRetentionEndpoint = "api/v1/admin/retention"

/**
* Generate a retention data report for a given time period and bucket.
*
* @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.
* @param frequency Specify whether to use [FrequencyOneOf.DAY] or [FrequencyOneOf.MONTH] buckets.
* @see <a href="https://docs.joinmastodon.org/methods/admin/retention/#create">Mastodon API documentation: admin/retention/#create</a>
*/
fun calculateRetentionData(
startAt: Instant,
endAt: Instant,
frequency: FrequencyOneOf
): MastodonRequest<List<AdminCohort>> {
return client.getMastodonRequestForList(
endpoint = adminRetentionEndpoint,
method = MastodonClient.Method.POST,
parameters = Parameters().apply {
append("start_at", startAt.toString())
append("end_at", endAt.toString())
append("frequency", frequency.apiName)
}
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
[
{
"period": "2022-09-08T00:00:00+00:00",
"frequency": "day",
"data": [
{
"date": "2022-09-08T00:00:00+00:00",
"rate": 1,
"value": "2"
},
{
"date": "2022-09-09T00:00:00+00:00",
"rate": 1,
"value": "2"
},
{
"date": "2022-09-10T00:00:00+00:00",
"rate": 0.5,
"value": "1"
},
{
"date": "2022-09-14T00:00:00+00:00",
"rate": 0.5,
"value": "1"
}
]
},
{
"period": "2022-09-09T00:00:00+00:00",
"frequency": "day",
"data": [
{
"date": "2022-09-09T00:00:00+00:00",
"rate": 0,
"value": "0"
},
{
"date": "2022-09-14T00:00:00+00:00",
"rate": 0,
"value": "0"
}
]
},
{
"period": "2022-09-10T00:00:00+00:00",
"frequency": "day",
"data": [
{
"date": "2022-09-10T00:00:00+00:00",
"rate": 0,
"value": "0"
},
{
"date": "2022-09-14T00:00:00+00:00",
"rate": 0,
"value": "0"
}
]
},
{
"period": "2022-09-14T00:00:00+00:00",
"frequency": "day",
"data": [
{
"date": "2022-09-14T00:00:00+00:00",
"rate": 0,
"value": "0"
}
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[
{
"period": "2022-09-01T00:00:00+00:00",
"frequency": "month",
"data": [
{
"date": "2022-09-01T00:00:00+00:00",
"rate": 1.0,
"value": "2"
}
]
}
]
Loading

0 comments on commit fc95f95

Please sign in to comment.