Skip to content

Commit

Permalink
Allow modifying GuildOnboarding (#819)
Browse files Browse the repository at this point in the history
The DSL looks like this:
val onboarding = guild.editOnboarding {
    enabled = true
    mode = OnboardingMode.Advanced
    defaultChannelId(channelId1)
    defaultChannelId(channelId2)
    defaultChannelId(channelId3)
    defaultChannelId(channelId4)
    defaultChannelId(channelId5)
    defaultChannelId(channelId6)
    defaultChannelId(channelId7)
    prompt(
        OnboardingPromptType.MultipleChoice,
        title = "prompt title",
        singleSelect = false,
        required = false,
        inOnboarding = true,
    ) {
        option(title = "option 1 title") {
            channelIds += someChannelId
            description = "option 1 description"
        }
        option(title = "option 2 title") {
            roleIds += someRoleId
        }
    }
}
println(onboarding)

See discord/discord-api-docs#6101
  • Loading branch information
lukellmann authored Sep 17, 2023
1 parent 2dad036 commit 9a7b302
Show file tree
Hide file tree
Showing 15 changed files with 568 additions and 11 deletions.
36 changes: 32 additions & 4 deletions common/api/common.api
Original file line number Diff line number Diff line change
Expand Up @@ -4121,18 +4121,20 @@ public final class dev/kord/common/entity/DiscordGuildMember$Companion {

public final class dev/kord/common/entity/DiscordGuildOnboarding {
public static final field Companion Ldev/kord/common/entity/DiscordGuildOnboarding$Companion;
public synthetic fun <init> (ILdev/kord/common/entity/Snowflake;Ljava/util/List;Ljava/util/List;ZLkotlinx/serialization/internal/SerializationConstructorMarker;)V
public fun <init> (Ldev/kord/common/entity/Snowflake;Ljava/util/List;Ljava/util/List;Z)V
public synthetic fun <init> (ILdev/kord/common/entity/Snowflake;Ljava/util/List;Ljava/util/List;ZLdev/kord/common/entity/OnboardingMode;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V
public fun <init> (Ldev/kord/common/entity/Snowflake;Ljava/util/List;Ljava/util/List;ZLdev/kord/common/entity/OnboardingMode;)V
public final fun component1 ()Ldev/kord/common/entity/Snowflake;
public final fun component2 ()Ljava/util/List;
public final fun component3 ()Ljava/util/List;
public final fun component4 ()Z
public final fun copy (Ldev/kord/common/entity/Snowflake;Ljava/util/List;Ljava/util/List;Z)Ldev/kord/common/entity/DiscordGuildOnboarding;
public static synthetic fun copy$default (Ldev/kord/common/entity/DiscordGuildOnboarding;Ldev/kord/common/entity/Snowflake;Ljava/util/List;Ljava/util/List;ZILjava/lang/Object;)Ldev/kord/common/entity/DiscordGuildOnboarding;
public final fun component5 ()Ldev/kord/common/entity/OnboardingMode;
public final fun copy (Ldev/kord/common/entity/Snowflake;Ljava/util/List;Ljava/util/List;ZLdev/kord/common/entity/OnboardingMode;)Ldev/kord/common/entity/DiscordGuildOnboarding;
public static synthetic fun copy$default (Ldev/kord/common/entity/DiscordGuildOnboarding;Ldev/kord/common/entity/Snowflake;Ljava/util/List;Ljava/util/List;ZLdev/kord/common/entity/OnboardingMode;ILjava/lang/Object;)Ldev/kord/common/entity/DiscordGuildOnboarding;
public fun equals (Ljava/lang/Object;)Z
public final fun getDefaultChannelIds ()Ljava/util/List;
public final fun getEnabled ()Z
public final fun getGuildId ()Ldev/kord/common/entity/Snowflake;
public final fun getMode ()Ldev/kord/common/entity/OnboardingMode;
public final fun getPrompts ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
Expand Down Expand Up @@ -7894,6 +7896,32 @@ public final class dev/kord/common/entity/NsfwLevel$Unknown : dev/kord/common/en
public fun <init> (I)V
}

public abstract class dev/kord/common/entity/OnboardingMode {
public static final field Companion Ldev/kord/common/entity/OnboardingMode$Companion;
public synthetic fun <init> (ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun equals (Ljava/lang/Object;)Z
public final fun getValue ()I
public final fun hashCode ()I
public final fun toString ()Ljava/lang/String;
}

public final class dev/kord/common/entity/OnboardingMode$Advanced : dev/kord/common/entity/OnboardingMode {
public static final field INSTANCE Ldev/kord/common/entity/OnboardingMode$Advanced;
}

public final class dev/kord/common/entity/OnboardingMode$Companion {
public final fun from (I)Ldev/kord/common/entity/OnboardingMode;
public final fun getEntries ()Ljava/util/List;
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class dev/kord/common/entity/OnboardingMode$Default : dev/kord/common/entity/OnboardingMode {
public static final field INSTANCE Ldev/kord/common/entity/OnboardingMode$Default;
}

public final class dev/kord/common/entity/OnboardingMode$Unknown : dev/kord/common/entity/OnboardingMode {
}

public abstract class dev/kord/common/entity/OnboardingPromptType {
public static final field Companion Ldev/kord/common/entity/OnboardingPromptType$Companion;
public synthetic fun <init> (ILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// THIS FILE IS AUTO-GENERATED, DO NOT EDIT!
@file:Suppress(names = arrayOf("IncorrectFormatting", "ReplaceArrayOfWithLiteral",
"SpellCheckingInspection", "GrazieInspection"))

package dev.kord.common.entity

import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

/**
* Defines the criteria used to satisfy Onboarding constraints that are required for enabling.
*
* See [OnboardingMode]s in the
* [Discord Developer Documentation](https://discord.com/developers/docs/resources/guild#guild-onboarding-object-onboarding-mode).
*/
@Serializable(with = OnboardingMode.Serializer::class)
public sealed class OnboardingMode(
/**
* The raw value used by Discord.
*/
public val `value`: Int,
) {
final override fun equals(other: Any?): Boolean = this === other ||
(other is OnboardingMode && this.value == other.value)

final override fun hashCode(): Int = value.hashCode()

final override fun toString(): String =
if (this is Unknown) "OnboardingMode.Unknown(value=$value)"
else "OnboardingMode.${this::class.simpleName}"

/**
* An unknown [OnboardingMode].
*
* This is used as a fallback for [OnboardingMode]s that haven't been added to Kord yet.
*/
public class Unknown internal constructor(
`value`: Int,
) : OnboardingMode(value)

/**
* Counts only Default Channels towards constraints.
*/
public object Default : OnboardingMode(0)

/**
* Counts Default Channels and Questions towards constraints.
*/
public object Advanced : OnboardingMode(1)

internal object Serializer : KSerializer<OnboardingMode> {
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("dev.kord.common.entity.OnboardingMode",
PrimitiveKind.INT)

override fun serialize(encoder: Encoder, `value`: OnboardingMode) {
encoder.encodeInt(value.value)
}

override fun deserialize(decoder: Decoder): OnboardingMode = from(decoder.decodeInt())
}

public companion object {
/**
* A [List] of all known [OnboardingMode]s.
*/
public val entries: List<OnboardingMode> by lazy(mode = PUBLICATION) {
listOf(
Default,
Advanced,
)
}


/**
* Returns an instance of [OnboardingMode] with [OnboardingMode.value] equal to the
* specified [value].
*/
public fun from(`value`: Int): OnboardingMode = when (value) {
0 -> Default
1 -> Advanced
else -> Unknown(value)
}
}
}
11 changes: 11 additions & 0 deletions common/src/commonMain/kotlin/entity/DiscordGuildOnboarding.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
@file:Generate(
INT_KORD_ENUM, name = "OnboardingMode", unknownConstructorWasPublic = false,
kDoc = "Defines the criteria used to satisfy Onboarding constraints that are required for enabling.",
docUrl = "https://discord.com/developers/docs/resources/guild#guild-onboarding-object-onboarding-mode",
entries = [
Entry("Default", intValue = 0, kDoc = "Counts only Default Channels towards constraints."),
Entry("Advanced", intValue = 1, kDoc = "Counts Default Channels and Questions towards constraints."),
],
)

@file:Generate(
INT_KORD_ENUM, name = "OnboardingPromptType",
docUrl = "https://discord.com/developers/docs/resources/guild#guild-onboarding-object-prompt-types",
Expand All @@ -21,6 +31,7 @@ public data class DiscordGuildOnboarding(
val prompts: List<DiscordOnboardingPrompt>,
@SerialName("default_channel_ids") val defaultChannelIds: List<Snowflake>,
val enabled: Boolean,
val mode: OnboardingMode,
)

@Serializable
Expand Down
2 changes: 2 additions & 0 deletions core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ public final class dev/kord/core/behavior/GuildBehaviorKt {
public static final fun createVoiceChannel (Ldev/kord/core/behavior/GuildBehavior;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun createVoiceChannel$default (Ldev/kord/core/behavior/GuildBehavior;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public static final fun edit (Ldev/kord/core/behavior/GuildBehavior;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun editOnboarding (Ldev/kord/core/behavior/GuildBehavior;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun editWidget (Ldev/kord/core/behavior/GuildBehavior;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static final fun getAuditLogEntries (Ldev/kord/core/behavior/GuildBehavior;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow;
public static synthetic fun getAuditLogEntries$default (Ldev/kord/core/behavior/GuildBehavior;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
Expand Down Expand Up @@ -6388,6 +6389,7 @@ public final class dev/kord/core/entity/GuildOnboarding : dev/kord/core/KordObje
public final fun getGuildId ()Ldev/kord/common/entity/Snowflake;
public final fun getGuildOrNull (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun getKord ()Ldev/kord/core/Kord;
public final fun getMode ()Ldev/kord/common/entity/OnboardingMode;
public final fun getPrompts ()Ljava/util/List;
public fun getSupplier ()Ldev/kord/core/supplier/EntitySupplier;
public final fun isEnabled ()Z
Expand Down
16 changes: 16 additions & 0 deletions core/src/commonMain/kotlin/behavior/GuildBehavior.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import dev.kord.common.annotation.KordExperimental
import dev.kord.common.entity.*
import dev.kord.common.entity.AutoModerationRuleEventType.MessageSend
import dev.kord.common.entity.Permission.ManageGuild
import dev.kord.common.entity.Permission.ManageRoles
import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.unwrap
import dev.kord.common.exception.RequestException
Expand Down Expand Up @@ -968,6 +969,21 @@ public suspend inline fun GuildBehavior.editWidget(builder: GuildWidgetModifyBui
return GuildWidget(GuildWidgetData.from(kord.rest.guild.modifyGuildWidget(id, builder)), id, kord)
}

/**
* Requests to edit the [GuildOnboarding] object of the guild and returns the edited onboarding object.
*
* This requires the [ManageGuild] and [ManageRoles] permissions.
*
* @throws RestRequestException if something went wrong during the request.
*/
public suspend inline fun GuildBehavior.editOnboarding(
builder: GuildOnboardingModifyBuilder.() -> Unit,
): GuildOnboarding {
contract { callsInPlace(builder, EXACTLY_ONCE) }
val onboarding = kord.rest.guild.modifyGuildOnboarding(guildId = id, builder)
return GuildOnboarding(onboarding, kord)
}

/**
* The [Audit log entries][AuditLogEntry] from this guild, configured by the [builder].
*
Expand Down
3 changes: 3 additions & 0 deletions core/src/commonMain/kotlin/entity/GuildOnboarding.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public class GuildOnboarding(
/** Whether onboarding is enabled in the [guild]. */
public val isEnabled: Boolean get() = data.enabled

/** Current [mode][OnboardingMode] of onboarding. */
public val mode: OnboardingMode get() = data.mode

/**
* Requests the [Guild] this onboarding is part of.
*
Expand Down
1 change: 1 addition & 0 deletions ksp-annotations/src/commonMain/kotlin/Generate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ annotation class Generate(
val hadFlagsProperty: Boolean = false,
val flagsPropertyWasSet: Boolean = false,
val builderHadFlagsFunction: Boolean = false,
val unknownConstructorWasPublic: Boolean = true,
) {
enum class EntityType { INT_KORD_ENUM, STRING_KORD_ENUM, INT_FLAGS, BIT_SET_FLAGS }

Expand Down
11 changes: 8 additions & 3 deletions ksp-processors/src/main/kotlin/generation/GenerationEntity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ internal sealed class GenerationEntity(
class KordEnum(
name: String, kDoc: String?, docUrl: String, valueName: String, entries: List<Entry>,
override val valueType: ValueType,
val unknownConstructorWasPublic: Boolean,
) : GenerationEntity(name, kDoc, docUrl, valueName, entries) {
enum class ValueType : GenerationEntity.ValueType { INT, STRING }
}
Expand Down Expand Up @@ -72,7 +73,7 @@ internal fun Generate.toGenerationEntityOrNull(logger: KSPLogger, annotation: KS
Generate::wasEnum, Generate::collectionWasDataClass, Generate::hadFlagsProperty,
Generate::flagsPropertyWasSet, Generate::builderHadFlagsFunction,
)
INT_FLAGS, BIT_SET_FLAGS -> true
INT_FLAGS, BIT_SET_FLAGS -> areNotSpecified(Generate::unknownConstructorWasPublic)
}

val mappedEntries = (entries zip args[Generate::entries]!!).mapNotNull { (entry, annotation) ->
Expand All @@ -84,8 +85,12 @@ internal fun Generate.toGenerationEntityOrNull(logger: KSPLogger, annotation: KS
} else {
val kDoc = kDoc.toKDoc()
when (entityType) {
INT_KORD_ENUM -> KordEnum(name, kDoc, docUrl, valueName, mappedEntries, KordEnum.ValueType.INT)
STRING_KORD_ENUM -> KordEnum(name, kDoc, docUrl, valueName, mappedEntries, KordEnum.ValueType.STRING)
INT_KORD_ENUM -> KordEnum(
name, kDoc, docUrl, valueName, mappedEntries, KordEnum.ValueType.INT, unknownConstructorWasPublic,
)
STRING_KORD_ENUM -> KordEnum(
name, kDoc, docUrl, valueName, mappedEntries, KordEnum.ValueType.STRING, unknownConstructorWasPublic,
)
INT_FLAGS -> BitFlags(
name, kDoc, docUrl, valueName, mappedEntries, BitFlags.ValueType.INT, wasEnum, collectionWasDataClass,
hadFlagsProperty, flagsPropertyWasSet, builderHadFlagsFunction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ internal fun KordEnum.generateFileSpec(originatingFile: KSFile) = fileSpecForGen
primaryConstructor {
addModifiers(INTERNAL)
addParameter(valueName, valueCN)
addParameter("unused", type = NOTHING.copy(nullable = true)) {
if (unknownConstructorWasPublic) addParameter("unused", type = NOTHING.copy(nullable = true)) {
@OptIn(DelicateKotlinPoetApi::class)
addAnnotation(Suppress("UNUSED_PARAMETER"))
}
}
addSuperclassConstructorParameter(valueName)
// TODO bump deprecation level and remove eventually (also share code with bit flags then)
addConstructor {
if (unknownConstructorWasPublic) addConstructor {
@OptIn(DelicateKotlinPoetApi::class)
addAnnotation(
Deprecated(
Expand Down Expand Up @@ -69,7 +69,7 @@ internal fun KordEnum.generateFileSpec(originatingFile: KSFile) = fileSpecForGen
for (entry in entriesDistinctByValue) {
addStatement("$valueFormat·->·${entry.nameWithSuppressedDeprecation}", entry.value)
}
addStatement("else·->·Unknown($valueName,·null)")
addStatement(if (unknownConstructorWasPublic) "else·->·Unknown($valueName,·null)" else "else·->·Unknown($valueName)")
}
}
}
Expand Down
Loading

0 comments on commit 9a7b302

Please sign in to comment.