From 5b7f147982db1c8f02eb17e24341b035845c3ce2 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 24 Apr 2021 11:37:54 +0300 Subject: [PATCH 01/13] compute All --- common/src/main/kotlin/entity/Permission.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/common/src/main/kotlin/entity/Permission.kt b/common/src/main/kotlin/entity/Permission.kt index c23a1051763c..476413015e14 100644 --- a/common/src/main/kotlin/entity/Permission.kt +++ b/common/src/main/kotlin/entity/Permission.kt @@ -1,6 +1,7 @@ package dev.kord.common.entity import dev.kord.common.DiscordBitSet +import dev.kord.common.EmptyBitSet import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.descriptors.PrimitiveKind @@ -18,7 +19,7 @@ class Permissions constructor(val code: DiscordBitSet) { /** * Returns this [Permissions] as a [Set] of [Permission] */ - val values = Permission.values.filter { it.code in code }.toSet() + val values = Permission.values.filter { it.code in code }.toSet() operator fun plus(permission: Permission): Permissions = Permissions(code + permission.code) @@ -153,7 +154,8 @@ sealed class Permission(val code: DiscordBitSet) { object ManageWebhooks : Permission(0x20000000) object ManageEmojis : Permission(0x40000000) object UseSlashCommands : Permission(0x80000000) - object All : Permission(0xFFFFFDFF) + object RequestToSpeak : Permission(0x100000000) + object All : Permission(Permission.values.fold(EmptyBitSet()) { acc, value -> acc + value.code }) companion object { val values: Set @@ -189,6 +191,7 @@ sealed class Permission(val code: DiscordBitSet) { ManageWebhooks, ManageEmojis, UseSlashCommands, + RequestToSpeak ) } } From a25ee7adc004acdaa8111bc0ea78399a1540b282 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 24 Apr 2021 11:40:38 +0300 Subject: [PATCH 02/13] implement rest endpoints --- .../channel/EditGuildChannelBuilder.kt | 30 ++++++++++++ .../builder/guild/VoiceStateModifyBuilder.kt | 37 +++++++++++++++ .../kotlin/json/request/VoiceStateRequests.kt | 24 ++++++++++ rest/src/main/kotlin/route/Route.kt | 7 +++ .../src/main/kotlin/service/ChannelService.kt | 12 +++++ rest/src/main/kotlin/service/GuildService.kt | 46 +++++++++++++++++-- 6 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt create mode 100644 rest/src/main/kotlin/json/request/VoiceStateRequests.kt diff --git a/rest/src/main/kotlin/builder/channel/EditGuildChannelBuilder.kt b/rest/src/main/kotlin/builder/channel/EditGuildChannelBuilder.kt index be9c7c211b4f..448a4c16b856 100644 --- a/rest/src/main/kotlin/builder/channel/EditGuildChannelBuilder.kt +++ b/rest/src/main/kotlin/builder/channel/EditGuildChannelBuilder.kt @@ -85,6 +85,36 @@ class VoiceChannelModifyBuilder : AuditRequestBuilder } + +@KordDsl +class StageVoiceChannelModifyBuilder : AuditRequestBuilder { + override var reason: String? = null + + private var _name: Optional = Optional.Missing() + var name: String? by ::_name.delegate() + + private var _position: OptionalInt? = OptionalInt.Missing + var position: Int? by ::_position.delegate() + + private var _topic: Optional = Optional.Missing() + var topic: String? by ::_topic.delegate() + + private var _parentId: OptionalSnowflake? = OptionalSnowflake.Missing + var parentId: Snowflake? by ::_parentId.delegate() + + private var _permissionOverwrites: Optional?> = Optional.Missing() + var permissionOverwrites: MutableSet? by ::_permissionOverwrites.delegate() + + override fun toRequest(): ChannelModifyPatchRequest = ChannelModifyPatchRequest( + name = _name, + position = _position, + parentId = _parentId, + topic = _topic, + permissionOverwrites = _permissionOverwrites + ) + +} + @KordDsl class NewsChannelModifyBuilder : AuditRequestBuilder { override var reason: String? = null diff --git a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt new file mode 100644 index 000000000000..3a437c13ba08 --- /dev/null +++ b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt @@ -0,0 +1,37 @@ +package dev.kord.rest.builder.guild + +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.delegate.delegate +import dev.kord.rest.builder.RequestBuilder +import dev.kord.rest.json.request.CurrentVoiceStateModifyRequest +import dev.kord.rest.json.request.VoiceStateModifyRequest + +class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder { + + private var _requestToSpeakTimestamp: Optional = Optional.Missing() + + private var _suppress: OptionalBoolean = OptionalBoolean.Missing + + var requestToSpeakTimestamp: String? by ::_requestToSpeakTimestamp.delegate() + + var suppress: Boolean? by ::_suppress.delegate() + + + override fun toRequest(): CurrentVoiceStateModifyRequest { + return CurrentVoiceStateModifyRequest(channelId, _suppress, _requestToSpeakTimestamp) + } +} + + +class VoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder { + + private var _suppress: OptionalBoolean = OptionalBoolean.Missing + + var suppress: Boolean? by ::_suppress.delegate() + + override fun toRequest(): VoiceStateModifyRequest { + return VoiceStateModifyRequest(channelId, _suppress) + } +} \ No newline at end of file diff --git a/rest/src/main/kotlin/json/request/VoiceStateRequests.kt b/rest/src/main/kotlin/json/request/VoiceStateRequests.kt new file mode 100644 index 000000000000..0cdb775ed080 --- /dev/null +++ b/rest/src/main/kotlin/json/request/VoiceStateRequests.kt @@ -0,0 +1,24 @@ +package dev.kord.rest.json.request + +import dev.kord.common.entity.Snowflake +import dev.kord.common.entity.optional.Optional +import dev.kord.common.entity.optional.OptionalBoolean +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class CurrentVoiceStateModifyRequest( + @SerialName("channel_id") + val channelId: Snowflake, + val suppress: OptionalBoolean = OptionalBoolean.Missing, + @SerialName("request_to_speak_timestamp") + val requestToSpeakTimeStamp: Optional = Optional.Missing() +) + + +@Serializable +data class VoiceStateModifyRequest( + @SerialName("channel_id") + val channelId: Snowflake, + val suppress: OptionalBoolean = OptionalBoolean.Missing +) \ No newline at end of file diff --git a/rest/src/main/kotlin/route/Route.kt b/rest/src/main/kotlin/route/Route.kt index 704953ff6f5e..38fb000d9e3b 100644 --- a/rest/src/main/kotlin/route/Route.kt +++ b/rest/src/main/kotlin/route/Route.kt @@ -639,6 +639,13 @@ sealed class Route( NoStrategy ) + object SelfVoiceStatePatch: + Route(HttpMethod.Patch, "/guilds/${GuildId}/voice-states/@me", NoStrategy) + + + object OthersVoiceStatePatch: + Route(HttpMethod.Patch, "/guilds/${GuildId}/voice-states/${UserId}", NoStrategy) + companion object { val baseUrl = "https://discord.com/api/$restVersion" } diff --git a/rest/src/main/kotlin/service/ChannelService.kt b/rest/src/main/kotlin/service/ChannelService.kt index 721e1a019572..e1e23f701e3e 100644 --- a/rest/src/main/kotlin/service/ChannelService.kt +++ b/rest/src/main/kotlin/service/ChannelService.kt @@ -252,6 +252,18 @@ suspend inline fun ChannelService.patchVoiceChannel( return patchChannel(channelId, VoiceChannelModifyBuilder().apply(builder).toRequest()) } + +@OptIn(ExperimentalContracts::class) +suspend inline fun ChannelService.patchStageVoiceChannel( + channelId: Snowflake, + builder: StageVoiceChannelModifyBuilder.() -> Unit +): DiscordChannel { + contract { + callsInPlace(builder, InvocationKind.EXACTLY_ONCE) + } + return patchChannel(channelId, StageVoiceChannelModifyBuilder().apply(builder).toRequest()) +} + @OptIn(ExperimentalContracts::class) suspend inline fun ChannelService.patchStoreChannel( channelId: Snowflake, diff --git a/rest/src/main/kotlin/service/GuildService.kt b/rest/src/main/kotlin/service/GuildService.kt index 13a1cb2783b2..ffafff1770f0 100644 --- a/rest/src/main/kotlin/service/GuildService.kt +++ b/rest/src/main/kotlin/service/GuildService.kt @@ -5,10 +5,7 @@ import dev.kord.common.annotation.KordExperimental import dev.kord.common.entity.* import dev.kord.rest.builder.ban.BanCreateBuilder import dev.kord.rest.builder.channel.* -import dev.kord.rest.builder.guild.GuildCreateBuilder -import dev.kord.rest.builder.guild.GuildModifyBuilder -import dev.kord.rest.builder.guild.GuildWidgetModifyBuilder -import dev.kord.rest.builder.guild.WelcomeScreenModifyBuilder +import dev.kord.rest.builder.guild.* import dev.kord.rest.builder.integration.IntegrationModifyBuilder import dev.kord.rest.builder.member.MemberAddBuilder import dev.kord.rest.builder.member.MemberModifyBuilder @@ -387,6 +384,22 @@ class GuildService(requestHandler: RequestHandler) : RestService(requestHandler) body(GuildWelcomeScreenModifyRequest.serializer(), request) } + + suspend fun modifyCurrentVoiceState(guildId: Snowflake, request: CurrentVoiceStateModifyRequest) = + call(Route.SelfVoiceStatePatch) { + keys[Route.GuildId] = guildId + body(CurrentVoiceStateModifyRequest.serializer(), request) + } + + + suspend fun modifyVoiceState(guildId: Snowflake, userId: Snowflake, request: VoiceStateModifyRequest) = + call(Route.SelfVoiceStatePatch) { + keys[Route.GuildId] = guildId + keys[Route.UserId] = userId + body(VoiceStateModifyRequest.serializer(), request) + } + + } @OptIn(ExperimentalContracts::class) @@ -442,3 +455,28 @@ suspend inline fun GuildService.createCategory( val createBuilder = CategoryCreateBuilder(name).apply(builder) return createGuildChannel(guildId, createBuilder.toRequest(), createBuilder.reason) } + + +@OptIn(ExperimentalContracts::class) +suspend inline fun GuildService.modifyCurrentVoiceState( + guildId: Snowflake, + channelId: Snowflake, + builder: CurrentVoiceStateModifyBuilder.() -> Unit +) { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + val modifyBuilder = CurrentVoiceStateModifyBuilder(channelId).apply(builder) + modifyCurrentVoiceState(guildId, modifyBuilder.toRequest()) +} + + +@OptIn(ExperimentalContracts::class) +suspend inline fun GuildService.modifyVoiceState( + guildId: Snowflake, + channelId: Snowflake, + userId: Snowflake, + builder: VoiceStateModifyBuilder.() -> Unit +) { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + val modifyBuilder = VoiceStateModifyBuilder(channelId).apply(builder) + modifyVoiceState(guildId, userId, modifyBuilder.toRequest()) +} From 7a3803684ab7bff44ed77b2c8293addd8a6dbe09 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 24 Apr 2021 11:43:48 +0300 Subject: [PATCH 03/13] json representation --- common/src/main/kotlin/entity/DiscordChannel.kt | 3 +++ common/src/main/kotlin/entity/DiscordGuild.kt | 2 ++ core/src/main/kotlin/cache/data/VoiceStateData.kt | 8 ++++---- core/src/main/kotlin/entity/VoiceState.kt | 2 ++ core/src/main/kotlin/entity/channel/Channel.kt | 1 + 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/common/src/main/kotlin/entity/DiscordChannel.kt b/common/src/main/kotlin/entity/DiscordChannel.kt index 3d96a0c5e8cd..5fb9f3f522d5 100644 --- a/common/src/main/kotlin/entity/DiscordChannel.kt +++ b/common/src/main/kotlin/entity/DiscordChannel.kt @@ -94,6 +94,8 @@ sealed class ChannelType(val value: Int) { /** A channel in which game developers can sell their game on Discord. */ object GuildStore : ChannelType(6) + object GuildStageVoice : ChannelType(13) + companion object; internal object Serializer : KSerializer { @@ -108,6 +110,7 @@ sealed class ChannelType(val value: Int) { 4 -> GuildCategory 5 -> GuildNews 6 -> GuildStore + 13 -> GuildStageVoice else -> Unknown(code) } diff --git a/common/src/main/kotlin/entity/DiscordGuild.kt b/common/src/main/kotlin/entity/DiscordGuild.kt index 7893fdfba282..914c584b7429 100644 --- a/common/src/main/kotlin/entity/DiscordGuild.kt +++ b/common/src/main/kotlin/entity/DiscordGuild.kt @@ -372,6 +372,8 @@ data class DiscordVoiceState( @SerialName("self_stream") val selfStream: OptionalBoolean = OptionalBoolean.Missing, val suppress: Boolean, + @SerialName("request_to_speak_timestamp") + val requestToSpeakTimestamp: String? ) /** diff --git a/core/src/main/kotlin/cache/data/VoiceStateData.kt b/core/src/main/kotlin/cache/data/VoiceStateData.kt index 73d702d410f4..5084b07a5e53 100644 --- a/core/src/main/kotlin/cache/data/VoiceStateData.kt +++ b/core/src/main/kotlin/cache/data/VoiceStateData.kt @@ -1,10 +1,8 @@ package dev.kord.core.cache.data import dev.kord.cache.api.data.description -import dev.kord.common.entity.DiscordGuildMember import dev.kord.common.entity.DiscordVoiceState 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 dev.kord.common.entity.optional.mapSnowflake @@ -31,7 +29,8 @@ data class VoiceStateData( val selfMute: Boolean, val selfStream: OptionalBoolean = OptionalBoolean.Missing, val suppress: Boolean, -) { + val requestToSpeakTimestamp: String? + ) { companion object { val description = description(VoiceStateData::id) @@ -48,7 +47,8 @@ data class VoiceStateData( selfDeaf = selfDeaf, selfMute = selfMute, selfStream = selfStream, - suppress = suppress + suppress = suppress, + requestToSpeakTimestamp = requestToSpeakTimestamp ) } } diff --git a/core/src/main/kotlin/entity/VoiceState.kt b/core/src/main/kotlin/entity/VoiceState.kt index a8927beefdfe..bd5009b5c32a 100644 --- a/core/src/main/kotlin/entity/VoiceState.kt +++ b/core/src/main/kotlin/entity/VoiceState.kt @@ -36,6 +36,8 @@ class VoiceState( val isSuppressed: Boolean get() = data.suppress + val requestToSpeakTimestamp: String? get() = data.requestToSpeakTimestamp + /** * Whether this user is streaming using "Go Live". */ diff --git a/core/src/main/kotlin/entity/channel/Channel.kt b/core/src/main/kotlin/entity/channel/Channel.kt index f2c9bc84a9bf..b391501fa16d 100644 --- a/core/src/main/kotlin/entity/channel/Channel.kt +++ b/core/src/main/kotlin/entity/channel/Channel.kt @@ -42,6 +42,7 @@ interface Channel : ChannelBehavior { ): Channel = when (data.type) { GuildText -> TextChannel(data, kord) DM, GroupDM -> DmChannel(data, kord) + GuildStageVoice -> StageChannel(data, kord) GuildVoice -> VoiceChannel(data, kord) GuildCategory -> Category(data, kord) GuildNews -> NewsChannel(data, kord) From f1f4d6827f8bf89a7abd168802c9ce0f70045f9e Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 24 Apr 2021 11:53:53 +0300 Subject: [PATCH 04/13] implement core representation --- .../channel/BaseVoiceChannelBehavior.kt | 26 +++++++ .../behavior/channel/StageChannelBehavior.kt | 76 +++++++++++++++++++ .../behavior/channel/VoiceChannelBehavior.kt | 22 +----- .../entity/channel/StageVoiceChannel.kt | 50 ++++++++++++ 4 files changed, 153 insertions(+), 21 deletions(-) create mode 100644 core/src/main/kotlin/behavior/channel/BaseVoiceChannelBehavior.kt create mode 100644 core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt create mode 100644 core/src/main/kotlin/entity/channel/StageVoiceChannel.kt diff --git a/core/src/main/kotlin/behavior/channel/BaseVoiceChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/BaseVoiceChannelBehavior.kt new file mode 100644 index 000000000000..4167f1ecc488 --- /dev/null +++ b/core/src/main/kotlin/behavior/channel/BaseVoiceChannelBehavior.kt @@ -0,0 +1,26 @@ +package dev.kord.core.behavior.channel + +import dev.kord.cache.api.query +import dev.kord.common.exception.RequestException +import dev.kord.core.cache.data.VoiceStateData +import dev.kord.core.cache.idEq +import dev.kord.core.entity.VoiceState +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +interface BaseVoiceChannelBehavior : GuildChannelBehavior { + + /** + * Requests to retrieve the present voice states of this channel. + * + * This property is not resolvable through REST and will always use [KordCache] instead. + * + * 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. + */ + val voiceStates: Flow + get() = kord.cache.query { idEq(VoiceStateData::channelId, id) } + .asFlow() + .map { VoiceState(it, kord) } + +} \ No newline at end of file diff --git a/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt new file mode 100644 index 000000000000..99566742daac --- /dev/null +++ b/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt @@ -0,0 +1,76 @@ +package dev.kord.core.behavior.channel + +import dev.kord.common.entity.Snowflake +import dev.kord.core.Kord +import dev.kord.core.cache.data.ChannelData +import dev.kord.core.entity.channel.Channel +import dev.kord.core.entity.channel.StageChannel +import dev.kord.core.supplier.EntitySupplier +import dev.kord.core.supplier.EntitySupplyStrategy +import dev.kord.rest.builder.channel.StageVoiceChannelModifyBuilder +import dev.kord.rest.builder.guild.CurrentVoiceStateModifyBuilder +import dev.kord.rest.builder.guild.VoiceStateModifyBuilder +import dev.kord.rest.service.modifyCurrentVoiceState +import dev.kord.rest.service.modifyVoiceState +import dev.kord.rest.service.patchStageVoiceChannel +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +interface StageChannelBehavior : BaseVoiceChannelBehavior { + + override fun withStrategy( + strategy: EntitySupplyStrategy<*> + ): StageChannelBehavior { + return StageChannelBehavior(id, guildId, kord, strategy.supply(kord)) + } + + fun StageChannelBehavior( + id: Snowflake, + guildId: Snowflake, + kord: Kord, + supplier: EntitySupplier = kord.defaultSupplier + ): StageChannelBehavior = object : StageChannelBehavior { + override val guildId: Snowflake get() = guildId + override val id: Snowflake get() = id + override val kord get() = kord + override val supplier get() = supplier + } +} + +@OptIn(ExperimentalContracts::class) +suspend inline fun StageChannelBehavior.editCurrentVoiceState(builder: CurrentVoiceStateModifyBuilder.() -> Unit) { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + kord.rest.guild.modifyCurrentVoiceState(guildId, id, builder) +} + +@OptIn(ExperimentalContracts::class) +suspend inline fun StageChannelBehavior.editVoiceState( + userId: Snowflake, + builder: VoiceStateModifyBuilder.() -> Unit +) { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + kord.rest.guild.modifyVoiceState(guildId, id, userId, builder) +} + +@OptIn(ExperimentalContracts::class) +suspend fun StageChannelBehavior.edit(builder: StageVoiceChannelModifyBuilder.() -> Unit): StageChannel { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + val response = kord.rest.channel.patchStageVoiceChannel(id, builder) + + val data = ChannelData.from(response) + return Channel.from(data, kord) as StageChannel +} + +fun StageChannelBehavior( + id: Snowflake, + guildId: Snowflake, + kord: Kord, + supplier: EntitySupplier = kord.defaultSupplier +): StageChannelBehavior = object : StageChannelBehavior { + override val guildId: Snowflake + get() = guildId + override val kord get() = kord + override val id: Snowflake get() = id + override val supplier get() = supplier +} \ No newline at end of file diff --git a/core/src/main/kotlin/behavior/channel/VoiceChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/VoiceChannelBehavior.kt index 54c29c86d22c..7a052f4cb95b 100644 --- a/core/src/main/kotlin/behavior/channel/VoiceChannelBehavior.kt +++ b/core/src/main/kotlin/behavior/channel/VoiceChannelBehavior.kt @@ -1,14 +1,9 @@ package dev.kord.core.behavior.channel -import dev.kord.cache.api.query - import dev.kord.common.entity.Snowflake import dev.kord.common.exception.RequestException import dev.kord.core.Kord import dev.kord.core.cache.data.ChannelData -import dev.kord.core.cache.data.VoiceStateData -import dev.kord.core.cache.idEq -import dev.kord.core.entity.VoiceState import dev.kord.core.entity.channel.Channel import dev.kord.core.entity.channel.VoiceChannel import dev.kord.core.exception.EntityNotFoundException @@ -17,8 +12,6 @@ import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.rest.builder.channel.VoiceChannelModifyBuilder import dev.kord.rest.request.RestRequestException import dev.kord.rest.service.patchVoiceChannel -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.map import java.util.* import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind @@ -27,20 +20,7 @@ import kotlin.contracts.contract /** * The behavior of a Discord Voice Channel associated to a guild. */ -interface VoiceChannelBehavior : GuildChannelBehavior { - - /** - * Requests to retrieve the present voice states of this channel. - * - * This property is not resolvable through REST and will always use [KordCache] instead. - * - * 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. - */ - val voiceStates: Flow - get() = kord.cache.query { idEq(VoiceStateData::channelId, id) } - .asFlow() - .map { VoiceState(it, kord) } +interface VoiceChannelBehavior : BaseVoiceChannelBehavior { /** * Requests to get the this behavior as a [VoiceChannel]. diff --git a/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt b/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt new file mode 100644 index 000000000000..02e538709a94 --- /dev/null +++ b/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt @@ -0,0 +1,50 @@ +package dev.kord.core.entity.channel + +import dev.kord.common.entity.optional.getOrThrow +import dev.kord.core.Kord +import dev.kord.core.behavior.channel.ChannelBehavior +import dev.kord.core.behavior.channel.GuildChannelBehavior +import dev.kord.core.behavior.channel.StageChannelBehavior +import dev.kord.core.cache.data.ChannelData +import dev.kord.core.supplier.EntitySupplier +import dev.kord.core.supplier.EntitySupplyStrategy +import java.util.* + +class StageChannel( + override val data: ChannelData, + override val kord: Kord, + override val supplier: EntitySupplier = kord.defaultSupplier +) : CategorizableChannel, StageChannelBehavior { + + /** + * The bitrate (in bits) of this channel. + */ + val bitrate: Int get() = data.bitrate.getOrThrow() + + /** + * The user limit of the voice channel. + */ + val userLimit: Int get() = data.userLimit.getOrThrow() + + /** + * returns a new [StageChannel] with the given [strategy]. + * + * @param strategy the strategy to use for the new instance. By default [EntitySupplyStrategy.CacheWithRestFallback]. + */ + override fun withStrategy(strategy: EntitySupplyStrategy<*>): StageChannel = + StageChannel(data, kord, strategy.supply(kord)) + + override suspend fun asChannel(): StageChannel = this + + override fun hashCode(): Int = Objects.hash(id, guildId) + + override fun equals(other: Any?): Boolean = when (other) { + is GuildChannelBehavior -> other.id == id && other.guildId == guildId + is ChannelBehavior -> other.id == id + else -> false + } + + override fun toString(): String { + return "VoiceChannel(data=$data, kord=$kord, supplier=$supplier)" + } +} \ No newline at end of file From d346d5fd1c918c7d15f95e5d1f8b50df07cf85c7 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 24 Apr 2021 11:54:11 +0300 Subject: [PATCH 05/13] handle stage channels --- core/src/main/kotlin/event/channel/ChannelCreateEvent.kt | 7 +++++++ core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt | 6 ++++++ core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt | 7 +++++++ .../src/main/kotlin/gateway/handler/ChannelEventHandler.kt | 3 +++ 4 files changed, 23 insertions(+) diff --git a/core/src/main/kotlin/event/channel/ChannelCreateEvent.kt b/core/src/main/kotlin/event/channel/ChannelCreateEvent.kt index 560f497dd71f..c43203c00628 100644 --- a/core/src/main/kotlin/event/channel/ChannelCreateEvent.kt +++ b/core/src/main/kotlin/event/channel/ChannelCreateEvent.kt @@ -46,6 +46,13 @@ class VoiceChannelCreateEvent(override val channel: VoiceChannel, override val s } } + +class StageChannelCreateEvent(override val channel: StageChannel, override val shard: Int) : ChannelCreateEvent { + override fun toString(): String { + return "StageChannelCreateEvent(channel=$channel, shard=$shard)" + } +} + class UnknownChannelCreateEvent(override val channel: Channel, override val shard: Int) : ChannelCreateEvent { override fun toString(): String { return "UnknownChannelCreateEvent(channel=$channel, shard=$shard)" diff --git a/core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt b/core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt index 5345f62b75a4..08b8993721b1 100644 --- a/core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt +++ b/core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt @@ -46,6 +46,12 @@ class VoiceChannelDeleteEvent(override val channel: VoiceChannel, override val s } } +class StageChannelDeleteEvent(override val channel: StageChannel, override val shard: Int) : ChannelDeleteEvent { + override fun toString(): String { + return "StageChannelDeleteEvent(channel=$channel, shard=$shard)" + } +} + class UnknownChannelDeleteEvent(override val channel: Channel, override val shard: Int) : ChannelCreateEvent { override fun toString(): String { diff --git a/core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt b/core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt index bb6db1e141f9..a87316e07a48 100644 --- a/core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt +++ b/core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt @@ -47,6 +47,13 @@ class VoiceChannelUpdateEvent(override val channel: VoiceChannel, override val s } +class StageChannelUpdateEvent(override val channel: StageChannel, override val shard: Int) : ChannelUpdateEvent { + override fun toString(): String { + return "StageChannelUpdateEvent(channel=$channel, shard=$shard)" + } +} + + class UnknownChannelUpdateEvent(override val channel: Channel, override val shard: Int) : ChannelCreateEvent { override fun toString(): String { return "UnknownChannelUpdateEvent(channel=$channel, shard=$shard)" diff --git a/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt b/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt index eed6c8bb642a..c2c23010f721 100644 --- a/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt @@ -43,6 +43,7 @@ internal class ChannelEventHandler( is StoreChannel -> StoreChannelCreateEvent(channel, shard) is DmChannel -> DMChannelCreateEvent(channel, shard) is TextChannel -> TextChannelCreateEvent(channel, shard) + is StageChannel -> StageChannelCreateEvent(channel, shard) is VoiceChannel -> VoiceChannelCreateEvent(channel, shard) is Category -> CategoryCreateEvent(channel, shard) else -> UnknownChannelCreateEvent(channel, shard) @@ -60,6 +61,7 @@ internal class ChannelEventHandler( is StoreChannel -> StoreChannelUpdateEvent(channel, shard) is DmChannel -> DMChannelUpdateEvent(channel, shard) is TextChannel -> TextChannelUpdateEvent(channel, shard) + is StageChannel -> StageChannelUpdateEvent(channel, shard) is VoiceChannel -> VoiceChannelUpdateEvent(channel, shard) is Category -> CategoryUpdateEvent(channel, shard) else -> UnknownChannelUpdateEvent(channel, shard) @@ -77,6 +79,7 @@ internal class ChannelEventHandler( is StoreChannel -> StoreChannelDeleteEvent(channel, shard) is DmChannel -> DMChannelDeleteEvent(channel, shard) is TextChannel -> TextChannelDeleteEvent(channel, shard) + is StageChannel -> StageChannelDeleteEvent(channel, shard) is VoiceChannel -> VoiceChannelDeleteEvent(channel, shard) is Category -> CategoryDeleteEvent(channel, shard) else -> UnknownChannelDeleteEvent(channel, shard) From 6026ea5c2d721b1d2a2f61082be202d10267584c Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 24 Apr 2021 21:32:25 +0300 Subject: [PATCH 06/13] Apply suggestions Co-authored-by: BartArys --- .../kotlin/behavior/channel/StageChannelBehavior.kt | 2 +- core/src/main/kotlin/cache/data/VoiceStateData.kt | 3 +-- .../main/kotlin/entity/channel/StageVoiceChannel.kt | 4 ++-- .../kotlin/builder/guild/VoiceStateModifyBuilder.kt | 10 ++++++---- .../src/main/kotlin/json/request/VoiceStateRequests.kt | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt index 99566742daac..ac9214a033ff 100644 --- a/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt +++ b/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt @@ -73,4 +73,4 @@ fun StageChannelBehavior( override val kord get() = kord override val id: Snowflake get() = id override val supplier get() = supplier -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/cache/data/VoiceStateData.kt b/core/src/main/kotlin/cache/data/VoiceStateData.kt index 5084b07a5e53..5d580fa53ed1 100644 --- a/core/src/main/kotlin/cache/data/VoiceStateData.kt +++ b/core/src/main/kotlin/cache/data/VoiceStateData.kt @@ -6,7 +6,6 @@ import dev.kord.common.entity.Snowflake import dev.kord.common.entity.optional.OptionalBoolean import dev.kord.common.entity.optional.OptionalSnowflake import dev.kord.common.entity.optional.mapSnowflake -import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable val VoiceStateData.id get() = "$userId$guildId" @@ -30,7 +29,7 @@ data class VoiceStateData( val selfStream: OptionalBoolean = OptionalBoolean.Missing, val suppress: Boolean, val requestToSpeakTimestamp: String? - ) { +) { companion object { val description = description(VoiceStateData::id) diff --git a/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt b/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt index 02e538709a94..9beb4a65072c 100644 --- a/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt +++ b/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt @@ -45,6 +45,6 @@ class StageChannel( } override fun toString(): String { - return "VoiceChannel(data=$data, kord=$kord, supplier=$supplier)" + return "StageChannel(data=$data, kord=$kord, supplier=$supplier)" } -} \ No newline at end of file +} diff --git a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt index 3a437c13ba08..a05a9d2b33cc 100644 --- a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt +++ b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt @@ -4,23 +4,25 @@ 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.delegate.delegate +import dev.kord.common.entity.optional.map import dev.kord.rest.builder.RequestBuilder import dev.kord.rest.json.request.CurrentVoiceStateModifyRequest import dev.kord.rest.json.request.VoiceStateModifyRequest +import java.time.LocalDateTime class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder { - private var _requestToSpeakTimestamp: Optional = Optional.Missing() + private var _requestToSpeakTimestamp: Optional = Optional.Missing() private var _suppress: OptionalBoolean = OptionalBoolean.Missing - var requestToSpeakTimestamp: String? by ::_requestToSpeakTimestamp.delegate() + var requestToSpeakTimestamp: LocalDateTime? by ::_requestToSpeakTimestamp.delegate() var suppress: Boolean? by ::_suppress.delegate() override fun toRequest(): CurrentVoiceStateModifyRequest { - return CurrentVoiceStateModifyRequest(channelId, _suppress, _requestToSpeakTimestamp) + return CurrentVoiceStateModifyRequest(channelId, _suppress, _requestToSpeakTimestamp.map { it.toString() }) } } @@ -34,4 +36,4 @@ class VoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder Date: Sat, 24 Apr 2021 21:43:57 +0300 Subject: [PATCH 07/13] Remove duplicated factory function Co-authored-by: BartArys --- .../kotlin/behavior/channel/StageChannelBehavior.kt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt index ac9214a033ff..492170b37a6d 100644 --- a/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt +++ b/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt @@ -25,17 +25,6 @@ interface StageChannelBehavior : BaseVoiceChannelBehavior { return StageChannelBehavior(id, guildId, kord, strategy.supply(kord)) } - fun StageChannelBehavior( - id: Snowflake, - guildId: Snowflake, - kord: Kord, - supplier: EntitySupplier = kord.defaultSupplier - ): StageChannelBehavior = object : StageChannelBehavior { - override val guildId: Snowflake get() = guildId - override val id: Snowflake get() = id - override val kord get() = kord - override val supplier get() = supplier - } } @OptIn(ExperimentalContracts::class) From ad8a46643a0ff7b3b3d5e90ddbb5ede0051657fe Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Sat, 24 Apr 2021 22:24:52 +0300 Subject: [PATCH 08/13] add documentation --- .../behavior/channel/StageChannelBehavior.kt | 22 +++++++++++++++++++ .../entity/channel/StageVoiceChannel.kt | 4 ++++ .../builder/guild/VoiceStateModifyBuilder.kt | 9 ++++++++ 3 files changed, 35 insertions(+) diff --git a/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt index 492170b37a6d..2d93dcc7bd79 100644 --- a/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt +++ b/core/src/main/kotlin/behavior/channel/StageChannelBehavior.kt @@ -5,11 +5,13 @@ import dev.kord.core.Kord import dev.kord.core.cache.data.ChannelData import dev.kord.core.entity.channel.Channel import dev.kord.core.entity.channel.StageChannel +import dev.kord.core.entity.channel.VoiceChannel import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.rest.builder.channel.StageVoiceChannelModifyBuilder import dev.kord.rest.builder.guild.CurrentVoiceStateModifyBuilder import dev.kord.rest.builder.guild.VoiceStateModifyBuilder +import dev.kord.rest.request.RestRequestException import dev.kord.rest.service.modifyCurrentVoiceState import dev.kord.rest.service.modifyVoiceState import dev.kord.rest.service.patchStageVoiceChannel @@ -19,6 +21,9 @@ import kotlin.contracts.contract interface StageChannelBehavior : BaseVoiceChannelBehavior { + /** + * Returns a new [StageChannelBehavior] with the given [strategy]. + */ override fun withStrategy( strategy: EntitySupplyStrategy<*> ): StageChannelBehavior { @@ -27,12 +32,18 @@ interface StageChannelBehavior : BaseVoiceChannelBehavior { } +/** + * Requests to edit the current user's voice state in this [StageChannel]. + */ @OptIn(ExperimentalContracts::class) suspend inline fun StageChannelBehavior.editCurrentVoiceState(builder: CurrentVoiceStateModifyBuilder.() -> Unit) { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } kord.rest.guild.modifyCurrentVoiceState(guildId, id, builder) } +/** + * Requests to edit the another user's voice state in this [StageChannel]. + */ @OptIn(ExperimentalContracts::class) suspend inline fun StageChannelBehavior.editVoiceState( userId: Snowflake, @@ -42,6 +53,13 @@ suspend inline fun StageChannelBehavior.editVoiceState( kord.rest.guild.modifyVoiceState(guildId, id, userId, builder) } +/** + * Requests to edit this channel. + * + * @return The edited [StageChannel]. + * + * @throws [RestRequestException] if something went wrong during the request. + */ @OptIn(ExperimentalContracts::class) suspend fun StageChannelBehavior.edit(builder: StageVoiceChannelModifyBuilder.() -> Unit): StageChannel { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } @@ -62,4 +80,8 @@ fun StageChannelBehavior( override val kord get() = kord override val id: Snowflake get() = id override val supplier get() = supplier + + override fun toString(): String { + return "StageChannelBehavior(id=$id, guildId=$guildId, kord=$kord, supplier=$supplier)" + } } diff --git a/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt b/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt index 9beb4a65072c..e7f35962f6de 100644 --- a/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt +++ b/core/src/main/kotlin/entity/channel/StageVoiceChannel.kt @@ -10,6 +10,10 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import java.util.* +/** + * An instance of a [Discord Stage Channel](https://support.discord.com/hc/en-us/articles/1500005513722) + * associated to a community guild. + */ class StageChannel( override val data: ChannelData, override val kord: Kord, diff --git a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt index a05a9d2b33cc..489c1483ec4e 100644 --- a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt +++ b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt @@ -16,8 +16,14 @@ class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder< private var _suppress: OptionalBoolean = OptionalBoolean.Missing + /** + * sets the user's request to speak. + */ var requestToSpeakTimestamp: LocalDateTime? by ::_requestToSpeakTimestamp.delegate() + /** + * whether this user is muted by the current user. + */ var suppress: Boolean? by ::_suppress.delegate() @@ -31,6 +37,9 @@ class VoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder Date: Sun, 25 Apr 2021 20:32:55 +0300 Subject: [PATCH 09/13] Use OffsetDateTime instead of LocalDateTime --- .../main/kotlin/builder/guild/VoiceStateModifyBuilder.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt index 489c1483ec4e..a8c7a8bb096e 100644 --- a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt +++ b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt @@ -8,18 +8,18 @@ import dev.kord.common.entity.optional.map import dev.kord.rest.builder.RequestBuilder import dev.kord.rest.json.request.CurrentVoiceStateModifyRequest import dev.kord.rest.json.request.VoiceStateModifyRequest -import java.time.LocalDateTime +import java.time.OffsetDateTime class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder { - private var _requestToSpeakTimestamp: Optional = Optional.Missing() + private var _requestToSpeakTimestamp: Optional = Optional.Missing() private var _suppress: OptionalBoolean = OptionalBoolean.Missing /** * sets the user's request to speak. */ - var requestToSpeakTimestamp: LocalDateTime? by ::_requestToSpeakTimestamp.delegate() + var requestToSpeakTimestamp: OffsetDateTime? by ::_requestToSpeakTimestamp.delegate() /** * whether this user is muted by the current user. From 8688d7c1aff3b31b1f174d67fb445d6f069f1194 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Mon, 26 Apr 2021 14:10:20 +0300 Subject: [PATCH 10/13] Document the requestToSpeak variable --- .../main/kotlin/builder/guild/VoiceStateModifyBuilder.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt index a8c7a8bb096e..daceec344343 100644 --- a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt +++ b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt @@ -17,7 +17,12 @@ class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder< private var _suppress: OptionalBoolean = OptionalBoolean.Missing /** - * sets the user's request to speak. + * Sets the user's request to speak. + * The timestamp is used to sort how users appear on the moderators request list. + * e.g: A client who requested to speak at 18:00, + * will appear above a client who requested to speak at 20:00 in the same timezone. + * A date in the past is treated as "now" by Discord. + * A null value removes the request to speak. */ var requestToSpeakTimestamp: OffsetDateTime? by ::_requestToSpeakTimestamp.delegate() From af0235890f12b158ae0fa3c073a4fc2c244c7c58 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Mon, 26 Apr 2021 14:18:15 +0300 Subject: [PATCH 11/13] Add spaces --- rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt index daceec344343..e4605343795e 100644 --- a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt +++ b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt @@ -19,8 +19,10 @@ class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder< /** * Sets the user's request to speak. * The timestamp is used to sort how users appear on the moderators request list. + * * e.g: A client who requested to speak at 18:00, * will appear above a client who requested to speak at 20:00 in the same timezone. + * * A date in the past is treated as "now" by Discord. * A null value removes the request to speak. */ From b4c399b618322b64825517205f9bc639af9544a9 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Mon, 26 Apr 2021 14:20:16 +0300 Subject: [PATCH 12/13] improve docs [ci skip] --- rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt index e4605343795e..99e7347e257c 100644 --- a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt +++ b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt @@ -23,8 +23,8 @@ class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder< * e.g: A client who requested to speak at 18:00, * will appear above a client who requested to speak at 20:00 in the same timezone. * - * A date in the past is treated as "now" by Discord. - * A null value removes the request to speak. + * * A date in the past is treated as "now" by Discord. + * * A null value removes the request to speak. */ var requestToSpeakTimestamp: OffsetDateTime? by ::_requestToSpeakTimestamp.delegate() From 4feb9440c25f642517685ee6274d6ad90ba99630 Mon Sep 17 00:00:00 2001 From: HopeBaron Date: Mon, 26 Apr 2021 15:12:19 +0300 Subject: [PATCH 13/13] use Instant instead of OffsetDateTime --- .../main/kotlin/builder/guild/VoiceStateModifyBuilder.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt index 99e7347e257c..0b48f486ad6d 100644 --- a/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt +++ b/rest/src/main/kotlin/builder/guild/VoiceStateModifyBuilder.kt @@ -8,17 +8,17 @@ import dev.kord.common.entity.optional.map import dev.kord.rest.builder.RequestBuilder import dev.kord.rest.json.request.CurrentVoiceStateModifyRequest import dev.kord.rest.json.request.VoiceStateModifyRequest -import java.time.OffsetDateTime +import java.time.Instant class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder { - private var _requestToSpeakTimestamp: Optional = Optional.Missing() + private var _requestToSpeakTimestamp: Optional = Optional.Missing() private var _suppress: OptionalBoolean = OptionalBoolean.Missing /** * Sets the user's request to speak. - * The timestamp is used to sort how users appear on the moderators request list. + * The timestamp is used to sort how users appear on the moderators' request list. * * e.g: A client who requested to speak at 18:00, * will appear above a client who requested to speak at 20:00 in the same timezone. @@ -26,7 +26,7 @@ class CurrentVoiceStateModifyBuilder(val channelId: Snowflake) : RequestBuilder< * * A date in the past is treated as "now" by Discord. * * A null value removes the request to speak. */ - var requestToSpeakTimestamp: OffsetDateTime? by ::_requestToSpeakTimestamp.delegate() + var requestToSpeakTimestamp: Instant? by ::_requestToSpeakTimestamp.delegate() /** * whether this user is muted by the current user.