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

Deserialize time as Duration #586

Merged
merged 14 commits into from
Apr 16, 2022
3 changes: 2 additions & 1 deletion common/src/main/kotlin/entity/AuditLog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dev.kord.common.entity
import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalSnowflake
import dev.kord.common.entity.optional.orEmpty
import dev.kord.common.serialization.DurationInWholeDaysSerializer
import dev.kord.common.serialization.DurationInWholeSecondsSerializer
import kotlinx.datetime.Instant
import kotlinx.serialization.*
Expand Down Expand Up @@ -348,7 +349,7 @@ public sealed class AuditLogChangeKey<T>(public val name: String, public val ser
public object ExpireBehavior : AuditLogChangeKey<IntegrationExpireBehavior>("expire_behavior", serializer())

@SerialName("expire_grace_period")
public object ExpireGracePeriod : AuditLogChangeKey<Int>("expire_grace_period", serializer())
public object ExpireGracePeriod : AuditLogChangeKey<Duration>("expire_grace_period", DurationInWholeDaysSerializer)

@SerialName("user_limit")
public object UserLimit : AuditLogChangeKey<Int>("user_limit", serializer())
Expand Down
4 changes: 2 additions & 2 deletions common/src/main/kotlin/entity/DiscordChannel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import dev.kord.common.entity.optional.OptionalBoolean
import dev.kord.common.entity.optional.OptionalInt
import dev.kord.common.entity.optional.OptionalSnowflake
import dev.kord.common.serialization.DurationInWholeMinutesSerializer
import dev.kord.common.serialization.DurationInWholeSeconds
import kotlinx.datetime.Instant
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
Expand All @@ -17,7 +18,6 @@ import kotlinx.serialization.encoding.Encoder
import kotlin.DeprecationLevel.WARNING
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
import dev.kord.common.serialization.DurationInWholeSecondsSerializer as InWholeSeconds

/**
* A representation of a [Discord Channel Structure](https://discord.com/developers/docs/resources/channel).
Expand Down Expand Up @@ -60,7 +60,7 @@ public data class DiscordChannel(
@SerialName("user_limit")
val userLimit: OptionalInt = OptionalInt.Missing,
@SerialName("rate_limit_per_user")
val rateLimitPerUser: Optional<@Serializable(InWholeSeconds::class) Duration> = Optional.Missing(),
val rateLimitPerUser: Optional<DurationInWholeSeconds> = Optional.Missing(),
val recipients: Optional<List<DiscordUser>> = Optional.Missing(),
val icon: Optional<String?> = Optional.Missing(),
@SerialName("owner_id")
Expand Down
7 changes: 2 additions & 5 deletions common/src/main/kotlin/entity/DiscordGuild.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalBoolean
import dev.kord.common.entity.optional.OptionalInt
import dev.kord.common.entity.optional.OptionalSnowflake
import dev.kord.common.serialization.DurationInWholeSecondsSerializer
import dev.kord.common.serialization.DurationInWholeSeconds
import kotlinx.datetime.Instant
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
Expand All @@ -14,7 +14,6 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlin.time.Duration

/**
* A partial representation of a [DiscordGuild] that may be [unavailable].
Expand Down Expand Up @@ -95,9 +94,7 @@ public data class DiscordGuild(
ReplaceWith("DiscordChannel#rtcRegion")
) val region: String,
@SerialName("afk_channel_id") val afkChannelId: Snowflake?,
@SerialName("afk_timeout")
@Serializable(with = DurationInWholeSecondsSerializer::class)
val afkTimeout: Duration,
@SerialName("afk_timeout") val afkTimeout: DurationInWholeSeconds,
@SerialName("widget_enabled") val widgetEnabled: OptionalBoolean = OptionalBoolean.Missing,
@SerialName("widget_channel_id") val widgetChannelId: OptionalSnowflake? = OptionalSnowflake.Missing,
@SerialName("verification_level") val verificationLevel: VerificationLevel,
Expand Down
3 changes: 2 additions & 1 deletion common/src/main/kotlin/entity/DiscordIntegration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.kord.common.entity

import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalBoolean
import dev.kord.common.serialization.DurationInWholeDays
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand All @@ -25,7 +26,7 @@ public data class DiscordIntegration(
@SerialName("expire_behavior")
val expireBehavior: IntegrationExpireBehavior,
@SerialName("expire_grace_period")
val expireGracePeriod: Int,
val expireGracePeriod: DurationInWholeDays,
val user: DiscordUser,
val account: DiscordIntegrationsAccount,
@SerialName("synced_at")
Expand Down
6 changes: 2 additions & 4 deletions common/src/main/kotlin/entity/DiscordInvite.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dev.kord.common.entity

import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalInt
import dev.kord.common.serialization.DurationInWholeSecondsSerializer
import dev.kord.common.serialization.DurationInWholeSeconds
import kotlinx.datetime.Instant
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
Expand All @@ -12,7 +12,6 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlin.time.Duration

public sealed interface BaseDiscordInvite {
public val code: String
Expand Down Expand Up @@ -80,8 +79,7 @@ public data class DiscordInviteWithMetadata(
@SerialName("max_uses")
val maxUses: Int,
@SerialName("max_age")
@Serializable(with = DurationInWholeSecondsSerializer::class)
val maxAge: Duration,
val maxAge: DurationInWholeSeconds,
val temporary: Boolean,
@SerialName("created_at")
val createdAt: Instant,
Expand Down
42 changes: 42 additions & 0 deletions common/src/main/kotlin/serialization/DurationSerializers.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.kord.common.serialization

import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
Expand Down Expand Up @@ -28,23 +29,64 @@ public sealed class DurationSerializer(private val unit: DurationUnit, name: Str
}


// nanoseconds

/** Serializer that encodes and decodes [Duration]s in [whole nanoseconds][Duration.inWholeNanoseconds]. */
public object DurationInWholeNanosecondsSerializer : DurationSerializer(NANOSECONDS, "DurationInWholeNanoseconds")
lukellmann marked this conversation as resolved.
Show resolved Hide resolved

/** A [Duration] that is [serializable][Serializable] with [DurationInWholeNanosecondsSerializer]. */
public typealias DurationInWholeNanoseconds = @Serializable(with = DurationInWholeNanosecondsSerializer::class) Duration


// microseconds

/** Serializer that encodes and decodes [Duration]s in [whole microseconds][Duration.inWholeMicroseconds]. */
public object DurationInWholeMicrosecondsSerializer : DurationSerializer(MICROSECONDS, "DurationInWholeMicroseconds")

/** A [Duration] that is [serializable][Serializable] with [DurationInWholeMicrosecondsSerializer]. */
public typealias DurationInWholeMicroseconds = @Serializable(with = DurationInWholeMicrosecondsSerializer::class) Duration


// milliseconds

/** Serializer that encodes and decodes [Duration]s in [whole milliseconds][Duration.inWholeMilliseconds]. */
public object DurationInWholeMillisecondsSerializer : DurationSerializer(MILLISECONDS, "DurationInWholeMilliseconds")

/** A [Duration] that is [serializable][Serializable] with [DurationInWholeMillisecondsSerializer]. */
public typealias DurationInWholeMilliseconds = @Serializable(with = DurationInWholeMillisecondsSerializer::class) Duration


// seconds

/** Serializer that encodes and decodes [Duration]s in [whole seconds][Duration.inWholeSeconds]. */
public object DurationInWholeSecondsSerializer : DurationSerializer(SECONDS, "DurationInWholeSeconds")

/** A [Duration] that is [serializable][Serializable] with [DurationInWholeSecondsSerializer]. */
public typealias DurationInWholeSeconds = @Serializable(with = DurationInWholeSecondsSerializer::class) Duration


// minutes

/** Serializer that encodes and decodes [Duration]s in [whole minutes][Duration.inWholeMinutes]. */
public object DurationInWholeMinutesSerializer : DurationSerializer(MINUTES, "DurationInWholeMinutes")

/** A [Duration] that is [serializable][Serializable] with [DurationInWholeMinutesSerializer]. */
public typealias DurationInWholeMinutes = @Serializable(with = DurationInWholeMinutesSerializer::class) Duration


// hours

/** Serializer that encodes and decodes [Duration]s in [whole hours][Duration.inWholeHours]. */
public object DurationInWholeHoursSerializer : DurationSerializer(HOURS, "DurationInWholeHours")

/** A [Duration] that is [serializable][Serializable] with [DurationInWholeHoursSerializer]. */
public typealias DurationInWholeHours = @Serializable(with = DurationInWholeHoursSerializer::class) Duration


// days

/** Serializer that encodes and decodes [Duration]s in [whole days][Duration.inWholeDays]. */
public object DurationInWholeDaysSerializer : DurationSerializer(DAYS, "DurationInWholeDays")

/** A [Duration] that is [serializable][Serializable] with [DurationInWholeDaysSerializer]. */
public typealias DurationInWholeDays = @Serializable(with = DurationInWholeDaysSerializer::class) Duration
5 changes: 2 additions & 3 deletions core/src/main/kotlin/cache/data/ChannelData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import dev.kord.cache.api.data.DataDescription
import dev.kord.cache.api.data.description
import dev.kord.common.entity.*
import dev.kord.common.entity.optional.*
import dev.kord.common.serialization.DurationInWholeSeconds
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlin.time.Duration
import dev.kord.common.serialization.DurationInWholeSecondsSerializer as InWholeSeconds

@Serializable
public data class ChannelData(
Expand All @@ -22,7 +21,7 @@ public data class ChannelData(
val lastMessageId: OptionalSnowflake? = OptionalSnowflake.Missing,
val bitrate: OptionalInt = OptionalInt.Missing,
val userLimit: OptionalInt = OptionalInt.Missing,
val rateLimitPerUser: Optional<@Serializable(InWholeSeconds::class) Duration> = Optional.Missing(),
val rateLimitPerUser: Optional<DurationInWholeSeconds> = Optional.Missing(),
val recipients: Optional<List<Snowflake>> = Optional.Missing(),
val icon: Optional<String?> = Optional.Missing(),
val ownerId: OptionalSnowflake = OptionalSnowflake.Missing,
Expand Down
6 changes: 2 additions & 4 deletions core/src/main/kotlin/cache/data/GuildData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import dev.kord.cache.api.data.DataDescription
import dev.kord.cache.api.data.description
import dev.kord.common.entity.*
import dev.kord.common.entity.optional.*
import dev.kord.common.serialization.DurationInWholeSecondsSerializer
import dev.kord.common.serialization.DurationInWholeSeconds
import kotlinx.serialization.Serializable
import kotlin.time.Duration

private val MessageData.nullableGuildId get() = guildId.value
private val ChannelData.nullableGuildId get() = guildId.value
Expand All @@ -26,8 +25,7 @@ public data class GuildData(
@Deprecated("The region field has been moved to Channel#rtcRegion in Discord API v9", ReplaceWith("ChannelData#rtcRegion"))
val region: String,
val afkChannelId: Snowflake? = null,
@Serializable(with = DurationInWholeSecondsSerializer::class)
val afkTimeout: Duration,
val afkTimeout: DurationInWholeSeconds,
val widgetEnabled: OptionalBoolean = OptionalBoolean.Missing,
val widgetChannelId: OptionalSnowflake? = OptionalSnowflake.Missing,
val verificationLevel: VerificationLevel,
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/kotlin/cache/data/IntegrationData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.kord.core.cache.data

import dev.kord.common.entity.*
import dev.kord.common.entity.optional.OptionalBoolean
import dev.kord.common.serialization.DurationInWholeDays
import kotlinx.serialization.Serializable

@Serializable
Expand All @@ -15,7 +16,7 @@ public data class IntegrationData(
val roleId: Snowflake,
val enableEmoticons: OptionalBoolean = OptionalBoolean.Missing,
val expireBehavior: IntegrationExpireBehavior,
val expireGracePeriod: Int,
val expireGracePeriod: DurationInWholeDays,
val user: DiscordUser,
val account: IntegrationsAccountData,
val syncedAt: String,
Expand Down
6 changes: 2 additions & 4 deletions core/src/main/kotlin/cache/data/InviteCreateData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalSnowflake
import dev.kord.common.entity.optional.map
import dev.kord.common.entity.optional.mapSnowflake
import dev.kord.common.serialization.DurationInWholeSecondsSerializer
import dev.kord.common.serialization.DurationInWholeSeconds
import dev.kord.gateway.DiscordCreatedInvite
import kotlinx.serialization.Serializable
import kotlin.time.Duration

@Serializable
public data class InviteCreateData(
Expand All @@ -18,8 +17,7 @@ public data class InviteCreateData(
val createdAt: String,
val guildId: OptionalSnowflake = OptionalSnowflake.Missing,
val inviterId: OptionalSnowflake = OptionalSnowflake.Missing,
@Serializable(with = DurationInWholeSecondsSerializer::class)
val maxAge: Duration,
val maxAge: DurationInWholeSeconds,
val maxUses: Int,
val targetType: Optional<InviteTargetType> = Optional.Missing(),
val targetUserId: OptionalSnowflake = OptionalSnowflake.Missing,
Expand Down
6 changes: 2 additions & 4 deletions core/src/main/kotlin/cache/data/InviteData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package dev.kord.core.cache.data

import dev.kord.common.entity.*
import dev.kord.common.entity.optional.*
import dev.kord.common.serialization.DurationInWholeSecondsSerializer
import dev.kord.common.serialization.DurationInWholeSeconds
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlin.time.Duration

public sealed interface BaseInviteData {
public val code: String
Expand Down Expand Up @@ -75,8 +74,7 @@ public data class InviteWithMetadataData(
override val guildScheduledEvent: Optional<GuildScheduledEventData> = Optional.Missing(),
val uses: Int,
val maxUses: Int,
@Serializable(with = DurationInWholeSecondsSerializer::class)
val maxAge: Duration,
val maxAge: DurationInWholeSeconds,
val temporary: Boolean,
val createdAt: Instant,
) : BaseInviteData {
Expand Down
6 changes: 2 additions & 4 deletions core/src/main/kotlin/entity/Integration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import java.util.*
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.time.Duration
import kotlin.time.Duration.Companion.days

/**
* A [Discord integration](https://discord.com/developers/docs/resources/guild#get-guild-integrations).
Expand Down Expand Up @@ -95,10 +94,9 @@ public class Integration(
get() = data.expireBehavior

/**
* The grace period in days before expiring subscribers.
* The grace period before expiring subscribers.
*/
public val expireGracePeriod: Duration
get() = data.expireGracePeriod.days
public val expireGracePeriod: Duration get() = data.expireGracePeriod

/**
* The id of the [user][User] for this integration.
Expand Down
11 changes: 6 additions & 5 deletions gateway/src/main/kotlin/Event.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import dev.kord.common.entity.*
import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalBoolean
import dev.kord.common.entity.optional.OptionalSnowflake
import dev.kord.common.serialization.DurationInWholeSecondsSerializer
import kotlinx.serialization.*
import dev.kord.common.serialization.DurationInWholeSeconds
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.PrimitiveKind
Expand All @@ -18,7 +21,6 @@ import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import mu.KotlinLogging
import kotlin.time.Duration
import kotlinx.serialization.DeserializationStrategy as KDeserializationStrategy

private val jsonLogger = KotlinLogging.logger { }
Expand Down Expand Up @@ -628,8 +630,7 @@ public data class DiscordCreatedInvite(
val guildId: OptionalSnowflake = OptionalSnowflake.Missing,
val inviter: Optional<DiscordUser> = Optional.Missing(),
@SerialName("max_age")
@Serializable(with = DurationInWholeSecondsSerializer::class)
val maxAge: Duration,
val maxAge: DurationInWholeSeconds,
@SerialName("max_uses")
val maxUses: Int,
@SerialName("target_type")
Expand Down
5 changes: 2 additions & 3 deletions rest/src/main/kotlin/json/request/ChannelRequests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalBoolean
import dev.kord.common.entity.optional.OptionalInt
import dev.kord.common.entity.optional.OptionalSnowflake
import dev.kord.common.serialization.DurationInWholeSeconds
import kotlinx.datetime.Instant
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlin.time.Duration
import dev.kord.common.serialization.DurationInWholeSecondsSerializer as InWholeSeconds

@Serializable
public data class ChannelModifyPutRequest(
Expand All @@ -35,7 +34,7 @@ public data class ChannelModifyPatchRequest(
val topic: Optional<String?> = Optional.Missing(),
val nsfw: OptionalBoolean? = OptionalBoolean.Missing,
@SerialName("rate_limit_per_user")
val rateLimitPerUser: Optional<@Serializable(InWholeSeconds::class) Duration?> = Optional.Missing(),
val rateLimitPerUser: Optional<DurationInWholeSeconds?> = Optional.Missing(),
val bitrate: OptionalInt? = OptionalInt.Missing,
@SerialName("user_limit")
val userLimit: OptionalInt? = OptionalInt.Missing,
Expand Down
Loading