From e44a1c357a88aeed91a4a11531db7a73f366ee0e Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Tue, 28 Dec 2021 12:03:31 +0200 Subject: [PATCH 01/21] add missing fields to PartialGuild --- common/src/main/kotlin/entity/DiscordGuild.kt | 166 +++++++----------- .../kotlin/cache/data/PartialGuildData.kt | 20 ++- core/src/main/kotlin/entity/Guild.kt | 2 +- core/src/main/kotlin/entity/PartialGuild.kt | 71 +++++++- 4 files changed, 148 insertions(+), 111 deletions(-) diff --git a/common/src/main/kotlin/entity/DiscordGuild.kt b/common/src/main/kotlin/entity/DiscordGuild.kt index e4e9b3d1d95d..1c95a477544a 100644 --- a/common/src/main/kotlin/entity/DiscordGuild.kt +++ b/common/src/main/kotlin/entity/DiscordGuild.kt @@ -81,82 +81,54 @@ data class DiscordGuild( val id: Snowflake, val name: String, val icon: String?, - @SerialName("icon_hash") - val iconHash: Optional = Optional.Missing(), + @SerialName("icon_hash") val iconHash: Optional = Optional.Missing(), val splash: Optional = Optional.Missing(), - @SerialName("discovery_splash") - val discoverySplash: Optional = Optional.Missing(), + @SerialName("discovery_splash") val discoverySplash: Optional = Optional.Missing(), val owner: OptionalBoolean = OptionalBoolean.Missing, - @SerialName("owner_id") - val ownerId: Snowflake, + @SerialName("owner_id") val ownerId: Snowflake, val permissions: Optional = Optional.Missing(), - @Deprecated("The region field has been moved to Channel#rtcRegion in Discord API v9", ReplaceWith("DiscordChannel#rtcRegion")) - val region: String, - @SerialName("afk_channel_id") - val afkChannelId: Snowflake?, - @SerialName("afk_timeout") - val afkTimeout: Int, - @SerialName("widget_enabled") - val widgetEnabled: OptionalBoolean = OptionalBoolean.Missing, - @SerialName("widget_channel_id") - val widgetChannelId: OptionalSnowflake? = OptionalSnowflake.Missing, - @SerialName("verification_level") - val verificationLevel: VerificationLevel, - @SerialName("default_message_notifications") - val defaultMessageNotifications: DefaultMessageNotificationLevel, - @SerialName("explicit_content_filter") - val explicitContentFilter: ExplicitContentFilter, + @Deprecated( + "The region field has been moved to Channel#rtcRegion in Discord API v9", + ReplaceWith("DiscordChannel#rtcRegion") + ) val region: String, + @SerialName("afk_channel_id") val afkChannelId: Snowflake?, + @SerialName("afk_timeout") val afkTimeout: Int, + @SerialName("widget_enabled") val widgetEnabled: OptionalBoolean = OptionalBoolean.Missing, + @SerialName("widget_channel_id") val widgetChannelId: OptionalSnowflake? = OptionalSnowflake.Missing, + @SerialName("verification_level") val verificationLevel: VerificationLevel, + @SerialName("default_message_notifications") val defaultMessageNotifications: DefaultMessageNotificationLevel, + @SerialName("explicit_content_filter") val explicitContentFilter: ExplicitContentFilter, val roles: List, val emojis: List, val features: List, - @SerialName("mfa_level") - val mfaLevel: MFALevel, - @SerialName("application_id") - val applicationId: Snowflake?, - @SerialName("system_channel_id") - val systemChannelId: Snowflake?, - @SerialName("system_channel_flags") - val systemChannelFlags: SystemChannelFlags, - @SerialName("rules_channel_id") - val rulesChannelId: Snowflake?, - @SerialName("joined_at") - val joinedAt: Optional = Optional.Missing(), + @SerialName("mfa_level") val mfaLevel: MFALevel, + @SerialName("application_id") val applicationId: Snowflake?, + @SerialName("system_channel_id") val systemChannelId: Snowflake?, + @SerialName("system_channel_flags") val systemChannelFlags: SystemChannelFlags, + @SerialName("rules_channel_id") val rulesChannelId: Snowflake?, + @SerialName("joined_at") val joinedAt: Optional = Optional.Missing(), val large: OptionalBoolean = OptionalBoolean.Missing, val unavailable: OptionalBoolean = OptionalBoolean.Missing, - @SerialName("member_count") - val memberCount: OptionalInt = OptionalInt.Missing, - @SerialName("voice_states") - val voiceStates: Optional> = Optional.Missing(), + @SerialName("member_count") val memberCount: OptionalInt = OptionalInt.Missing, + @SerialName("voice_states") val voiceStates: Optional> = Optional.Missing(), val members: Optional> = Optional.Missing(), val channels: Optional> = Optional.Missing(), val threads: Optional> = Optional.Missing(), val presences: Optional> = Optional.Missing(), - @SerialName("max_presences") - val maxPresences: OptionalInt? = OptionalInt.Missing, - @SerialName("max_members") - val maxMembers: OptionalInt = OptionalInt.Missing, - @SerialName("vanity_url_code") - val vanityUrlCode: String?, + @SerialName("max_presences") val maxPresences: OptionalInt? = OptionalInt.Missing, + @SerialName("max_members") val maxMembers: OptionalInt = OptionalInt.Missing, + @SerialName("vanity_url_code") val vanityUrlCode: String?, val description: String?, val banner: String?, - @SerialName("premium_tier") - val premiumTier: PremiumTier, - @SerialName("premium_subscription_count") - val premiumSubscriptionCount: OptionalInt = OptionalInt.Missing, - @SerialName("preferred_locale") - val preferredLocale: String, - @SerialName("public_updates_channel_id") - val publicUpdatesChannelId: Snowflake?, - @SerialName("max_video_channel_users") - val maxVideoChannelUsers: OptionalInt = OptionalInt.Missing, - @SerialName("approximate_member_count") - val approximateMemberCount: OptionalInt = OptionalInt.Missing, - @SerialName("approximate_presence_count") - val approximatePresenceCount: OptionalInt = OptionalInt.Missing, - @SerialName("welcome_screen") - val welcomeScreen: Optional = Optional.Missing(), - @SerialName("nsfw_level") - val nsfwLevel: NsfwLevel + @SerialName("premium_tier") val premiumTier: PremiumTier, + @SerialName("premium_subscription_count") val premiumSubscriptionCount: OptionalInt = OptionalInt.Missing, + @SerialName("preferred_locale") val preferredLocale: String, + @SerialName("public_updates_channel_id") val publicUpdatesChannelId: Snowflake?, + @SerialName("max_video_channel_users") val maxVideoChannelUsers: OptionalInt = OptionalInt.Missing, + @SerialName("approximate_member_count") val approximateMemberCount: OptionalInt = OptionalInt.Missing, + @SerialName("approximate_presence_count") val approximatePresenceCount: OptionalInt = OptionalInt.Missing, + @SerialName("welcome_screen") val welcomeScreen: Optional = Optional.Missing(), + @SerialName("nsfw_level") val nsfwLevel: NsfwLevel ) /** @@ -176,9 +148,15 @@ class DiscordPartialGuild( val owner: OptionalBoolean = OptionalBoolean.Missing, val permissions: Optional = Optional.Missing(), val features: List, - @SerialName("welcome_screen") - val welcomeScreen: Optional = Optional.Missing() -) + @SerialName("welcome_screen") val welcomeScreen: Optional = Optional.Missing(), + @SerialName("vanity_url_code") val vanityUrlCode: String?, + val description: String?, + val banner: String?, + val splash: Optional = Optional.Missing(), + @SerialName("nsfw_level") val nsfwLevel: NsfwLevel, + @SerialName("verification_level") + val verificationLevel: VerificationLevel + ) /** * A representation of a [Discord Guild Feature](https://discord.com/developers/docs/resources/guild#guild-object-guild-features). @@ -332,15 +310,13 @@ enum class SystemChannelFlag(val code: Int) { @Serializable data class DiscordGuildBan( - @SerialName("guild_id") - val guildId: Snowflake, + @SerialName("guild_id") val guildId: Snowflake, val user: DiscordUser, ) @Serializable data class DiscordGuildIntegrations( - @SerialName("guild_id") - val guildId: Snowflake, + @SerialName("guild_id") val guildId: Snowflake, ) @Serializable @@ -361,17 +337,14 @@ data class DiscordIntegrationAccount( @Serializable data class DiscordVoiceServerUpdateData( val token: String, - @SerialName("guild_id") - val guildId: Snowflake, + @SerialName("guild_id") val guildId: Snowflake, val endpoint: String?, ) @Serializable data class DiscordWebhooksUpdateData( - @SerialName("guild_id") - val guildId: Snowflake, - @SerialName("channel_id") - val channelId: Snowflake, + @SerialName("guild_id") val guildId: Snowflake, + @SerialName("channel_id") val channelId: Snowflake, ) /** @@ -393,29 +366,19 @@ data class DiscordWebhooksUpdateData( */ @Serializable data class DiscordVoiceState( - @SerialName("guild_id") - val guildId: OptionalSnowflake = OptionalSnowflake.Missing, - @SerialName("channel_id") - val channelId: Snowflake?, - @SerialName("user_id") - val userId: Snowflake, - @SerialName("guild_member") - val member: Optional = Optional.Missing(), - @SerialName("session_id") - val sessionId: String, + @SerialName("guild_id") val guildId: OptionalSnowflake = OptionalSnowflake.Missing, + @SerialName("channel_id") val channelId: Snowflake?, + @SerialName("user_id") val userId: Snowflake, + @SerialName("guild_member") val member: Optional = Optional.Missing(), + @SerialName("session_id") val sessionId: String, val deaf: Boolean, val mute: Boolean, - @SerialName("self_deaf") - val selfDeaf: Boolean, - @SerialName("self_mute") - val selfMute: Boolean, - @SerialName("self_video") - val selfVideo: Boolean, - @SerialName("self_stream") - val selfStream: OptionalBoolean = OptionalBoolean.Missing, + @SerialName("self_deaf") val selfDeaf: Boolean, + @SerialName("self_mute") val selfMute: Boolean, + @SerialName("self_video") val selfVideo: Boolean, + @SerialName("self_stream") val selfStream: OptionalBoolean = OptionalBoolean.Missing, val suppress: Boolean, - @SerialName("request_to_speak_timestamp") - val requestToSpeakTimestamp: String? + @SerialName("request_to_speak_timestamp") val requestToSpeakTimestamp: String? ) /** @@ -621,18 +584,13 @@ sealed class VerificationLevel(val value: Int) { @Serializable data class DiscordWelcomeScreenChannel( - @SerialName("channel_id") - val channelId: Snowflake, + @SerialName("channel_id") val channelId: Snowflake, val description: String, - @SerialName("emoji_id") - val emojiId: Snowflake?, - @SerialName("emoji_name") - val emojiName: String? + @SerialName("emoji_id") val emojiId: Snowflake?, + @SerialName("emoji_name") val emojiName: String? ) @Serializable data class DiscordWelcomeScreen( - val description: String?, - @SerialName("welcome_channels") - val welcomeChannels: List + val description: String?, @SerialName("welcome_channels") val welcomeChannels: List ) diff --git a/core/src/main/kotlin/cache/data/PartialGuildData.kt b/core/src/main/kotlin/cache/data/PartialGuildData.kt index 5c07b31a9859..fcb881a16bc9 100644 --- a/core/src/main/kotlin/cache/data/PartialGuildData.kt +++ b/core/src/main/kotlin/cache/data/PartialGuildData.kt @@ -1,12 +1,10 @@ package dev.kord.core.cache.data -import dev.kord.common.entity.DiscordPartialGuild -import dev.kord.common.entity.GuildFeature -import dev.kord.common.entity.Permissions -import dev.kord.common.entity.Snowflake +import dev.kord.common.entity.* import dev.kord.common.entity.optional.Optional import dev.kord.common.entity.optional.OptionalBoolean import dev.kord.common.entity.optional.map +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable @@ -18,6 +16,12 @@ public class PartialGuildData( public val permissions: Optional = Optional.Missing(), public val features: List, public val welcomeScreen: Optional = Optional.Missing(), + public val vanityUrlCode: String?, + public val description: String?, + public val banner: String?, + public val splash: Optional = Optional.Missing(), + public val nsfwLevel: NsfwLevel, + public val verificationLevel: VerificationLevel, ) { public companion object { public fun from(partialGuild: DiscordPartialGuild): PartialGuildData = with(partialGuild) { @@ -28,7 +32,13 @@ public class PartialGuildData( owner, permissions, features, - welcomeScreen = welcomeScreen.map { WelcomeScreenData.from(it) }, + welcomeScreen.map { WelcomeScreenData.from(it) }, + vanityUrlCode, + description, + banner, + splash, + nsfwLevel, + verificationLevel, ) } } diff --git a/core/src/main/kotlin/entity/Guild.kt b/core/src/main/kotlin/entity/Guild.kt index 7f44a8ebc73d..02a9d7a1a421 100644 --- a/core/src/main/kotlin/entity/Guild.kt +++ b/core/src/main/kotlin/entity/Guild.kt @@ -421,7 +421,7 @@ public class Guild( * Gets the discovery splash url in the specified [format], if present. */ public fun getDiscoverySplashUrl(format: Image.Format): String? = - data.splash.value?.let { "discovery-splashes/$id/${it}.${format.extension}" } + splashHash?.let { "discovery-splashes/$id/${it}.${format.extension}" } /** * Requests to get the splash image in the specified [format], if present. diff --git a/core/src/main/kotlin/entity/PartialGuild.kt b/core/src/main/kotlin/entity/PartialGuild.kt index 686e70042db9..496519613fda 100644 --- a/core/src/main/kotlin/entity/PartialGuild.kt +++ b/core/src/main/kotlin/entity/PartialGuild.kt @@ -1,7 +1,9 @@ package dev.kord.core.entity +import dev.kord.common.entity.NsfwLevel import dev.kord.common.entity.Permissions import dev.kord.common.entity.Snowflake +import dev.kord.common.entity.VerificationLevel import dev.kord.common.entity.optional.unwrap import dev.kord.common.entity.optional.value import dev.kord.common.exception.RequestException @@ -12,6 +14,7 @@ import dev.kord.core.exception.EntityNotFoundException import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.rest.Image +import dev.kord.rest.service.RestClient import java.util.* public class PartialGuild( @@ -53,11 +56,60 @@ public class PartialGuild( public val permissions: Permissions? get() = data.permissions.value + + /** + * The vanity code of this server used in the [vanityUrl], if present. + */ + public val vanityCode: String? get() = data.vanityUrlCode + + /** + * The vanity invite URL of this server, if present. + */ + public val vanityUrl: String? get() = data.vanityUrlCode?.let { "https://discord.gg/$it" } + + /** + * The description of this guild, if present. + */ + public val description: String? get() = data.description + + + /** + * The [NSFW Level](https://discord.com/developers/docs/resources/guild#guild-object-guild-nsfw-level) of this Guild + */ + public val nsfw: NsfwLevel get() = data.nsfwLevel + + /** + * The verification level required for the guild. + */ + public val verificationLevel: VerificationLevel get() = data.verificationLevel + + public val splashHash: String? get() = data.splash.value + + + /** + * Gets the discovery splash url in the specified [format], if present. + */ + public fun getDiscoverySplashUrl(format: Image.Format): String? = + splashHash?.let { "discovery-splashes/$id/${it}.${format.extension}" } + + /** + * Requests to get the splash image in the specified [format], if present. + * + * This property is not resolvable through cache and will always use the [RestClient] instead. + */ + public suspend fun getDiscoverySplash(format: Image.Format): Image? { + val url = getDiscoverySplashUrl(format) ?: return null + + return Image.fromUrl(kord.resources.httpClient, url) + } + + /** * Gets the icon url, if present. */ public fun getIconUrl(format: Image.Format): String? = - data.icon?.let { "https://cdn.discordapp.com/icons/$id/$it.${format.extension}" } + iconHash?.let { "https://cdn.discordapp.com/icons/$id/$it.${format.extension}" } + /** * Requests to get the icon image in the specified [format], if present. @@ -68,6 +120,23 @@ public class PartialGuild( return Image.fromUrl(kord.resources.httpClient, url) } + + /** + * Gets the banner url in the specified format. + */ + public fun getBannerUrl(format: Image.Format): String? = + data.banner?.let { "https://cdn.discordapp.com/banners/$id/$it.${format.extension}" } + + /** + * Requests to get the banner image in the specified [format], if present. + */ + public suspend fun getBanner(format: Image.Format): Image? { + val url = getBannerUrl(format) ?: return null + + return Image.fromUrl(kord.resources.httpClient, url) + } + + /** * Requests to get the full [Guild] entity for this [PartialGuild]. * From ef4805551f02ce8ebe505769df157520fac3926e Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sun, 2 Jan 2022 12:09:28 +0200 Subject: [PATCH 02/21] cleanup warnings and update gradle --- common/src/main/kotlin/entity/AuditLog.kt | 8 ++-- .../interaction/ActionInteractionBehavior.kt | 4 +- .../interaction/FollowupMessageBehavior.kt | 4 +- .../InteractionResponseBehavior.kt | 12 +++--- .../PublicFollowupMessageBehavior.kt | 4 +- .../main/kotlin/cache/data/InteractionData.kt | 1 + .../interaction/ComponentInteraction.kt | 2 +- .../gateway/handler/MessageEventHandler.kt | 5 +-- core/src/test/kotlin/UtilKtTest.kt | 6 +-- .../kotlin/regression/CacheMissRegression.kt | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../src/main/kotlin/service/ChannelService.kt | 1 + rest/src/main/kotlin/service/GuildService.kt | 4 +- .../main/kotlin/service/InteractionService.kt | 39 ++----------------- voice/src/main/kotlin/gateway/Command.kt | 2 + 15 files changed, 34 insertions(+), 64 deletions(-) diff --git a/common/src/main/kotlin/entity/AuditLog.kt b/common/src/main/kotlin/entity/AuditLog.kt index 5aa69c029b7b..e14c7db7613f 100644 --- a/common/src/main/kotlin/entity/AuditLog.kt +++ b/common/src/main/kotlin/entity/AuditLog.kt @@ -155,11 +155,11 @@ data class AuditLogChange( @Suppress("UNCHECKED_CAST") override fun serialize(encoder: Encoder, value: AuditLogChange) { - val value = value as AuditLogChange + val logChange = value as AuditLogChange encoder.encodeStructure(descriptor) { - encodeSerializableElement(descriptor, 0, value.key.serializer, value.new as Unit) - encodeSerializableElement(descriptor, 0, value.key.serializer, value.old as Unit) - encodeSerializableElement(descriptor, 0, AuditLogChangeKey.serializer(Unit.serializer()), value.key) + encodeSerializableElement(descriptor, 0, logChange.key.serializer, logChange.new as Unit) + encodeSerializableElement(descriptor, 0, logChange.key.serializer, logChange.old as Unit) + encodeSerializableElement(descriptor, 0, AuditLogChangeKey.serializer(Unit.serializer()), logChange.key) } } } diff --git a/core/src/main/kotlin/behavior/interaction/ActionInteractionBehavior.kt b/core/src/main/kotlin/behavior/interaction/ActionInteractionBehavior.kt index 99f705b88627..4b374eb81f0f 100644 --- a/core/src/main/kotlin/behavior/interaction/ActionInteractionBehavior.kt +++ b/core/src/main/kotlin/behavior/interaction/ActionInteractionBehavior.kt @@ -76,8 +76,8 @@ public suspend inline fun ActionInteractionBehavior.respondEphemeral( ): EphemeralInteractionResponseBehavior { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - val builder = InteractionResponseCreateBuilder(true).apply(builder) - val request = builder.toRequest() + val appliedBuilder = InteractionResponseCreateBuilder(true).apply(builder) + val request = appliedBuilder.toRequest() kord.rest.interaction.createInteractionResponse(id, token, request) return EphemeralInteractionResponseBehavior(applicationId, token, kord) diff --git a/core/src/main/kotlin/behavior/interaction/FollowupMessageBehavior.kt b/core/src/main/kotlin/behavior/interaction/FollowupMessageBehavior.kt index 2d55ebd655db..e4ab5cf03544 100644 --- a/core/src/main/kotlin/behavior/interaction/FollowupMessageBehavior.kt +++ b/core/src/main/kotlin/behavior/interaction/FollowupMessageBehavior.kt @@ -46,7 +46,7 @@ public interface FollowupMessageBehavior : KordEntity, Strategizable { @OptIn(ExperimentalContracts::class) public suspend inline fun FollowupMessageBehavior.edit(builder: FollowupMessageModifyBuilder.() -> Unit): EphemeralFollowupMessage { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - val builder = FollowupMessageModifyBuilder().apply(builder) - val response = kord.rest.interaction.modifyFollowupMessage(applicationId, token, id, builder.toRequest()) + val appliedBuilder = FollowupMessageModifyBuilder().apply(builder) + val response = kord.rest.interaction.modifyFollowupMessage(applicationId, token, id, appliedBuilder.toRequest()) return EphemeralFollowupMessage(Message(response.toData(), kord), applicationId, token, kord) } diff --git a/core/src/main/kotlin/behavior/interaction/InteractionResponseBehavior.kt b/core/src/main/kotlin/behavior/interaction/InteractionResponseBehavior.kt index a335d18e20a5..b8710c9cf757 100644 --- a/core/src/main/kotlin/behavior/interaction/InteractionResponseBehavior.kt +++ b/core/src/main/kotlin/behavior/interaction/InteractionResponseBehavior.kt @@ -29,8 +29,8 @@ public interface InteractionResponseBehavior : KordObject { @OptIn(ExperimentalContracts::class) public suspend inline fun InteractionResponseBehavior.followUp(builder: FollowupMessageCreateBuilder.() -> Unit): PublicFollowupMessage { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - val builder = FollowupMessageCreateBuilder(false).apply(builder) - val message = kord.rest.interaction.createFollowupMessage(applicationId, token, builder.toRequest()) + val appliedBuilder = FollowupMessageCreateBuilder(false).apply(builder) + val message = kord.rest.interaction.createFollowupMessage(applicationId, token, appliedBuilder.toRequest()) return PublicFollowupMessage(Message(message.toData(), kord), applicationId, token, kord) } @@ -42,8 +42,8 @@ public suspend inline fun InteractionResponseBehavior.followUp(builder: Followup @OptIn(ExperimentalContracts::class) public suspend inline fun InteractionResponseBehavior.followUpEphemeral(builder: FollowupMessageCreateBuilder.() -> Unit): EphemeralFollowupMessage { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - val builder = FollowupMessageCreateBuilder(true).apply(builder) - val message = kord.rest.interaction.createFollowupMessage(applicationId, token, builder.toRequest()) + val appliedBuilder = FollowupMessageCreateBuilder(true).apply(builder) + val message = kord.rest.interaction.createFollowupMessage(applicationId, token, appliedBuilder.toRequest()) return EphemeralFollowupMessage(Message(message.toData(), kord), applicationId, token, kord) } @@ -58,6 +58,6 @@ public suspend inline fun InteractionResponseBehavior.followUpEphemeral(builder: @OptIn(ExperimentalContracts::class) public suspend inline fun InteractionResponseBehavior.edit(builder: InteractionResponseModifyBuilder.() -> Unit) { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - val builder = InteractionResponseModifyBuilder().apply(builder) - kord.rest.interaction.modifyInteractionResponse(applicationId, token, builder.toRequest()) + val appliedBuilder = InteractionResponseModifyBuilder().apply(builder) + kord.rest.interaction.modifyInteractionResponse(applicationId, token, appliedBuilder.toRequest()) } diff --git a/core/src/main/kotlin/behavior/interaction/PublicFollowupMessageBehavior.kt b/core/src/main/kotlin/behavior/interaction/PublicFollowupMessageBehavior.kt index 797d6201114b..122614e9b2b6 100644 --- a/core/src/main/kotlin/behavior/interaction/PublicFollowupMessageBehavior.kt +++ b/core/src/main/kotlin/behavior/interaction/PublicFollowupMessageBehavior.kt @@ -46,8 +46,8 @@ public interface PublicFollowupMessageBehavior : FollowupMessageBehavior { @OptIn(ExperimentalContracts::class) public suspend inline fun PublicFollowupMessageBehavior.edit(builder: FollowupMessageModifyBuilder.() -> Unit): PublicFollowupMessage { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - val builder = FollowupMessageModifyBuilder().apply(builder) - val response = kord.rest.interaction.modifyFollowupMessage(applicationId, token, id, builder.toRequest()) + val appliedBuilder = FollowupMessageModifyBuilder().apply(builder) + val response = kord.rest.interaction.modifyFollowupMessage(applicationId, token, id, appliedBuilder.toRequest()) return PublicFollowupMessage(Message(response.toData(), kord), applicationId, token, kord) } diff --git a/core/src/main/kotlin/cache/data/InteractionData.kt b/core/src/main/kotlin/cache/data/InteractionData.kt index ea0dc7f1195a..e5ce8c3f0b77 100644 --- a/core/src/main/kotlin/cache/data/InteractionData.kt +++ b/core/src/main/kotlin/cache/data/InteractionData.kt @@ -130,6 +130,7 @@ public data class OptionData( val name: String, @OptIn(KordExperimental::class) val value: Optional> = Optional.Missing(), + @OptIn(KordExperimental::class) val values: Optional>> = Optional.Missing(), val subCommands: Optional> = Optional.Missing(), val focused: OptionalBoolean = OptionalBoolean.Missing diff --git a/core/src/main/kotlin/entity/interaction/ComponentInteraction.kt b/core/src/main/kotlin/entity/interaction/ComponentInteraction.kt index af2df5ee7954..ddb696bb9e52 100644 --- a/core/src/main/kotlin/entity/interaction/ComponentInteraction.kt +++ b/core/src/main/kotlin/entity/interaction/ComponentInteraction.kt @@ -81,7 +81,7 @@ public fun ComponentInteraction( data: InteractionData, kord: Kord, supplier: EntitySupplier = kord.defaultSupplier, -): ComponentInteraction = when (val type = data.data.componentType.value) { +): ComponentInteraction = when (data.data.componentType.value) { ComponentType.Button -> if (data.guildId.value == null) GlobalButtonInteraction( data, kord, diff --git a/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt b/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt index 455a6deac3b3..b39c96ff7b20 100644 --- a/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt @@ -13,7 +13,6 @@ import dev.kord.core.entity.ReactionEmoji import dev.kord.core.event.message.* import dev.kord.gateway.* import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.singleOrNull import kotlinx.coroutines.flow.toSet @@ -67,8 +66,8 @@ internal class MessageEventHandler( //cache interaction user if present. if (interaction is Optional.Value) { - val userData = UserData.from(interaction.value!!.user) - cache.put(userData) + val interactionUserData = UserData.from(interaction.value!!.user) + cache.put(interactionUserData) } mentions.forEach { diff --git a/core/src/test/kotlin/UtilKtTest.kt b/core/src/test/kotlin/UtilKtTest.kt index d02506182e38..e26a6c78d3e6 100644 --- a/core/src/test/kotlin/UtilKtTest.kt +++ b/core/src/test/kotlin/UtilKtTest.kt @@ -2,7 +2,7 @@ package dev.kord.core import dev.kord.common.entity.Snowflake import kotlinx.coroutines.flow.count -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test @@ -10,7 +10,7 @@ internal class UtilKtTest { @Test @ExperimentalStdlibApi - fun `paginate forwards selects the right id`() = runBlockingTest { + fun `paginate forwards selects the right id`() = runTest { val flow = paginateForwards(start = Snowflake(0u), batchSize = 100, idSelector = { it }) { var value = it.value.value @@ -29,7 +29,7 @@ internal class UtilKtTest { @Test @ExperimentalStdlibApi - fun `paginate backwards selects the right id`() = runBlockingTest { + fun `paginate backwards selects the right id`() = runTest { val flow = paginateBackwards(start = Snowflake(1000u), batchSize = 100, idSelector = { it }) { var value = it.value.value diff --git a/core/src/test/kotlin/regression/CacheMissRegression.kt b/core/src/test/kotlin/regression/CacheMissRegression.kt index 6c2d3e3cfb46..d61bc7575199 100644 --- a/core/src/test/kotlin/regression/CacheMissRegression.kt +++ b/core/src/test/kotlin/regression/CacheMissRegression.kt @@ -37,7 +37,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.runTest import kotlinx.serialization.SerializationStrategy import kotlinx.serialization.json.Json import org.junit.jupiter.api.Test @@ -122,7 +122,7 @@ class CacheMissingRegressions { lateinit var kord: Kord @BeforeTest - fun setup() = runBlockingTest { //TODO, move this over to entity supplier tests instead, eventually. + fun setup() = runTest { //TODO, move this over to entity supplier tests instead, eventually. val token = System.getenv("KORD_TEST_TOKEN") val resources = ClientResources( token, diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c9f906b81b11..d8d3f4bdd9e7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ #Tue Dec 31 15:02:18 CET 2019 -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStorePath=wrapper/dists diff --git a/rest/src/main/kotlin/service/ChannelService.kt b/rest/src/main/kotlin/service/ChannelService.kt index f050455cb075..188a576fa871 100644 --- a/rest/src/main/kotlin/service/ChannelService.kt +++ b/rest/src/main/kotlin/service/ChannelService.kt @@ -120,6 +120,7 @@ class ChannelService(requestHandler: RequestHandler) : RestService(requestHandle suspend fun bulkDelete(channelId: Snowflake, messages: BulkDeleteRequest, reason: String?) = call(Route.BulkMessageDeletePost) { keys[Route.ChannelId] = channelId body(BulkDeleteRequest.serializer(), messages) + auditLogReason(reason) } suspend fun deleteChannel(channelId: Snowflake, reason: String? = null) = call(Route.ChannelDelete) { diff --git a/rest/src/main/kotlin/service/GuildService.kt b/rest/src/main/kotlin/service/GuildService.kt index 26cb57b3b099..cee66b467c7f 100644 --- a/rest/src/main/kotlin/service/GuildService.kt +++ b/rest/src/main/kotlin/service/GuildService.kt @@ -539,8 +539,8 @@ suspend inline fun GuildService.modifyGuildWelcomeScreen( builder: WelcomeScreenModifyBuilder.() -> Unit ): DiscordWelcomeScreen { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - val builder = WelcomeScreenModifyBuilder().apply(builder) - return modifyGuildWelcomeScreen(guildId, builder.toRequest(), builder.reason) + val appliedBuilder= WelcomeScreenModifyBuilder().apply(builder) + return modifyGuildWelcomeScreen(guildId, appliedBuilder.toRequest(), appliedBuilder.reason) } @OptIn(ExperimentalContracts::class) diff --git a/rest/src/main/kotlin/service/InteractionService.kt b/rest/src/main/kotlin/service/InteractionService.kt index 93cbdaf203f3..06c7f35f85dc 100644 --- a/rest/src/main/kotlin/service/InteractionService.kt +++ b/rest/src/main/kotlin/service/InteractionService.kt @@ -3,45 +3,13 @@ package dev.kord.rest.service import dev.kord.common.entity.* import dev.kord.common.entity.optional.Optional import dev.kord.common.entity.optional.coerceToMissing -import dev.kord.common.entity.Choice -import dev.kord.common.entity.DiscordApplicationCommand -import dev.kord.common.entity.DiscordAutoComplete -import dev.kord.common.entity.DiscordGuildApplicationCommandPermissions -import dev.kord.common.entity.DiscordMessage -import dev.kord.common.entity.InteractionResponseType -import dev.kord.common.entity.PartialDiscordGuildApplicationCommandPermissions -import dev.kord.common.entity.Snowflake import dev.kord.common.entity.optional.orEmpty -import dev.kord.rest.builder.interaction.ApplicationCommandPermissionsBulkModifyBuilder -import dev.kord.rest.builder.interaction.ApplicationCommandPermissionsModifyBuilder -import dev.kord.rest.builder.interaction.BaseChoiceBuilder -import dev.kord.rest.builder.interaction.ChatInputCreateBuilder -import dev.kord.rest.builder.interaction.ChatInputModifyBuilder -import dev.kord.rest.builder.interaction.IntChoiceBuilder -import dev.kord.rest.builder.interaction.MessageCommandCreateBuilder -import dev.kord.rest.builder.interaction.MessageCommandModifyBuilder -import dev.kord.rest.builder.interaction.MultiApplicationCommandBuilder -import dev.kord.rest.builder.interaction.NumberChoiceBuilder -import dev.kord.rest.builder.interaction.StringChoiceBuilder -import dev.kord.rest.builder.interaction.UserCommandCreateBuilder -import dev.kord.rest.builder.interaction.UserCommandModifyBuilder +import dev.kord.rest.builder.interaction.* import dev.kord.rest.builder.message.create.FollowupMessageCreateBuilder import dev.kord.rest.builder.message.create.InteractionResponseCreateBuilder import dev.kord.rest.builder.message.modify.FollowupMessageModifyBuilder import dev.kord.rest.builder.message.modify.InteractionResponseModifyBuilder -import dev.kord.rest.json.request.ApplicationCommandCreateRequest -import dev.kord.rest.json.request.ApplicationCommandModifyRequest -import dev.kord.rest.json.request.ApplicationCommandPermissionsEditRequest -import dev.kord.rest.json.request.AutoCompleteResponseCreateRequest -import dev.kord.rest.json.request.FollowupMessageCreateRequest -import dev.kord.rest.json.request.FollowupMessageModifyRequest -import dev.kord.rest.json.request.InteractionApplicationCommandCallbackData -import dev.kord.rest.json.request.InteractionResponseCreateRequest -import dev.kord.rest.json.request.InteractionResponseModifyRequest -import dev.kord.rest.json.request.MultipartFollowupMessageCreateRequest -import dev.kord.rest.json.request.MultipartFollowupMessageModifyRequest -import dev.kord.rest.json.request.MultipartInteractionResponseCreateRequest -import dev.kord.rest.json.request.MultipartInteractionResponseModifyRequest +import dev.kord.rest.json.request.* import dev.kord.rest.request.RequestHandler import dev.kord.rest.route.Route import kotlinx.serialization.KSerializer @@ -623,7 +591,6 @@ class InteractionService(requestHandler: RequestHandler) : RestService(requestHa suspend inline fun modifyInteractionResponse( applicationId: Snowflake, interactionToken: String, - ephemeral: Boolean = false, builder: InteractionResponseModifyBuilder.() -> Unit ): DiscordMessage { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } @@ -696,7 +663,7 @@ class InteractionService(requestHandler: RequestHandler) : RestService(requestHa ) } - public suspend fun acknowledge(interactionId: Snowflake, interactionToken: String, ephemeral: Boolean = false) { + suspend fun acknowledge(interactionId: Snowflake, interactionToken: String, ephemeral: Boolean = false) { val request = InteractionResponseCreateRequest( type = InteractionResponseType.DeferredChannelMessageWithSource, data = Optional( diff --git a/voice/src/main/kotlin/gateway/Command.kt b/voice/src/main/kotlin/gateway/Command.kt index 9f10ce2f1ae9..88a3016f0d8e 100644 --- a/voice/src/main/kotlin/gateway/Command.kt +++ b/voice/src/main/kotlin/gateway/Command.kt @@ -19,6 +19,7 @@ public sealed class Command { element("d", JsonObject.serializer().descriptor) } + @OptIn(KordVoice::class) override fun serialize(encoder: Encoder, value: Command) { val composite = encoder.beginStructure(descriptor) @@ -72,6 +73,7 @@ public data class SendSpeaking( val ssrc: UInt ) : Command() +@KordVoice @Serializable public data class SelectProtocol( val protocol: String, From d0a8a8e3334cb74782964bc9a2faa52832d6a999 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sun, 2 Jan 2022 12:59:22 +0200 Subject: [PATCH 03/21] make PartialGuild properties optional --- common/src/main/kotlin/entity/DiscordGuild.kt | 10 +++++----- core/src/main/kotlin/cache/data/PartialGuildData.kt | 12 +++++++----- core/src/main/kotlin/entity/PartialGuild.kt | 12 ++++++------ 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/common/src/main/kotlin/entity/DiscordGuild.kt b/common/src/main/kotlin/entity/DiscordGuild.kt index 1c95a477544a..7783e040364b 100644 --- a/common/src/main/kotlin/entity/DiscordGuild.kt +++ b/common/src/main/kotlin/entity/DiscordGuild.kt @@ -149,13 +149,13 @@ class DiscordPartialGuild( val permissions: Optional = Optional.Missing(), val features: List, @SerialName("welcome_screen") val welcomeScreen: Optional = Optional.Missing(), - @SerialName("vanity_url_code") val vanityUrlCode: String?, - val description: String?, - val banner: String?, + @SerialName("vanity_url_code") val vanityUrlCode: Optional = Optional.Missing(), + val description: Optional = Optional.Missing(), + val banner: Optional = Optional.Missing(), val splash: Optional = Optional.Missing(), - @SerialName("nsfw_level") val nsfwLevel: NsfwLevel, + @SerialName("nsfw_level") val nsfwLevel: Optional = Optional.Missing(), @SerialName("verification_level") - val verificationLevel: VerificationLevel + val verificationLevel: Optional = Optional.Missing() ) /** diff --git a/core/src/main/kotlin/cache/data/PartialGuildData.kt b/core/src/main/kotlin/cache/data/PartialGuildData.kt index fcb881a16bc9..cead06ba7e2d 100644 --- a/core/src/main/kotlin/cache/data/PartialGuildData.kt +++ b/core/src/main/kotlin/cache/data/PartialGuildData.kt @@ -16,12 +16,14 @@ public class PartialGuildData( public val permissions: Optional = Optional.Missing(), public val features: List, public val welcomeScreen: Optional = Optional.Missing(), - public val vanityUrlCode: String?, - public val description: String?, - public val banner: String?, + @SerialName("vanity_url_code") public val vanityUrlCode: Optional = Optional.Missing(), + public val description: Optional = Optional.Missing(), + public val banner: Optional = Optional.Missing(), public val splash: Optional = Optional.Missing(), - public val nsfwLevel: NsfwLevel, - public val verificationLevel: VerificationLevel, + @SerialName("nsfw_level") public val nsfwLevel: Optional = Optional.Missing(), + @SerialName("verification_level") + public val verificationLevel: Optional = Optional.Missing() + ) { public companion object { public fun from(partialGuild: DiscordPartialGuild): PartialGuildData = with(partialGuild) { diff --git a/core/src/main/kotlin/entity/PartialGuild.kt b/core/src/main/kotlin/entity/PartialGuild.kt index 496519613fda..a0f2fbabd739 100644 --- a/core/src/main/kotlin/entity/PartialGuild.kt +++ b/core/src/main/kotlin/entity/PartialGuild.kt @@ -60,28 +60,28 @@ public class PartialGuild( /** * The vanity code of this server used in the [vanityUrl], if present. */ - public val vanityCode: String? get() = data.vanityUrlCode + public val vanityCode: String? get() = data.vanityUrlCode.value /** * The vanity invite URL of this server, if present. */ - public val vanityUrl: String? get() = data.vanityUrlCode?.let { "https://discord.gg/$it" } + public val vanityUrl: String? get() = vanityCode?.let { "https://discord.gg/$it" } /** * The description of this guild, if present. */ - public val description: String? get() = data.description + public val description: String? get() = data.description.value /** * The [NSFW Level](https://discord.com/developers/docs/resources/guild#guild-object-guild-nsfw-level) of this Guild */ - public val nsfw: NsfwLevel get() = data.nsfwLevel + public val nsfw: NsfwLevel? get() = data.nsfwLevel.value /** * The verification level required for the guild. */ - public val verificationLevel: VerificationLevel get() = data.verificationLevel + public val verificationLevel: VerificationLevel? get() = data.verificationLevel.value public val splashHash: String? get() = data.splash.value @@ -125,7 +125,7 @@ public class PartialGuild( * Gets the banner url in the specified format. */ public fun getBannerUrl(format: Image.Format): String? = - data.banner?.let { "https://cdn.discordapp.com/banners/$id/$it.${format.extension}" } + data.banner.value?.let { "https://cdn.discordapp.com/banners/$id/$it.${format.extension}" } /** * Requests to get the banner image in the specified [format], if present. From 533fca61f036cd04fe61a81578e9799890dd5fcb Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 8 Jan 2022 16:45:21 +0200 Subject: [PATCH 04/21] Fix invite endpoints --- .../src/main/kotlin/entity/DiscordInvite.kt | 2 +- .../src/main/kotlin/behavior/GuildBehavior.kt | 4 +- core/src/main/kotlin/cache/data/InviteData.kt | 4 +- core/src/main/kotlin/entity/Invite.kt | 8 ++-- .../kotlin/supplier/RestEntitySupplier.kt | 46 +++++++++++++------ rest/src/main/kotlin/service/GuildService.kt | 4 ++ 6 files changed, 46 insertions(+), 22 deletions(-) diff --git a/common/src/main/kotlin/entity/DiscordInvite.kt b/common/src/main/kotlin/entity/DiscordInvite.kt index 08046fc7ac04..c38d049a9e70 100644 --- a/common/src/main/kotlin/entity/DiscordInvite.kt +++ b/common/src/main/kotlin/entity/DiscordInvite.kt @@ -10,7 +10,7 @@ import kotlinx.serialization.Serializable data class DiscordInvite( val code: String, val guild: Optional = Optional.Missing(), - val channel: DiscordChannel, + val channel: DiscordChannel?, val inviter: Optional = Optional.Missing(), @SerialName("target_user") val targetUser: Optional = Optional.Missing(), diff --git a/core/src/main/kotlin/behavior/GuildBehavior.kt b/core/src/main/kotlin/behavior/GuildBehavior.kt index 152ccec02471..c8213deac4e1 100644 --- a/core/src/main/kotlin/behavior/GuildBehavior.kt +++ b/core/src/main/kotlin/behavior/GuildBehavior.kt @@ -432,8 +432,8 @@ public interface GuildBehavior : KordEntity, Strategizable { * @throws [RequestException] if anything went wrong during the request. * @throws [EntityNotFoundException] if the [Invite] wasn't present. */ - public suspend fun getInvite(code: String, withCounts: Boolean = true): Invite = - kord.with(rest).getInvite(code, withCounts) + public suspend fun getInvite(code: String, withCounts: Boolean = true, withExpiration: Boolean = true,scheduledEventId: Snowflake? = null): Invite = + kord.with(rest).getInvite(code, withCounts, withExpiration, scheduledEventId) /** * Requests to get the [Invite] represented by the [code], diff --git a/core/src/main/kotlin/cache/data/InviteData.kt b/core/src/main/kotlin/cache/data/InviteData.kt index 7831ac3f5adc..66585f29fac0 100644 --- a/core/src/main/kotlin/cache/data/InviteData.kt +++ b/core/src/main/kotlin/cache/data/InviteData.kt @@ -10,7 +10,7 @@ import kotlinx.serialization.Serializable public data class InviteData( val code: String, val guild: Optional = Optional.Missing(), - val channelId: Snowflake, + val channelId: Snowflake?, val inviterId: OptionalSnowflake = OptionalSnowflake.Missing, val targetUserId: OptionalSnowflake = OptionalSnowflake.Missing, val targetUserType: Optional = Optional.Missing(), @@ -24,7 +24,7 @@ public data class InviteData( InviteData( code, guild = guild.map { PartialGuildData.from(it) }, - channelId = channel.id, + channelId = channel?.id, inviterId = inviter.mapSnowflake { it.id }, targetUserId = targetUser.mapSnowflake { it.id }, targetUserType, diff --git a/core/src/main/kotlin/entity/Invite.kt b/core/src/main/kotlin/entity/Invite.kt index dc029eb17bbc..f26ce458d656 100644 --- a/core/src/main/kotlin/entity/Invite.kt +++ b/core/src/main/kotlin/entity/Invite.kt @@ -33,7 +33,7 @@ public data class Invite( /** * The id of the channel this invite is associated to. */ - public val channelId: Snowflake get() = data.channelId + public val channelId: Snowflake? get() = data.channelId /** * Returns [PartialGuild] if the invite was made in a guild, or null if not. @@ -53,7 +53,7 @@ public data class Invite( /** * The behavior of the channel this invite is associated to. */ - public val channel: ChannelBehavior get() = ChannelBehavior(channelId, kord) + public val channel: ChannelBehavior? get() = channelId?.let { ChannelBehavior(it, kord) } /** @@ -87,7 +87,7 @@ public data class Invite( * @throws [RequestException] if anything went wrong during the request. * @throws [EntityNotFoundException] if the [Channel] wasn't present. */ - public suspend fun getChannel(): Channel = supplier.getChannelOf(channelId) + public suspend fun getChannel(): Channel? = channelId?.let { supplier.getChannelOf(it) } /** * Requests to get the channel this invite is for, @@ -95,7 +95,7 @@ public data class Invite( * * @throws [RequestException] if anything went wrong during the request. */ - public suspend fun getChannelOrNull(): Channel? = supplier.getChannelOfOrNull(channelId) + public suspend fun getChannelOrNull(): Channel? = channelId?.let { supplier.getChannelOfOrNull(it) } /** * Requests to get the creator of the invite for, diff --git a/core/src/main/kotlin/supplier/RestEntitySupplier.kt b/core/src/main/kotlin/supplier/RestEntitySupplier.kt index 13b9dbce620e..91fafc418989 100644 --- a/core/src/main/kotlin/supplier/RestEntitySupplier.kt +++ b/core/src/main/kotlin/supplier/RestEntitySupplier.kt @@ -273,13 +273,25 @@ public class RestEntitySupplier(public val kord: Kord) : EntitySupplier { Webhook(data, kord) } - public suspend fun getInviteOrNull(code: String, withCounts: Boolean): Invite? = catchNotFound { - val response = invite.getInvite(code, withCounts) + public suspend fun getInviteOrNull( + code: String, + withCounts: Boolean, + withExpiration: Boolean = true, + scheduledEventId: Snowflake? = null + ): Invite? = catchNotFound { + val response = invite.getInvite(code, withCounts, withExpiration, scheduledEventId) Invite(InviteData.from(response), kord) } - public suspend fun getInvite(code: String, withCounts: Boolean = true): Invite = - getInviteOrNull(code, withCounts) ?: EntityNotFoundException.inviteNotFound(code) + public suspend fun getInvite( + code: String, + withCounts: Boolean = true, + withExpiration: Boolean = true, + scheduledEventId: Snowflake? = null + ): Invite = + getInviteOrNull(code, withCounts, withExpiration, scheduledEventId) ?: EntityNotFoundException.inviteNotFound( + code + ) /** * Requests to get the information of the current application. @@ -412,7 +424,10 @@ public class RestEntitySupplier(public val kord: Kord) : EntitySupplier { return if (limit != Int.MAX_VALUE) flow.take(limit) else flow } - override fun getGuildApplicationCommands(applicationId: Snowflake, guildId: Snowflake): Flow = flow { + override fun getGuildApplicationCommands( + applicationId: Snowflake, + guildId: Snowflake + ): Flow = flow { for (command in interaction.getGuildApplicationCommands(applicationId, guildId)) { val data = ApplicationCommandData.from(command) emit(GuildApplicationCommand(data, interaction)) @@ -420,7 +435,10 @@ public class RestEntitySupplier(public val kord: Kord) : EntitySupplier { } - override suspend fun getGlobalApplicationCommandOrNull(applicationId: Snowflake, commandId: Snowflake): GlobalApplicationCommand? = catchNotFound { + override suspend fun getGlobalApplicationCommandOrNull( + applicationId: Snowflake, + commandId: Snowflake + ): GlobalApplicationCommand? = catchNotFound { val response = interaction.getGlobalCommand(applicationId, commandId) val data = ApplicationCommandData.from(response) GlobalApplicationCommand(data, interaction) @@ -433,7 +451,7 @@ public class RestEntitySupplier(public val kord: Kord) : EntitySupplier { } } - public suspend fun getOriginalInteractionOrNull(applicationId: Snowflake, token: String): Message? = catchNotFound { + public suspend fun getOriginalInteractionOrNull(applicationId: Snowflake, token: String): Message? = catchNotFound { val response = interaction.getInteractionResponse(applicationId, token) val data = MessageData.from(response) Message(data, kord) @@ -443,11 +461,12 @@ public class RestEntitySupplier(public val kord: Kord) : EntitySupplier { public suspend fun getOriginalInteraction(applicationId: Snowflake, token: String): Message { return getOriginalInteractionOrNull(applicationId, token) ?: EntityNotFoundException.interactionNotFound(token) } + override fun getGuildApplicationCommandPermissions( applicationId: Snowflake, guildId: Snowflake, ): Flow = flow { - interaction.getGuildApplicationCommandPermissions(applicationId, guildId) + interaction.getGuildApplicationCommandPermissions(applicationId, guildId) .forEach { val data = GuildApplicationCommandPermissionsData.from(it) emit(ApplicationCommandPermissions(data)) @@ -462,12 +481,13 @@ public class RestEntitySupplier(public val kord: Kord) : EntitySupplier { } } - override suspend fun getGuildScheduledEventOrNull(guildId: Snowflake, eventId: Snowflake): GuildScheduledEvent? = catchNotFound { - val event = kord.rest.guild.getScheduledEvent(guildId, eventId) - val data = GuildScheduledEventData.from(event) + override suspend fun getGuildScheduledEventOrNull(guildId: Snowflake, eventId: Snowflake): GuildScheduledEvent? = + catchNotFound { + val event = kord.rest.guild.getScheduledEvent(guildId, eventId) + val data = GuildScheduledEventData.from(event) - GuildScheduledEvent(data, kord) - } + GuildScheduledEvent(data, kord) + } override suspend fun getApplicationCommandPermissionsOrNull( applicationId: Snowflake, diff --git a/rest/src/main/kotlin/service/GuildService.kt b/rest/src/main/kotlin/service/GuildService.kt index cee66b467c7f..81151675ee85 100644 --- a/rest/src/main/kotlin/service/GuildService.kt +++ b/rest/src/main/kotlin/service/GuildService.kt @@ -530,6 +530,10 @@ class GuildService(requestHandler: RequestHandler) : RestService(requestHandler) if (withMember != null) { parameter("with_member", withMember) } + + if(position != null) { + parameter(position.key, position.value) + } } } From e7e49d6b81013a0f3d6b346c18b8bc42542841c8 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 8 Jan 2022 18:01:47 +0200 Subject: [PATCH 05/21] paginate users in scheduled events --- .../behavior/GuildScheduledEventBehavior.kt | 9 ++--- core/src/main/kotlin/cache/Query.kt | 4 +++ .../kotlin/supplier/CacheEntitySupplier.kt | 27 +++++++++++++- .../main/kotlin/supplier/EntitySupplier.kt | 24 +++++++++++++ .../kotlin/supplier/RestEntitySupplier.kt | 36 +++++++++++++++++++ rest/src/main/kotlin/service/GuildService.kt | 25 +++++++++++-- 6 files changed, 115 insertions(+), 10 deletions(-) diff --git a/core/src/main/kotlin/behavior/GuildScheduledEventBehavior.kt b/core/src/main/kotlin/behavior/GuildScheduledEventBehavior.kt index c07401f44437..a12ebd466ff7 100644 --- a/core/src/main/kotlin/behavior/GuildScheduledEventBehavior.kt +++ b/core/src/main/kotlin/behavior/GuildScheduledEventBehavior.kt @@ -27,17 +27,14 @@ import kotlin.contracts.contract public interface GuildScheduledEventBehavior : KordEntity, Strategizable { public val guildId: Snowflake + /** * Requests all the users which are interested in this event. * * @throws RequestException if anything goes wrong during the request */ - public val users: Flow get() = flow { - kord.rest.guild.getScheduledEventUsers(guildId, id).users.forEach { - val userData = UserData.from(it) - emit(User(userData, kord, supplier)) - } - } + @Deprecated("Use getUsersBefore or getUsersAfter") + public val users: Flow get() = supplier.getGuildScheduledEventUsersBefore(guildId, id) /** * Deletes this event. diff --git a/core/src/main/kotlin/cache/Query.kt b/core/src/main/kotlin/cache/Query.kt index 3b1802fd7fa8..2c2598809788 100644 --- a/core/src/main/kotlin/cache/Query.kt +++ b/core/src/main/kotlin/cache/Query.kt @@ -29,6 +29,10 @@ public fun QueryBuilder.idGt(property: KProperty1, va property.gt(value) } +public fun QueryBuilder.idLt(property: KProperty1, value: Snowflake) { + property.lt(value) +} + @JvmName("stringEq") public fun QueryBuilder.idEq(property: KProperty1, value: String?) { property.eq(value) diff --git a/core/src/main/kotlin/supplier/CacheEntitySupplier.kt b/core/src/main/kotlin/supplier/CacheEntitySupplier.kt index f34f678a6d08..1a252059406b 100644 --- a/core/src/main/kotlin/supplier/CacheEntitySupplier.kt +++ b/core/src/main/kotlin/supplier/CacheEntitySupplier.kt @@ -26,6 +26,7 @@ import dev.kord.core.cache.data.UserData import dev.kord.core.cache.data.WebhookData import dev.kord.core.cache.idEq import dev.kord.core.cache.idGt +import dev.kord.core.cache.idLt import dev.kord.core.entity.Ban import dev.kord.core.entity.Guild import dev.kord.core.entity.GuildEmoji @@ -311,7 +312,7 @@ public class CacheEntitySupplier(private val kord: Kord) : EntitySupplier { } override fun getTemplates(guildId: Snowflake): Flow