From 7a2e86ef66619193a78d2980cc8afd17e0a23c9e Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR <9496359+MrPowerGamerBR@users.noreply.github.com> Date: Tue, 5 Oct 2021 02:17:16 -0300 Subject: [PATCH] Add missing `invitable` field (#398) * Add missing `invitable` field * Add the "invitable" flag in the ThreadModifyBuilder, ChannelData and ThreadMetadata * Add invitable flag to the StartThreadBuilder * Add invitable flag on the startThread methods * Start Thread builders * Use thread builders in the core module * Make ChannelType val instead of var * Use the StartThreadBuilder for the Audit Log reason instead of using a reason argument Co-authored-by: Hope <34831095+HopeBaron@users.noreply.github.com> --- .../src/main/kotlin/entity/DiscordChannel.kt | 3 +- .../behavior/channel/NewsChannelBehavior.kt | 2 +- .../behavior/channel/TextChannelBehavior.kt | 18 +++++++---- .../threads/ThreadParentChannelBehavior.kt | 8 +++-- .../src/main/kotlin/cache/data/ChannelData.kt | 9 ++++-- .../channel/thread/StartThreadBuilder.kt | 25 ++++++++++++++++ .../thread/StartThreadWithMessageBuilder.kt | 16 ++++++++++ .../channel/thread/ThreadModifyBuilder.kt | 6 +++- .../kotlin/json/request/ChannelRequests.kt | 4 ++- .../src/main/kotlin/service/ChannelService.kt | 30 +++++++++++++++++-- 10 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 rest/src/main/kotlin/builder/channel/thread/StartThreadBuilder.kt create mode 100644 rest/src/main/kotlin/builder/channel/thread/StartThreadWithMessageBuilder.kt diff --git a/common/src/main/kotlin/entity/DiscordChannel.kt b/common/src/main/kotlin/entity/DiscordChannel.kt index 2a9b39bb33c4..271dc3da33ac 100644 --- a/common/src/main/kotlin/entity/DiscordChannel.kt +++ b/common/src/main/kotlin/entity/DiscordChannel.kt @@ -184,7 +184,8 @@ class DiscordThreadMetadata( val archiveTimestamp: String, @SerialName("auto_archive_duration") val autoArchiveDuration: ArchiveDuration, - val locked: OptionalBoolean = OptionalBoolean.Missing + val locked: OptionalBoolean = OptionalBoolean.Missing, + val invitable: OptionalBoolean = OptionalBoolean.Missing ) @Serializable(with = ArchiveDuration.Serializer::class) diff --git a/core/src/main/kotlin/behavior/channel/NewsChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/NewsChannelBehavior.kt index 7f3fac406f89..79748b130577 100644 --- a/core/src/main/kotlin/behavior/channel/NewsChannelBehavior.kt +++ b/core/src/main/kotlin/behavior/channel/NewsChannelBehavior.kt @@ -88,7 +88,7 @@ public interface NewsChannelBehavior : ThreadParentChannelBehavior { archiveDuration: ArchiveDuration = ArchiveDuration.Day, reason: String? = null ): NewsChannelThread { - return unsafeStartThread(name, archiveDuration, ChannelType.PublicNewsThread, reason) as NewsChannelThread + return unsafeStartThread(name, archiveDuration, ChannelType.PublicNewsThread) { this.reason = reason } as NewsChannelThread } public suspend fun startPublicThreadWithMessage( diff --git a/core/src/main/kotlin/behavior/channel/TextChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/TextChannelBehavior.kt index 4aba2a08505c..50cc1f91972a 100644 --- a/core/src/main/kotlin/behavior/channel/TextChannelBehavior.kt +++ b/core/src/main/kotlin/behavior/channel/TextChannelBehavior.kt @@ -3,6 +3,8 @@ package dev.kord.core.behavior.channel import dev.kord.common.entity.ArchiveDuration import dev.kord.common.entity.ChannelType import dev.kord.common.entity.Snowflake +import dev.kord.common.entity.optional.OptionalBoolean +import dev.kord.common.entity.optional.optional import dev.kord.common.exception.RequestException import dev.kord.core.Kord import dev.kord.core.behavior.channel.threads.PrivateThreadParentChannelBehavior @@ -16,6 +18,7 @@ import dev.kord.core.exception.EntityNotFoundException import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.rest.builder.channel.TextChannelModifyBuilder +import dev.kord.rest.builder.channel.thread.StartThreadBuilder import dev.kord.rest.request.RestRequestException import dev.kord.rest.service.patchTextChannel import kotlinx.coroutines.flow.Flow @@ -68,18 +71,23 @@ public interface TextChannelBehavior : PrivateThreadParentChannelBehavior { public suspend fun startPublicThread( name: String, archiveDuration: ArchiveDuration = ArchiveDuration.Day, - reason: String? = null - + builder: StartThreadBuilder.() -> Unit = {} ): TextChannelThread { - return unsafeStartThread(name, archiveDuration, ChannelType.PublicGuildThread, reason) as TextChannelThread + return unsafeStartThread( + name, + archiveDuration, + ChannelType.PublicGuildThread, + builder + ) as TextChannelThread } public suspend fun startPrivateThread( name: String, archiveDuration: ArchiveDuration = ArchiveDuration.Day, - reason: String? = null + builder: StartThreadBuilder.() -> Unit = {} ): TextChannelThread { - return unsafeStartThread(name, archiveDuration, ChannelType.PrivateThread, reason) as TextChannelThread + val startBuilder = StartThreadBuilder(name, archiveDuration, ChannelType.PrivateThread).apply(builder) + return unsafeStartThread(startBuilder.name, startBuilder.autoArchiveDuration, ChannelType.PrivateThread, builder) as TextChannelThread } public suspend fun startPublicThreadWithMessage( diff --git a/core/src/main/kotlin/behavior/channel/threads/ThreadParentChannelBehavior.kt b/core/src/main/kotlin/behavior/channel/threads/ThreadParentChannelBehavior.kt index adbb3f30ba9d..84def7d9ea3c 100644 --- a/core/src/main/kotlin/behavior/channel/threads/ThreadParentChannelBehavior.kt +++ b/core/src/main/kotlin/behavior/channel/threads/ThreadParentChannelBehavior.kt @@ -4,6 +4,8 @@ import dev.kord.common.entity.ArchiveDuration import dev.kord.common.entity.ChannelType 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.optional import dev.kord.common.exception.RequestException import dev.kord.core.Kord import dev.kord.core.behavior.channel.ChannelBehavior @@ -16,6 +18,7 @@ import dev.kord.core.entity.channel.thread.ThreadChannel import dev.kord.core.exception.EntityNotFoundException import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import dev.kord.rest.builder.channel.thread.StartThreadBuilder import dev.kord.rest.json.request.StartThreadRequest import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.filter @@ -131,11 +134,10 @@ internal suspend fun ThreadParentChannelBehavior.unsafeStartThread( name: String, archiveDuration: ArchiveDuration = ArchiveDuration.Day, type: ChannelType, - reason: String? = null + builder: StartThreadBuilder.() -> Unit ): ThreadChannel { - val response = - kord.rest.channel.startThread(id, StartThreadRequest(name, archiveDuration, Optional.Value(type)), reason) + kord.rest.channel.startThread(id, name, archiveDuration, type, builder) val data = ChannelData.from(response) return Channel.from(data, kord) as ThreadChannel diff --git a/core/src/main/kotlin/cache/data/ChannelData.kt b/core/src/main/kotlin/cache/data/ChannelData.kt index 63df5b64d689..7fd3438ac3f1 100644 --- a/core/src/main/kotlin/cache/data/ChannelData.kt +++ b/core/src/main/kotlin/cache/data/ChannelData.kt @@ -77,11 +77,14 @@ public data class ThreadMetadataData( val archived: Boolean, val archiveTimestamp: String, val autoArchiveDuration: ArchiveDuration, - val locked: OptionalBoolean = OptionalBoolean.Missing + val locked: OptionalBoolean = OptionalBoolean.Missing, + val invitable: OptionalBoolean = OptionalBoolean.Missing ) { - public companion object { + + public companion object { public fun from(threadMetadata: DiscordThreadMetadata): ThreadMetadataData = with(threadMetadata) { - ThreadMetadataData(archived, archiveTimestamp, autoArchiveDuration, locked) + ThreadMetadataData(archived, archiveTimestamp, autoArchiveDuration, locked, invitable) + } } } diff --git a/rest/src/main/kotlin/builder/channel/thread/StartThreadBuilder.kt b/rest/src/main/kotlin/builder/channel/thread/StartThreadBuilder.kt new file mode 100644 index 000000000000..10209cbbd881 --- /dev/null +++ b/rest/src/main/kotlin/builder/channel/thread/StartThreadBuilder.kt @@ -0,0 +1,25 @@ +package dev.kord.rest.builder.channel.thread + +import dev.kord.common.entity.ArchiveDuration +import dev.kord.common.entity.ChannelType +import dev.kord.common.entity.optional.OptionalBoolean +import dev.kord.common.entity.optional.delegate.delegate +import dev.kord.common.entity.optional.optional +import dev.kord.rest.builder.AuditRequestBuilder +import dev.kord.rest.json.request.StartThreadRequest + +class StartThreadBuilder(var name: String, var autoArchiveDuration: ArchiveDuration, val type: ChannelType) : AuditRequestBuilder { + override var reason: String? = null + + private var _invitable: OptionalBoolean = OptionalBoolean.Missing + var invitable: Boolean? by ::_invitable.delegate() + + override fun toRequest(): StartThreadRequest { + return StartThreadRequest( + name = name, + autoArchiveDuration = autoArchiveDuration, + type = type.optional(), // Currently this is optional, but in API v10 it will be required according to Discord's docs. + invitable = _invitable + ) + } +} \ No newline at end of file diff --git a/rest/src/main/kotlin/builder/channel/thread/StartThreadWithMessageBuilder.kt b/rest/src/main/kotlin/builder/channel/thread/StartThreadWithMessageBuilder.kt new file mode 100644 index 000000000000..9ddc526684c3 --- /dev/null +++ b/rest/src/main/kotlin/builder/channel/thread/StartThreadWithMessageBuilder.kt @@ -0,0 +1,16 @@ +package dev.kord.rest.builder.channel.thread + +import dev.kord.common.entity.ArchiveDuration +import dev.kord.rest.builder.AuditRequestBuilder +import dev.kord.rest.json.request.StartThreadRequest + +class StartThreadWithMessageBuilder(var name: String, var autoArchiveDuration: ArchiveDuration) : AuditRequestBuilder { + override var reason: String? = null + + override fun toRequest(): StartThreadRequest { + return StartThreadRequest( + name = name, + autoArchiveDuration = autoArchiveDuration + ) + } +} \ No newline at end of file diff --git a/rest/src/main/kotlin/builder/channel/thread/ThreadModifyBuilder.kt b/rest/src/main/kotlin/builder/channel/thread/ThreadModifyBuilder.kt index c7e158b00687..277b5c6edfe7 100644 --- a/rest/src/main/kotlin/builder/channel/thread/ThreadModifyBuilder.kt +++ b/rest/src/main/kotlin/builder/channel/thread/ThreadModifyBuilder.kt @@ -24,13 +24,17 @@ class ThreadModifyBuilder : AuditRequestBuilder { private var _autoArchiveDuration: OptionalInt = OptionalInt.Missing var autoArchiveDuration: Int? by ::_autoArchiveDuration.delegate() + private var _invitable: OptionalBoolean = OptionalBoolean.Missing + var invitable: Boolean? by ::_invitable.delegate() + override fun toRequest(): ChannelModifyPatchRequest { return ChannelModifyPatchRequest( name = _name, locked = _locked, archived = _archived, autoArchiveDuration = _autoArchiveDuration, - rateLimitPerUser = _rateLimitPerUser + rateLimitPerUser = _rateLimitPerUser, + invitable = _invitable ) } diff --git a/rest/src/main/kotlin/json/request/ChannelRequests.kt b/rest/src/main/kotlin/json/request/ChannelRequests.kt index d2aa2b8fbaa9..4eefb4d010d5 100644 --- a/rest/src/main/kotlin/json/request/ChannelRequests.kt +++ b/rest/src/main/kotlin/json/request/ChannelRequests.kt @@ -51,6 +51,7 @@ data class ChannelModifyPatchRequest( @SerialName("auto_archive_duration") val autoArchiveDuration: OptionalInt = OptionalInt.Missing, val locked: OptionalBoolean = OptionalBoolean.Missing, + val invitable: OptionalBoolean = OptionalBoolean.Missing, ) @Serializable @@ -65,7 +66,8 @@ data class StartThreadRequest( val name: String, @SerialName("auto_archive_duration") val autoArchiveDuration: ArchiveDuration, - val type: Optional = Optional.Missing() + val type: Optional = Optional.Missing(), + val invitable: OptionalBoolean = OptionalBoolean.Missing ) data class ListThreadsBySnowflakeRequest( diff --git a/rest/src/main/kotlin/service/ChannelService.kt b/rest/src/main/kotlin/service/ChannelService.kt index b67ed56e737a..f050455cb075 100644 --- a/rest/src/main/kotlin/service/ChannelService.kt +++ b/rest/src/main/kotlin/service/ChannelService.kt @@ -4,6 +4,8 @@ import dev.kord.common.annotation.KordPreview import dev.kord.common.entity.* import dev.kord.common.entity.optional.orEmpty import dev.kord.rest.builder.channel.* +import dev.kord.rest.builder.channel.thread.StartThreadBuilder +import dev.kord.rest.builder.channel.thread.StartThreadWithMessageBuilder import dev.kord.rest.builder.message.create.UserMessageCreateBuilder import dev.kord.rest.builder.message.modify.UserMessageModifyBuilder import dev.kord.rest.json.request.* @@ -274,6 +276,7 @@ class ChannelService(requestHandler: RequestHandler) : RestService(requestHandle keys[Route.ChannelId] = channelId body(ChannelFollowRequest.serializer(), request) } + suspend fun startThreadWithMessage( channelId: Snowflake, messageId: Snowflake, @@ -285,10 +288,21 @@ class ChannelService(requestHandler: RequestHandler) : RestService(requestHandle keys[Route.MessageId] = messageId body(StartThreadRequest.serializer(), request) reason?.let { header("X-Audit-Log-Reason", reason) } - } } + @OptIn(ExperimentalContracts::class) + suspend fun startThreadWithMessage( + channelId: Snowflake, + messageId: Snowflake, + name: String, + archiveDuration: ArchiveDuration, + builder: StartThreadWithMessageBuilder.() -> Unit + ): DiscordChannel { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + val startBuilder = StartThreadWithMessageBuilder(name, archiveDuration).apply(builder) + return startThreadWithMessage(channelId, messageId, startBuilder.toRequest(), startBuilder.reason) + } suspend fun startThread( channelId: Snowflake, @@ -299,10 +313,22 @@ class ChannelService(requestHandler: RequestHandler) : RestService(requestHandle keys[Route.ChannelId] = channelId body(StartThreadRequest.serializer(), request) reason?.let { header("X-Audit-Log-Reason", reason) } - } } + @OptIn(ExperimentalContracts::class) + suspend fun startThread( + channelId: Snowflake, + name: String, + archiveDuration: ArchiveDuration, + type: ChannelType, + builder: StartThreadBuilder.() -> Unit = {} + ): DiscordChannel { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + val startBuilder = StartThreadBuilder(name, archiveDuration, type).apply(builder) + return startThread(channelId, startBuilder.toRequest(), startBuilder.reason) + } + suspend fun joinThread(channelId: Snowflake) { call(Route.JoinThreadPut) { keys[Route.ChannelId] = channelId