Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invite and Application revamp #530

Merged
merged 34 commits into from
Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9c6215f
create invite builder and request
lukellmann Feb 7, 2022
0574f16
invite create event
lukellmann Feb 7, 2022
c4726cf
application
lukellmann Feb 8, 2022
079caf9
default optional
lukellmann Feb 8, 2022
38ca533
invite create event
lukellmann Feb 8, 2022
d38bfa9
invite delete event
lukellmann Feb 8, 2022
30e28aa
partial application in invite create event
lukellmann Feb 8, 2022
2e66c0c
deprecate InviteTargetType
lukellmann Feb 8, 2022
45ef7eb
rename ApplicationInfo
lukellmann Feb 9, 2022
33fc9aa
invite channel hierarchy
lukellmann Feb 9, 2022
94581cf
add DiscordInviteWithMetadata
lukellmann Feb 9, 2022
8841160
PartialGuild is GuildBehavior
lukellmann Feb 9, 2022
1fe52da
request: maxAge and maxUses
lukellmann Feb 9, 2022
7a53877
deprecate functions
lukellmann Feb 9, 2022
9d4b0de
ApplicationFlags
lukellmann Feb 10, 2022
a1686f1
Merge branch '0.8.x' into changes/invite-models
lukellmann Feb 19, 2022
39468b5
Merge branch '0.8.x' into changes/invite-models
lukellmann Feb 26, 2022
b74f97c
`code & (~otherCode)` instead of `code ^ (code & otherCode)` for flag…
lukellmann Feb 26, 2022
8b541b9
all optionals in PartialApplication, base interfaces
lukellmann Feb 26, 2022
dfe1b38
formatting
lukellmann Feb 26, 2022
6241236
rename base interface for invite
lukellmann Feb 26, 2022
7b5b549
remove UserFlag.None
lukellmann Feb 26, 2022
b728e7a
docs
lukellmann Feb 26, 2022
1d29a2d
no CategorizableChannel and TopGuildChannel supertype needed
lukellmann Feb 26, 2022
33916f7
TeamData instead of DiscordTeam in ApplicationData
lukellmann Feb 26, 2022
c649ee0
remove application.summary, see https://github.com/kordlib/kord/pull/…
lukellmann Mar 3, 2022
6b9a05e
introduce InviteWithMetadata
lukellmann Mar 3, 2022
ca06d86
single expression toString
lukellmann Mar 3, 2022
231662b
Merge branch '0.8.x' into changes/invite-models
lukellmann Mar 3, 2022
eda6b02
update docs for Permission.UseEmbeddedActivities to include reference…
lukellmann Mar 3, 2022
2bb16b0
defaultSupplier
lukellmann Mar 5, 2022
ab200d8
duration unit
lukellmann Mar 5, 2022
68a1f5b
Merge branch '0.8.x' into changes/invite-models
lukellmann Mar 5, 2022
9ff90fc
delete empty files after merge
lukellmann Mar 5, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions common/src/main/kotlin/entity/DiscordApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package dev.kord.common.entity

import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalSnowflake
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
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
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

public sealed interface BaseDiscordApplication {
public val id: Snowflake
public val name: String
public val icon: String?
public val description: String
public val rpcOrigins: Optional<List<String>>
public val termsOfServiceUrl: Optional<String>
public val privacyPolicyUrl: Optional<String>
public val owner: Optional<DiscordUser>
public val verifyKey: String
public val guildId: OptionalSnowflake
public val primarySkuId: OptionalSnowflake
public val slug: Optional<String>
public val coverImage: Optional<String>
public val flags: Optional<ApplicationFlags>
}

/**
* A representation of the
* [Application Structure](https://discord.com/developers/docs/resources/application#application-object-application-structure).
*/
@Serializable
public data class DiscordApplication(
override val id: Snowflake,
override val name: String,
override val icon: String?,
override val description: String,
@SerialName("rpc_origins")
override val rpcOrigins: Optional<List<String>> = Optional.Missing(),
@SerialName("bot_public")
val botPublic: Boolean,
@SerialName("bot_require_code_grant")
val botRequireCodeGrant: Boolean,
@SerialName("terms_of_service_url")
override val termsOfServiceUrl: Optional<String> = Optional.Missing(),
@SerialName("privacy_policy_url")
override val privacyPolicyUrl: Optional<String> = Optional.Missing(),
override val owner: Optional<DiscordUser> = Optional.Missing(),
@SerialName("verify_key")
override val verifyKey: String,
val team: DiscordTeam?,
@SerialName("guild_id")
override val guildId: OptionalSnowflake = OptionalSnowflake.Missing,
@SerialName("primary_sku_id")
override val primarySkuId: OptionalSnowflake = OptionalSnowflake.Missing,
override val slug: Optional<String> = Optional.Missing(),
@SerialName("cover_image")
override val coverImage: Optional<String> = Optional.Missing(),
override val flags: Optional<ApplicationFlags> = Optional.Missing(),
) : BaseDiscordApplication

