Created
February 18, 2022 16:59
-
-
Save lopcode/60457a994a3b0b0c7daa55e1f6e3227a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sponsor.api.fetcher | |
import io.ktor.client.HttpClient | |
import io.ktor.client.call.receive | |
import io.ktor.client.request.header | |
import io.ktor.client.request.parameter | |
import io.ktor.client.request.request | |
import io.ktor.client.statement.HttpResponse | |
import io.ktor.http.HttpMethod | |
import kotlinx.serialization.SerialName | |
import kotlinx.serialization.Serializable | |
import sponsor.api.serialization.OffsetDateTimeSerializer | |
import java.time.OffsetDateTime | |
class PatreonCampaignMembersFetcher( | |
private val client: HttpClient, | |
private val accessToken: String | |
) : PatreonCampaignMembersFetching { | |
@Serializable | |
private data class ResponseBody( | |
val data: List<Member>, | |
val included: List<Included> | |
) { | |
@Serializable | |
data class Member( | |
val attributes: MemberAttributes, | |
val id: String, | |
val relationships: MemberRelationships, | |
val type: String | |
) | |
@Serializable | |
data class MemberAttributes( | |
@SerialName("full_name") val fullName: String, | |
@SerialName("patron_status") val patronStatus: String | |
) | |
@Serializable | |
data class MemberRelationships( | |
@SerialName("currently_entitled_tiers") val currentlyEntitledTiers: TiersRelationship, | |
val user: UserRelationship | |
) | |
@Serializable | |
data class TiersRelationship( | |
val data: List<TierData> | |
) | |
@Serializable | |
data class TierData( | |
val id: String, | |
val type: String | |
) | |
@Serializable | |
data class UserRelationship( | |
val data: UserData | |
) | |
@Serializable | |
data class UserData( | |
val id: String, | |
val type: String | |
) | |
@Serializable | |
sealed class Included { | |
abstract val type: String | |
abstract val id: String | |
} | |
@Serializable | |
@SerialName("user") | |
data class IncludedUser( | |
override val type: String, | |
override val id: String, | |
val attributes: IncludedUserAttributes | |
) : Included() | |
@Serializable | |
data class IncludedUserAttributes( | |
@SerialName("full_name") val fullName: String, | |
@SerialName("hide_pledges") val hidePledges: Boolean, | |
val vanity: String? | |
) | |
@Serializable | |
@SerialName("tier") | |
data class IncludedTier( | |
override val type: String, | |
override val id: String, | |
val attributes: IncludedTierAttributes | |
) : Included() | |
@Serializable | |
data class IncludedTierAttributes( | |
@SerialName("amount_cents") val amountCents: Int, | |
@Serializable(OffsetDateTimeSerializer::class) | |
@SerialName("created_at") | |
val createdAt: OffsetDateTime, | |
val description: String?, | |
val title: String? | |
) | |
} | |
override suspend fun fetch( | |
campaignId: String | |
): Set<PatreonCampaignMembersFetching.PatronDTO> { | |
val result = client.request<HttpResponse>("https://www.patreon.com/api/oauth2/v2/campaigns/$campaignId/members") { | |
method = HttpMethod.Get | |
parameter("include", "currently_entitled_tiers,user") | |
parameter("fields[member]", "full_name,patron_status") | |
parameter("fields[tier]", "title,amount_cents,created_at,description") | |
parameter("fields[user]", "vanity,full_name,hide_pledges") | |
header("Authorization", "Bearer $accessToken") | |
} | |
// todo: paging | |
val responseBody = result.receive<ResponseBody>() | |
return convert(responseBody) | |
} | |
private fun convert( | |
response: ResponseBody | |
): Set<PatreonCampaignMembersFetching.PatronDTO> { | |
return response.data.map { memberResponse -> | |
val userRelationship = ( | |
response.included.first { | |
it.type == "user" && it.id == memberResponse.relationships.user.data.id | |
} as ResponseBody.IncludedUser | |
) | |
val name = when (userRelationship.attributes.hidePledges) { | |
true -> null | |
false -> userRelationship.attributes.vanity ?: memberResponse.attributes.fullName | |
} | |
val patronStatus = when (memberResponse.attributes.patronStatus) { | |
"active_patron" -> PatreonCampaignMembersFetching.Status.ACTIVE | |
"former_patron" -> PatreonCampaignMembersFetching.Status.FORMER | |
"declined_payment" -> PatreonCampaignMembersFetching.Status.DECLINED_PAYMENT | |
else -> PatreonCampaignMembersFetching.Status.UNKNOWN | |
} | |
PatreonCampaignMembersFetching.PatronDTO( | |
name = name, | |
status = patronStatus, | |
memberId = memberResponse.id, | |
userId = userRelationship.id | |
) | |
}.toSet() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment