diff --git a/buildSrc/src/main/kotlin/Documentation.kt b/buildSrc/src/main/kotlin/Documentation.kt index 090ed8310b63..d3f17efe08ab 100644 --- a/buildSrc/src/main/kotlin/Documentation.kt +++ b/buildSrc/src/main/kotlin/Documentation.kt @@ -1,6 +1,6 @@ import org.gradle.kotlin.dsl.assign import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask -import java.net.URL +import java.net.URI fun AbstractDokkaLeafTask.applyKordDokkaOptions() { @@ -16,7 +16,7 @@ fun AbstractDokkaLeafTask.applyKordDokkaOptions() { sourceLink { localDirectory = project.projectDir - remoteUrl = URL("https://github.com/kordlib/kord/blob/${project.commitHash}/${project.name}") + remoteUrl = URI.create("https://github.com/kordlib/kord/blob/${project.commitHash}/${project.name}").toURL() remoteLineSuffix = "#L" } diff --git a/core/api/core.api b/core/api/core.api index bab5c50b9149..19297e29b69a 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -42,8 +42,8 @@ public final class dev/kord/core/Kord : kotlinx/coroutines/CoroutineScope { public final fun getDefaultSupplier ()Ldev/kord/core/supplier/EntitySupplier; public final fun getEntitlement (Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getEntitlementOrNull (Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun getEntitlements (Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ldev/kord/core/supplier/EntitySupplyStrategy;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun getEntitlements$default (Ldev/kord/core/Kord;Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ldev/kord/core/supplier/EntitySupplyStrategy;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public final fun getEntitlements (Ldev/kord/core/supplier/EntitySupplyStrategy;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun getEntitlements$default (Ldev/kord/core/Kord;Ldev/kord/core/supplier/EntitySupplyStrategy;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public final fun getEvents ()Lkotlinx/coroutines/flow/SharedFlow; public final fun getGateway ()Ldev/kord/core/gateway/MasterGateway; public final fun getGlobalApplicationCommand (Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -3551,6 +3551,7 @@ public final class dev/kord/core/cache/data/EntitlementData { public final fun getApplicationId ()Ldev/kord/common/entity/Snowflake; public final fun getConsumed ()Ldev/kord/common/entity/optional/OptionalBoolean; public final fun getDeleted ()Z + public final fun getEnded ()Z public final fun getEndsAt ()Ldev/kord/common/entity/optional/Optional; public final fun getGuildId ()Ldev/kord/common/entity/optional/OptionalSnowflake; public final fun getId ()Ldev/kord/common/entity/Snowflake; @@ -7032,8 +7033,6 @@ public final class dev/kord/core/entity/Sku : dev/kord/core/entity/KordEntity, d public fun equals (Ljava/lang/Object;)Z public final fun getApplicationId ()Ldev/kord/common/entity/Snowflake; public final fun getData ()Ldev/kord/common/entity/DiscordSku; - public final fun getEntitlements (Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun getEntitlements$default (Ldev/kord/core/entity/Sku;Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public final fun getFlags ()Ldev/kord/common/entity/SkuFlags; public fun getId ()Ldev/kord/common/entity/Snowflake; public fun getKord ()Ldev/kord/core/Kord; @@ -13626,7 +13625,7 @@ public final class dev/kord/core/supplier/CacheEntitySupplier : dev/kord/core/su public fun getEmojis (Ldev/kord/common/entity/Snowflake;)Lkotlinx/coroutines/flow/Flow; public fun getEntitlement (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getEntitlementOrNull (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun getEntitlements (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun getEntitlements (Ldev/kord/common/entity/Snowflake;Ldev/kord/rest/json/request/EntitlementsListRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getFollowupMessage (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getFollowupMessageOrNull (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getGlobalApplicationCommand (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -13719,7 +13718,7 @@ public abstract interface class dev/kord/core/supplier/EntitySupplier { public abstract fun getEmojis (Ldev/kord/common/entity/Snowflake;)Lkotlinx/coroutines/flow/Flow; public abstract fun getEntitlement (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun getEntitlementOrNull (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun getEntitlements (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun getEntitlements (Ldev/kord/common/entity/Snowflake;Ldev/kord/rest/json/request/EntitlementsListRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun getFollowupMessage (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun getFollowupMessageOrNull (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun getGlobalApplicationCommand (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -13797,7 +13796,6 @@ public final class dev/kord/core/supplier/EntitySupplier$DefaultImpls { public static synthetic fun getCurrentUserGuilds$default (Ldev/kord/core/supplier/EntitySupplier;Ljava/lang/Integer;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; public static fun getEmoji (Ldev/kord/core/supplier/EntitySupplier;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun getEntitlement (Ldev/kord/core/supplier/EntitySupplier;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun getEntitlements$default (Ldev/kord/core/supplier/EntitySupplier;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static fun getFollowupMessage (Ldev/kord/core/supplier/EntitySupplier;Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun getGlobalApplicationCommand (Ldev/kord/core/supplier/EntitySupplier;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun getGlobalApplicationCommands$default (Ldev/kord/core/supplier/EntitySupplier;Ldev/kord/common/entity/Snowflake;Ljava/lang/Boolean;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; @@ -13880,7 +13878,7 @@ public final class dev/kord/core/supplier/RestEntitySupplier : dev/kord/core/sup public fun getEmojis (Ldev/kord/common/entity/Snowflake;)Lkotlinx/coroutines/flow/Flow; public fun getEntitlement (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getEntitlementOrNull (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun getEntitlements (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun getEntitlements (Ldev/kord/common/entity/Snowflake;Ldev/kord/rest/json/request/EntitlementsListRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getFollowupMessage (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getFollowupMessageOrNull (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getGlobalApplicationCommand (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -13982,7 +13980,7 @@ public final class dev/kord/core/supplier/StoreEntitySupplier : dev/kord/core/su public fun getEmojis (Ldev/kord/common/entity/Snowflake;)Lkotlinx/coroutines/flow/Flow; public fun getEntitlement (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getEntitlementOrNull (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun getEntitlements (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Ljava/lang/Integer;Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun getEntitlements (Ldev/kord/common/entity/Snowflake;Ldev/kord/rest/json/request/EntitlementsListRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getFollowupMessage (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getFollowupMessageOrNull (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getGlobalApplicationCommand (Ldev/kord/common/entity/Snowflake;Ldev/kord/common/entity/Snowflake;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; diff --git a/core/src/commonMain/kotlin/Kord.kt b/core/src/commonMain/kotlin/Kord.kt index 3370dfd13027..be33e3999312 100644 --- a/core/src/commonMain/kotlin/Kord.kt +++ b/core/src/commonMain/kotlin/Kord.kt @@ -30,6 +30,7 @@ import dev.kord.gateway.Gateway import dev.kord.gateway.builder.LoginBuilder import dev.kord.gateway.builder.PresenceBuilder import dev.kord.rest.builder.application.ApplicationRoleConnectionMetadataRecordsBuilder +import dev.kord.rest.builder.entitlement.EntitlementsListRequestBuilder import dev.kord.rest.builder.guild.GuildCreateBuilder import dev.kord.rest.builder.interaction.* import dev.kord.rest.builder.user.CurrentUserModifyBuilder @@ -379,17 +380,22 @@ public class Kord( rest.sku.listSkus(selfId).map { Sku(it, this) } /** - * Requests to get a list of [Entitlement]s with the given [skuId], [userId], or [guildId]. + * Requests to get a list of [Entitlement]s. * * @throws [RequestException] if anything went wrong during the request. */ - public suspend fun getEntitlements( - limit: Int? = null, - skuId: Snowflake? = null, - userId: Snowflake? = null, - guildId: Snowflake? = null, + public suspend inline fun getEntitlements( strategy: EntitySupplyStrategy<*> = resources.defaultStrategy, - ): Flow = strategy.supply(this).getEntitlements(selfId, skuId, limit, userId, guildId) + builder: EntitlementsListRequestBuilder.() -> Unit = {}, + ): Flow { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + + val request = EntitlementsListRequestBuilder() + .apply(builder) + .toRequest() + + return strategy.supply(this).getEntitlements(selfId, request) + } /** * Requests to get the [Entitlement] with the given [id] @@ -405,7 +411,8 @@ public class Kord( * * @throws [RequestException] if anything went wrong during the request. */ - public suspend fun getEntitlementOrNull(id: Snowflake): Entitlement? = defaultSupplier.getEntitlementOrNull(selfId, id) + public suspend fun getEntitlementOrNull(id: Snowflake): Entitlement? = + defaultSupplier.getEntitlementOrNull(selfId, id) /** * Requests to create a new [test entitlement][Entitlement] with the given [skuId], [ownerId] and [ownerType]. @@ -417,7 +424,8 @@ public class Kord( ownerId: Snowflake, ownerType: EntitlementOwnerType, ): Entitlement { - val response = rest.entitlement.createTestEntitlement(selfId, TestEntitlementCreateRequest(skuId, ownerId, ownerType)) + val response = + rest.entitlement.createTestEntitlement(selfId, TestEntitlementCreateRequest(skuId, ownerId, ownerType)) val data = EntitlementData.from(response) return Entitlement(data, this) diff --git a/core/src/commonMain/kotlin/cache/data/EntitlementData.kt b/core/src/commonMain/kotlin/cache/data/EntitlementData.kt index ed10bbc7883e..cc288ce8a824 100644 --- a/core/src/commonMain/kotlin/cache/data/EntitlementData.kt +++ b/core/src/commonMain/kotlin/cache/data/EntitlementData.kt @@ -8,6 +8,7 @@ import dev.kord.common.entity.Snowflake import dev.kord.common.entity.optional.Optional import dev.kord.common.entity.optional.OptionalBoolean import dev.kord.common.entity.optional.OptionalSnowflake +import kotlinx.datetime.Clock import kotlinx.datetime.Instant import kotlinx.serialization.Serializable @@ -24,6 +25,9 @@ public data class EntitlementData( val startsAt: Optional = Optional.Missing(), val consumed: OptionalBoolean = OptionalBoolean.Missing, ) { + val ended: Boolean + get() = endsAt.value?.let { Clock.System.now() >= it } ?: false + public companion object { public val description: DataDescription = description(EntitlementData::id) diff --git a/core/src/commonMain/kotlin/entity/Sku.kt b/core/src/commonMain/kotlin/entity/Sku.kt index 3cbd98f89080..39df514c077b 100644 --- a/core/src/commonMain/kotlin/entity/Sku.kt +++ b/core/src/commonMain/kotlin/entity/Sku.kt @@ -4,12 +4,10 @@ import dev.kord.common.entity.DiscordSku import dev.kord.common.entity.SkuFlags import dev.kord.common.entity.SkuType import dev.kord.common.entity.Snowflake -import dev.kord.common.exception.RequestException import dev.kord.core.Kord import dev.kord.core.hash import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy -import kotlinx.coroutines.flow.Flow /** * An instance of a [Discord Sku](https://discord.com/developers/docs/monetization/skus). @@ -50,26 +48,11 @@ public class Sku( */ public val flags: SkuFlags get() = data.flags - /** - * Requests to get the entitlements for this SKU. - * - * @param limit The maximum number of entitlements to return. Default is 100. - * @param userId The ID of the user to get entitlements for. If not provided, the current user is assumed. - * @param guildId The ID of the guild to get entitlements for. If not provided, entitlements for all guilds are returned. - * - * @throws [RequestException] if anything went wrong during the request. - */ - public suspend fun getEntitlements( - limit: Int? = null, - userId: Snowflake? = null, - guildId: Snowflake? = null, - ): Flow = supplier.getEntitlements(applicationId, id, limit, userId, guildId) - override fun withStrategy(strategy: EntitySupplyStrategy<*>): Sku = Sku(data, kord, strategy.supply(kord)) override fun hashCode(): Int = hash(id, applicationId) - override fun equals(other: Any?): Boolean = when (other) { + override fun equals(other: Any?): Boolean = when (other) { is Sku -> other.id == id && other.applicationId == applicationId else -> false } diff --git a/core/src/commonMain/kotlin/supplier/CacheEntitySupplier.kt b/core/src/commonMain/kotlin/supplier/CacheEntitySupplier.kt index d8da61aa4855..c7b4d69528a0 100644 --- a/core/src/commonMain/kotlin/supplier/CacheEntitySupplier.kt +++ b/core/src/commonMain/kotlin/supplier/CacheEntitySupplier.kt @@ -24,6 +24,8 @@ import dev.kord.core.entity.channel.thread.ThreadMember import dev.kord.core.entity.interaction.followup.FollowupMessage import dev.kord.core.exception.EntityNotFoundException import dev.kord.gateway.Gateway +import dev.kord.rest.json.request.EntitlementsListRequest +import dev.kord.rest.route.Position import kotlinx.coroutines.flow.* import kotlinx.datetime.Instant @@ -437,7 +439,10 @@ public class CacheEntitySupplier(private val kord: Kord) : EntitySupplier { return GlobalApplicationCommand(data, kord.rest.interaction) } - override fun getGlobalApplicationCommands(applicationId: Snowflake, withLocalizations: Boolean?): Flow = + override fun getGlobalApplicationCommands( + applicationId: Snowflake, + withLocalizations: Boolean? + ): Flow = cache.query { idEq(ApplicationCommandData::guildId, null) idEq(ApplicationCommandData::applicationId, applicationId) @@ -610,22 +615,23 @@ public class CacheEntitySupplier(private val kord: Kord) : EntitySupplier { override suspend fun getEntitlements( applicationId: Snowflake, - skuId: Snowflake?, - limit: Int?, - userId: Snowflake?, - guildId: Snowflake? + request: EntitlementsListRequest ): Flow { - checkLimit(limit) + checkLimit(request.limit) return cache .query { idEq(EntitlementData::applicationId, applicationId) - skuId?.let { idEq(EntitlementData::skuId, it) } - userId?.let { idEq(EntitlementData::userId, it) } - guildId?.let { idEq(EntitlementData::guildId, it) } + request.userId?.let { idEq(EntitlementData::userId, it) } + request.guildId?.let { idEq(EntitlementData::guildId, it) } } .asFlow() + .filter { + val containsSku = request.skuIds.isEmpty() || it.skuId in request.skuIds + val excludeEnded = request.excludeEnded == true && it.ended + containsSku && !excludeEnded && followsPosition(request.position, it.id) + } .map { Entitlement(it, kord) } - .limit(limit) + .limit(request.limit) } override fun toString(): String = "CacheEntitySupplier(cache=$cache)" @@ -636,4 +642,11 @@ private fun checkLimit(limit: Int?) { require(limit == null || limit > 0) { "At least 1 item should be requested, but got $limit." } } +private fun followsPosition(position: Position?, id: Snowflake): Boolean = when (position) { + is Position.Before -> id < position.value + is Position.After -> id > position.value + is Position.Around -> throw UnsupportedOperationException("Around is not supported for this operation.") + else -> true +} + private fun Flow.limit(limit: Int?): Flow = if (limit == null) this else take(limit) diff --git a/core/src/commonMain/kotlin/supplier/EntitySupplier.kt b/core/src/commonMain/kotlin/supplier/EntitySupplier.kt index 4424edcfb1f6..55b53eae52b3 100644 --- a/core/src/commonMain/kotlin/supplier/EntitySupplier.kt +++ b/core/src/commonMain/kotlin/supplier/EntitySupplier.kt @@ -16,6 +16,7 @@ import dev.kord.core.entity.channel.thread.ThreadChannel import dev.kord.core.entity.channel.thread.ThreadMember import dev.kord.core.entity.interaction.followup.FollowupMessage import dev.kord.core.exception.EntityNotFoundException +import dev.kord.rest.json.request.EntitlementsListRequest import kotlinx.coroutines.flow.Flow import kotlinx.datetime.Instant @@ -474,7 +475,11 @@ public interface EntitySupplier { limit: Int? = null, ): Flow - public fun getGuildApplicationCommands(applicationId: Snowflake, guildId: Snowflake, withLocalizations: Boolean? = null): Flow + public fun getGuildApplicationCommands( + applicationId: Snowflake, + guildId: Snowflake, + withLocalizations: Boolean? = null + ): Flow public suspend fun getGuildApplicationCommandOrNull( applicationId: Snowflake, @@ -505,7 +510,10 @@ public interface EntitySupplier { getGlobalApplicationCommandOrNull(applicationId, commandId) ?: EntityNotFoundException.applicationCommandNotFound(commandId) - public fun getGlobalApplicationCommands(applicationId: Snowflake, withLocalizations: Boolean? = null): Flow + public fun getGlobalApplicationCommands( + applicationId: Snowflake, + withLocalizations: Boolean? = null + ): Flow public suspend fun getApplicationCommandPermissionsOrNull( @@ -666,13 +674,7 @@ public interface EntitySupplier { * The returned flow is lazily executed, any [RequestException] will be thrown on * [terminal operators](https://kotlinlang.org/docs/reference/coroutines/flow.html#terminal-flow-operators) instead. */ - public suspend fun getEntitlements( - applicationId: Snowflake, - skuId: Snowflake? = null, - limit: Int? = null, - userId: Snowflake? = null, - guildId: Snowflake? = null - ): Flow + public suspend fun getEntitlements(applicationId: Snowflake, request: EntitlementsListRequest): Flow } diff --git a/core/src/commonMain/kotlin/supplier/FallbackEntitySupplier.kt b/core/src/commonMain/kotlin/supplier/FallbackEntitySupplier.kt index 1998efcca90c..776905cd3e4a 100644 --- a/core/src/commonMain/kotlin/supplier/FallbackEntitySupplier.kt +++ b/core/src/commonMain/kotlin/supplier/FallbackEntitySupplier.kt @@ -12,6 +12,7 @@ import dev.kord.core.entity.channel.thread.ThreadChannel import dev.kord.core.entity.channel.thread.ThreadMember import dev.kord.core.entity.interaction.followup.FollowupMessage import dev.kord.core.switchIfEmpty +import dev.kord.rest.json.request.EntitlementsListRequest import kotlinx.coroutines.flow.Flow import kotlinx.datetime.Instant @@ -185,7 +186,10 @@ private class FallbackEntitySupplier(val first: EntitySupplier, val second: Enti ) - override fun getGlobalApplicationCommands(applicationId: Snowflake, withLocalizations: Boolean?): Flow = + override fun getGlobalApplicationCommands( + applicationId: Snowflake, + withLocalizations: Boolean? + ): Flow = first.getGlobalApplicationCommands(applicationId, withLocalizations) .switchIfEmpty(second.getGlobalApplicationCommands(applicationId, withLocalizations)) @@ -278,16 +282,16 @@ private class FallbackEntitySupplier(val first: EntitySupplier, val second: Enti first.getAutoModerationRuleOrNull(guildId, ruleId) ?: second.getAutoModerationRuleOrNull(guildId, ruleId) override suspend fun getEntitlementOrNull(applicationId: Snowflake, entitlementId: Snowflake): Entitlement? = - first.getEntitlementOrNull(applicationId, entitlementId) ?: second.getEntitlementOrNull(applicationId, entitlementId) + first.getEntitlementOrNull(applicationId, entitlementId) ?: second.getEntitlementOrNull( + applicationId, + entitlementId + ) override suspend fun getEntitlements( applicationId: Snowflake, - skuId: Snowflake?, - limit: Int?, - userId: Snowflake?, - guildId: Snowflake? - ): Flow = first.getEntitlements(applicationId, skuId, limit, userId, guildId) - .switchIfEmpty(second.getEntitlements(applicationId, skuId, limit, userId, guildId)) + request: EntitlementsListRequest + ): Flow = first.getEntitlements(applicationId, request) + .switchIfEmpty(second.getEntitlements(applicationId, request)) override fun toString(): String = "FallbackEntitySupplier(first=$first, second=$second)" } diff --git a/core/src/commonMain/kotlin/supplier/RestEntitySupplier.kt b/core/src/commonMain/kotlin/supplier/RestEntitySupplier.kt index 53ca9afc9c8f..ba741588628a 100644 --- a/core/src/commonMain/kotlin/supplier/RestEntitySupplier.kt +++ b/core/src/commonMain/kotlin/supplier/RestEntitySupplier.kt @@ -447,7 +447,10 @@ public class RestEntitySupplier(public val kord: Kord) : EntitySupplier { GlobalApplicationCommand(data, interaction) } - override fun getGlobalApplicationCommands(applicationId: Snowflake, withLocalizations: Boolean?): Flow = flow { + override fun getGlobalApplicationCommands( + applicationId: Snowflake, + withLocalizations: Boolean? + ): Flow = flow { for (command in interaction.getGlobalApplicationCommands(applicationId, withLocalizations)) { val data = ApplicationCommandData.from(command) emit(GlobalApplicationCommand(data, interaction)) @@ -648,30 +651,22 @@ public class RestEntitySupplier(public val kord: Kord) : EntitySupplier { GuildApplicationCommand(data, interaction) } - override suspend fun getEntitlementOrNull(applicationId: Snowflake, entitlementId: Snowflake): Entitlement? = catchNotFound { - val response = entitlement.getEntitlement(applicationId, entitlementId) - val data = EntitlementData.from(response) - Entitlement(data, kord) - } + override suspend fun getEntitlementOrNull(applicationId: Snowflake, entitlementId: Snowflake): Entitlement? = + catchNotFound { + val response = entitlement.getEntitlement(applicationId, entitlementId) + val data = EntitlementData.from(response) + Entitlement(data, kord) + } // maxBatchSize: see https://discord.com/developers/docs/monetization/entitlements#list-entitlements override suspend fun getEntitlements( applicationId: Snowflake, - skuId: Snowflake?, - limit: Int?, - userId: Snowflake?, - guildId: Snowflake? - ): Flow = limitedPagination(limit, maxBatchSize = 100) { batchSize -> + request: EntitlementsListRequest + ): Flow = limitedPagination(request.limit, maxBatchSize = 100) { batchSize -> paginateForwards(batchSize, idSelector = { it.id }) { position -> entitlement.listEntitlements( applicationId = applicationId, - request = EntitlementsListRequest( - position = position, - limit = batchSize, - skuIds = listOfNotNull(skuId), - userId = userId, - guildId = guildId - ) + request = request.copy(position = position, limit = batchSize) ) }.map { val data = EntitlementData.from(it) diff --git a/core/src/commonMain/kotlin/supplier/StoreEntitySupplier.kt b/core/src/commonMain/kotlin/supplier/StoreEntitySupplier.kt index 8a10df397b65..f515f3fa1dbe 100644 --- a/core/src/commonMain/kotlin/supplier/StoreEntitySupplier.kt +++ b/core/src/commonMain/kotlin/supplier/StoreEntitySupplier.kt @@ -13,6 +13,7 @@ import dev.kord.core.entity.channel.TopGuildChannel import dev.kord.core.entity.channel.thread.ThreadChannel import dev.kord.core.entity.channel.thread.ThreadMember import dev.kord.core.entity.interaction.followup.FollowupMessage +import dev.kord.rest.json.request.EntitlementsListRequest import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.onEach import kotlinx.datetime.Instant @@ -318,11 +319,8 @@ public class StoreEntitySupplier( override suspend fun getEntitlements( applicationId: Snowflake, - skuId: Snowflake?, - limit: Int?, - userId: Snowflake?, - guildId: Snowflake? - ): Flow = storeOnEach(supplier.getEntitlements(applicationId, skuId, limit, userId, guildId)) { it.data } + request: EntitlementsListRequest + ): Flow = storeOnEach(supplier.getEntitlements(applicationId, request)) { it.data } private suspend inline fun storeAndReturn(value: T?, transform: (T) -> R): T? { if (value == null) return null diff --git a/rest/api/rest.api b/rest/api/rest.api index c5ad03b6f69f..ad9a11104008 100644 --- a/rest/api/rest.api +++ b/rest/api/rest.api @@ -1148,6 +1148,26 @@ public final class dev/kord/rest/builder/component/UserSelectBuilder : dev/kord/ public final fun getDefaultUsers ()Ljava/util/List; } +public final class dev/kord/rest/builder/entitlement/EntitlementsListRequestBuilder : dev/kord/rest/builder/RequestBuilder { + public fun ()V + public final fun after (Ldev/kord/common/entity/Snowflake;)V + public final fun before (Ldev/kord/common/entity/Snowflake;)V + public final fun getExcludeEnded ()Ljava/lang/Boolean; + public final fun getGuildId ()Ldev/kord/common/entity/Snowflake; + public final fun getLimit ()Ljava/lang/Integer; + public final fun getPosition ()Ldev/kord/rest/route/Position$BeforeOrAfter; + public final fun getSkuIds ()Ljava/util/List; + public final fun getUserId ()Ldev/kord/common/entity/Snowflake; + public final fun setExcludeEnded (Ljava/lang/Boolean;)V + public final fun setGuildId (Ldev/kord/common/entity/Snowflake;)V + public final fun setLimit (Ljava/lang/Integer;)V + public final fun setPosition (Ldev/kord/rest/route/Position$BeforeOrAfter;)V + public final fun setSkuIds (Ljava/util/List;)V + public final fun setUserId (Ldev/kord/common/entity/Snowflake;)V + public fun toRequest ()Ldev/kord/rest/json/request/EntitlementsListRequest; + public synthetic fun toRequest ()Ljava/lang/Object; +} + public final class dev/kord/rest/builder/guild/CurrentVoiceStateModifyBuilder : dev/kord/rest/builder/RequestBuilder { public fun ()V public final fun getChannelId ()Ldev/kord/common/entity/Snowflake; diff --git a/rest/src/commonMain/kotlin/builder/entitlement/EntitlementsListRequestBuilder.kt b/rest/src/commonMain/kotlin/builder/entitlement/EntitlementsListRequestBuilder.kt new file mode 100644 index 000000000000..c6fcccb8a7e5 --- /dev/null +++ b/rest/src/commonMain/kotlin/builder/entitlement/EntitlementsListRequestBuilder.kt @@ -0,0 +1,51 @@ +package dev.kord.rest.builder.entitlement + +import dev.kord.common.annotation.KordDsl +import dev.kord.common.entity.Snowflake +import dev.kord.rest.builder.RequestBuilder +import dev.kord.rest.json.request.EntitlementsListRequest +import dev.kord.rest.route.Position + +@KordDsl +public class EntitlementsListRequestBuilder : RequestBuilder { + /** + * User ID to look up entitlements for. + */ + public var userId: Snowflake? = null + + /** + * An optional list of SKU iDs to check entitlements for. + */ + public var skuIds: MutableList = mutableListOf() + + /** + * Retrieve entitlements before or after a specific entitlement ID. + */ + public var position: Position.BeforeOrAfter? = null + + /** + * The maximum number of entitlements to return. + */ + public var limit: Int? = null + + /** + * The guild ID to check entitlements for. + */ + public var guildId: Snowflake? = null + + /** + * Whether to exclude ended entitlements. + */ + public var excludeEnded: Boolean? = null + + public fun after(id: Snowflake) { + position = Position.After(id) + } + + public fun before(id: Snowflake) { + position = Position.Before(id) + } + + override fun toRequest(): EntitlementsListRequest = + EntitlementsListRequest(userId, skuIds, position, limit, guildId, excludeEnded) +}