/**
* A representation of the partial
* [Application Structure](https://discord.com/developers/docs/resources/application#application-object-application-structure)
* sent in [invite create events](https://discord.com/developers/docs/topics/gateway#invite-create).
*/
@Serializable
public data class DiscordPartialApplication(
override val id: Snowflake,
override val name: String,
override val icon: String?,
override val description: String,
@SerialName("rpc_origins")
override val rpcOrigins: Optional<List<String>> = Optional.Missing(),
@SerialName("terms_of_service_url")
override val termsOfServiceUrl: Optional<String> = Optional.Missing(),
@SerialName("privacy_policy_url")
override val privacyPolicyUrl: Optional<String> = Optional.Missing(),
override val owner: Optional<DiscordUser> = Optional.Missing(),
@SerialName("verify_key")
override val verifyKey: String,
@SerialName("guild_id")
override val guildId: OptionalSnowflake = OptionalSnowflake.Missing,
@SerialName("primary_sku_id")
override val primarySkuId: OptionalSnowflake = OptionalSnowflake.Missing,
override val slug: Optional<String> = Optional.Missing(),
@SerialName("cover_image")
override val coverImage: Optional<String> = Optional.Missing(),
override val flags: Optional<ApplicationFlags> = Optional.Missing(),
) : BaseDiscordApplication

public enum class ApplicationFlag(public val code: Int) {
GatewayPresence(1 shl 12),
GatewayPresenceLimited(1 shl 13),
GatewayGuildMembers(1 shl 14),
GatewayGuildMembersLimited(1 shl 15),
VerificationPendingGuildLimit(1 shl 16),
Embedded(1 shl 17),
GatewayMessageContent(1 shl 18),
GatewayMessageContentLimited(1 shl 19);

public operator fun plus(flag: ApplicationFlag): ApplicationFlags = ApplicationFlags(this.code or flag.code)

public operator fun plus(flags: ApplicationFlags): ApplicationFlags = flags + this
}

@Serializable(with = ApplicationFlags.Serializer::class)
public data class ApplicationFlags internal constructor(val code: Int) {

val flags: List<ApplicationFlag> get() = ApplicationFlag.values().filter { this.contains(it) }

public operator fun contains(flag: ApplicationFlag): Boolean = this.code and flag.code == flag.code

public operator fun contains(flags: ApplicationFlags): Boolean = this.code and flags.code == flags.code

public operator fun plus(flag: ApplicationFlag): ApplicationFlags = ApplicationFlags(this.code or flag.code)

public operator fun plus(flags: ApplicationFlags): ApplicationFlags = ApplicationFlags(this.code or flags.code)

public operator fun minus(flag: ApplicationFlag): ApplicationFlags =
ApplicationFlags(this.code and flag.code.inv())

public operator fun minus(flags: ApplicationFlags): ApplicationFlags =
ApplicationFlags(this.code and flags.code.inv())


public inline fun copy(builder: Builder.() -> Unit): ApplicationFlags {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
return Builder(code).apply(builder).flags()
}


internal object Serializer : KSerializer<ApplicationFlags> {

override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ApplicationFlags", PrimitiveKind.INT)

override fun deserialize(decoder: Decoder): ApplicationFlags {
val flags = decoder.decodeInt()
return ApplicationFlags(flags)
}

override fun serialize(encoder: Encoder, value: ApplicationFlags) {
encoder.encodeInt(value.code)
}
}


public class Builder(internal var code: Int = 0) {
public operator fun ApplicationFlag.unaryPlus() {
[email protected] = [email protected] or this.code
}

public operator fun ApplicationFlags.unaryPlus() {
[email protected] = [email protected] or this.code
}

public operator fun ApplicationFlag.unaryMinus() {
[email protected] = [email protected] and this.code.inv()
}

public operator fun ApplicationFlags.unaryMinus() {
[email protected] = [email protected] and this.code.inv()
}

public fun flags(): ApplicationFlags = ApplicationFlags(code)
}
}

public inline fun ApplicationFlags(builder: ApplicationFlags.Builder.() -> Unit): ApplicationFlags {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
return ApplicationFlags.Builder().apply(builder).flags()
}

public fun ApplicationFlags(vararg flags: ApplicationFlag): ApplicationFlags = ApplicationFlags {
flags.forEach { +it }
}

public fun ApplicationFlags(vararg flags: ApplicationFlags): ApplicationFlags = ApplicationFlags {
flags.forEach { +it }
}

public fun ApplicationFlags(flags: Iterable<ApplicationFlag>): ApplicationFlags = ApplicationFlags {
flags.forEach { +it }
}

@JvmName("ApplicationFlagsWithIterable")
public fun ApplicationFlags(flags: Iterable<ApplicationFlags>): ApplicationFlags = ApplicationFlags {
flags.forEach { +it }
}
2 changes: 1 addition & 1 deletion common/src/main/kotlin/entity/DiscordIntegration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public data class IntegrationApplication(
val icon: String?,
val description: String,
val summary: String,
val bot: Optional<DiscordUser>
val bot: Optional<DiscordUser> = Optional.Missing(),
)

@Serializable(with = IntegrationExpireBehavior.Serializer::class)
Expand Down
109 changes: 87 additions & 22 deletions common/src/main/kotlin/entity/DiscordInvite.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,86 @@ package dev.kord.common.entity
import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalInt
import kotlinx.datetime.Instant
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
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

public sealed interface BaseDiscordInvite {
public val code: String
public val guild: Optional<DiscordPartialGuild>
public val channel: DiscordChannel?
public val inviter: Optional<DiscordUser>
public val targetType: Optional<InviteTargetType>
public val targetUser: Optional<DiscordUser>
public val targetApplication: Optional<DiscordPartialApplication>
public val approximatePresenceCount: OptionalInt
public val approximateMemberCount: OptionalInt
public val expiresAt: Optional<Instant?>
public val guildScheduledEvent: Optional<DiscordGuildScheduledEvent>
}

@Serializable
public data class DiscordInvite(
val code: String,
val guild: Optional<DiscordPartialGuild> = Optional.Missing(),
val channel: DiscordChannel?,
val inviter: Optional<DiscordUser> = Optional.Missing(),
override val code: String,
override val guild: Optional<DiscordPartialGuild> = Optional.Missing(),
override val channel: DiscordChannel?,
override val inviter: Optional<DiscordUser> = Optional.Missing(),
@SerialName("target_type")
override val targetType: Optional<InviteTargetType> = Optional.Missing(),
@SerialName("target_user")
val targetUser: Optional<DiscordUser> = Optional.Missing(),
override val targetUser: Optional<DiscordUser> = Optional.Missing(),
@SerialName("target_application")
override val targetApplication: Optional<DiscordPartialApplication> = Optional.Missing(),
@Deprecated("This is no longer documented. Use 'targetType' instead.", ReplaceWith("this.targetType"))
@SerialName("target_user_type")
val targetUserType: Optional<TargetUserType> = Optional.Missing(),
val targetUserType: Optional<@Suppress("DEPRECATION") TargetUserType> = Optional.Missing(),
@SerialName("approximate_presence_count")
val approximatePresenceCount: OptionalInt = OptionalInt.Missing,
override val approximatePresenceCount: OptionalInt = OptionalInt.Missing,
@SerialName("approximate_member_count")
val approximateMemberCount: OptionalInt = OptionalInt.Missing,
override val approximateMemberCount: OptionalInt = OptionalInt.Missing,
@SerialName("expires_at")
val expiresAt: Optional<Instant?> = Optional.Missing(),
override val expiresAt: Optional<Instant?> = Optional.Missing(),
@SerialName("stage_instance")
@Deprecated("Stages are no longer discoverable")
val stageInstance: Optional<DiscordStageInstance> = Optional.Missing(),
@SerialName("guild_scheduled_event")
val guildScheduledEvent: Optional<DiscordGuildScheduledEvent> = Optional.Missing(),
)
override val guildScheduledEvent: Optional<DiscordGuildScheduledEvent> = Optional.Missing(),
) : BaseDiscordInvite

@Serializable
public data class DiscordInviteWithMetadata(
override val code: String,
override val guild: Optional<DiscordPartialGuild> = Optional.Missing(),
override val channel: DiscordChannel?,
override val inviter: Optional<DiscordUser> = Optional.Missing(),
@SerialName("target_type")
override val targetType: Optional<InviteTargetType> = Optional.Missing(),
@SerialName("target_user")
override val targetUser: Optional<DiscordUser> = Optional.Missing(),
@SerialName("target_application")
override val targetApplication: Optional<DiscordPartialApplication> = Optional.Missing(),
@SerialName("approximate_presence_count")
override val approximatePresenceCount: OptionalInt = OptionalInt.Missing,
@SerialName("approximate_member_count")
override val approximateMemberCount: OptionalInt = OptionalInt.Missing,
@SerialName("expires_at")
override val expiresAt: Optional<Instant?> = Optional.Missing(),
@SerialName("guild_scheduled_event")
override val guildScheduledEvent: Optional<DiscordGuildScheduledEvent> = Optional.Missing(),
val uses: Int,
@SerialName("max_uses")
val maxUses: Int,
@SerialName("max_age")
val maxAge: Int,
val temporary: Boolean,
@SerialName("created_at")
val createdAt: Instant,
) : BaseDiscordInvite

@Serializable
public data class DiscordPartialInvite(
Expand All @@ -39,14 +95,23 @@ public data class DiscordPartialInvite(
val uses: Int
)

@Serializable
public data class DiscordInviteMetadata(
val uses: Int,
@SerialName("max_uses")
val maxUses: Int,
@SerialName("max_age")
val maxAge: Int,
val temporary: Boolean,
@SerialName("created_at")
val createdAt: String,
)
@Serializable(with = InviteTargetType.Serializer::class)
public sealed class InviteTargetType(public val value: Int) {
public class Unknown(value: Int) : InviteTargetType(value)
public object Stream : InviteTargetType(1)
public object EmbeddedApplication : InviteTargetType(2)

internal object Serializer : KSerializer<InviteTargetType> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("InviteTargetType", PrimitiveKind.INT)

override fun deserialize(decoder: Decoder): InviteTargetType = when (val value = decoder.decodeInt()) {
1 -> Stream
2 -> EmbeddedApplication
else -> Unknown(value)
}

override fun serialize(encoder: Encoder, value: InviteTargetType) {
encoder.encodeInt(value.value)
}
}
}
4 changes: 2 additions & 2 deletions common/src/main/kotlin/entity/DiscordUser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ public data class DiscordOptionallyMemberUser(


public enum class UserFlag(public val code: Int) {
None(0),
DiscordEmployee(1 shl 0),
DiscordPartner(1 shl 1),
HypeSquad(1 shl 2),
Expand All @@ -112,7 +111,8 @@ public enum class UserFlag(public val code: Int) {
BugHunterLevel2(1 shl 14),
VerifiedBot(1 shl 16),
VerifiedBotDeveloper(1 shl 17),
DiscordCertifiedModerator(1 shl 18)
DiscordCertifiedModerator(1 shl 18),
BotHttpInteractions(1 shl 19),
}

@Serializable(with = UserFlags.UserFlagsSerializer::class)
Expand Down
5 changes: 5 additions & 0 deletions common/src/main/kotlin/entity/Invite.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

@Suppress("DEPRECATION")
@Deprecated(
"This is no longer documented. Use 'InviteTargetType' instead.",
ReplaceWith("InviteTargetType", "dev.kord.common.entity.InviteTargetType"),
)
@Serializable(with = TargetUserType.Serializer::class)
public sealed class TargetUserType(public val value: Int) {
public class Unknown(value: Int) : TargetUserType(value)
Expand Down
4 changes: 3 additions & 1 deletion common/src/main/kotlin/entity/Permission.kt
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,9 @@ public sealed class Permission(public val code: DiscordBitSet) {
/** Allows for sending messages in threads. */
public object SendMessagesInThreads : Permission(1L shl 38)

/** Allows for using Activities (applications with the `EMBEDDED` flag) in a voice channel. */
/**
* Allows for using Activities (applications with the [Embedded][ApplicationFlag.Embedded] flag) in a voice channel.
*/
public object UseEmbeddedActivities : Permission(1L shl 39)

/**
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/kotlin/Kord.kt
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public class Kord(

public fun <T : EntitySupplier> with(strategy: EntitySupplyStrategy<T>): T = strategy.supply(this)

public suspend fun getApplicationInfo(): ApplicationInfo = with(EntitySupplyStrategy.rest).getApplicationInfo()
public suspend fun getApplicationInfo(): Application = with(EntitySupplyStrategy.rest).getApplicationInfo()

/**
* Requests to create a new Guild configured through the [builder].
Expand Down
Loading