Skip to content

Commit

Permalink
Consistent timestamp naming
Browse files Browse the repository at this point in the history
  • Loading branch information
lukellmann committed Sep 2, 2021
1 parent 957fcc4 commit fd4f387
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 45 deletions.
12 changes: 9 additions & 3 deletions common/src/main/kotlin/entity/DiscordActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ data class DiscordActivity(
val url: Optional<String?> = Optional.Missing(),
@SerialName("created_at")
val createdAt: Long,
val timestamps: Optional<DiscordActivityTimeStamps> = Optional.Missing(),
val timestamps: Optional<DiscordActivityTimestamps> = Optional.Missing(),
@SerialName("application_id")
val applicationId: OptionalSnowflake = OptionalSnowflake.Missing,
val details: Optional<String?> = Optional.Missing(),
Expand Down Expand Up @@ -67,9 +67,15 @@ class ActivityFlags(val value: Int) {
}
}

@Deprecated(
"DiscordActivityTimeStamps was renamed to DiscordActivityTimestamps.",
ReplaceWith("DiscordActivityTimestamps"),
DeprecationLevel.ERROR,
)
typealias DiscordActivityTimeStamps = DiscordActivityTimestamps

@Serializable
data class DiscordActivityTimeStamps(
data class DiscordActivityTimestamps(
val start: OptionalLong = OptionalLong.Missing,
val end: OptionalLong = OptionalLong.Missing
)
Expand Down Expand Up @@ -154,4 +160,4 @@ enum class ActivityType(val code: Int) {
}
}

}
}
25 changes: 16 additions & 9 deletions common/src/main/kotlin/entity/Snowflake.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import kotlin.time.TimeMark

/**
* A unique identifier for entities [used by discord](https://discord.com/developers/docs/reference#snowflakes).
* Snowflakes are IDs with a [timeStamp], which makes them [comparable][Comparable] based on their timestamp.
* Snowflakes are IDs with a [timestamp], which makes them [comparable][Comparable] based on their timestamp.
*
* Note: this class has a natural ordering that is inconsistent with [equals],
* since [compareTo] only compares the first 42 bits of the ULong [value] (comparing the timestamp),
Expand Down Expand Up @@ -49,13 +49,13 @@ class Snowflake : Comparable<Snowflake> {
constructor(value: String) : this(value.toULong())

/**
* Creates a Snowflake from a given [instant].
* Creates a Snowflake from a given [timestamp].
*
* If the given [instant] is too far in the past / future, this constructor will create
* an instance with a [timeStamp] equal to the timeStamp of [Snowflake.min] / [Snowflake.max].
* If the given timestamp is too far in the past / future, this constructor will create an instance with a
* [timestamp][Snowflake.timestamp] equal to the timestamp of [Snowflake.min] / [Snowflake.max].
*/
constructor(instant: Instant) : this(
instant.toEpochMilliseconds()
constructor(timestamp: Instant) : this(
timestamp.toEpochMilliseconds()
.coerceAtLeast(discordEpochLong) // time before is unknown to Snowflakes
.minus(discordEpochLong)
.coerceAtMost(maxMillisecondsSinceDiscordEpoch) // time after is unknown to Snowflakes
Expand All @@ -71,13 +71,20 @@ class Snowflake : Comparable<Snowflake> {
/**
* The point in time this Snowflake represents.
*/
@Deprecated("timeStamp was renamed to timestamp.", ReplaceWith("timestamp"), DeprecationLevel.ERROR)
val timeStamp: Instant
get() = timestamp

/**
* The point in time this Snowflake represents.
*/
val timestamp: Instant
get() = Instant.fromEpochMilliseconds(value.shr(nonTimestampBitCount).toLong().plus(discordEpochLong))

/**
* A [TimeMark] for the point in time this Snowflake represents.
*/
val timeMark: TimeMark get() = SnowflakeTimeMark(timeStamp)
val timeMark: TimeMark get() = SnowflakeTimeMark(timestamp)

override fun compareTo(other: Snowflake): Int =
value.shr(nonTimestampBitCount).compareTo(other.value.shr(nonTimestampBitCount))
Expand Down Expand Up @@ -151,9 +158,9 @@ class Snowflake : Comparable<Snowflake> {
}
}

private class SnowflakeTimeMark(private val timeStamp: Instant) : TimeMark() {
private class SnowflakeTimeMark(private val timestamp: Instant) : TimeMark() {

override fun elapsedNow(): Duration = Clock.System.now() - timeStamp
override fun elapsedNow(): Duration = Clock.System.now() - timestamp
}

/**
Expand Down
32 changes: 16 additions & 16 deletions common/src/test/kotlin/entity/SnowflakeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,54 +11,54 @@ import kotlin.test.*
class SnowflakeTest {

@Test
fun `min Snowflake's timeStamp is equal to discordEpoch`() {
assertEquals(Snowflake.discordEpoch, Snowflake.min.timeStamp)
fun `min Snowflake's timestamp is equal to discordEpoch`() {
assertEquals(Snowflake.discordEpoch, Snowflake.min.timestamp)
}

@Test
fun `max Snowflake's timeStamp is equal to endOfTime`() {
assertEquals(Snowflake.endOfTime, Snowflake.max.timeStamp)
fun `max Snowflake's timestamp is equal to endOfTime`() {
assertEquals(Snowflake.endOfTime, Snowflake.max.timestamp)
}

@Test
fun `Snowflake created from ULong MIN_VALUE has timeStamp equal to discordEpoch`() {
fun `Snowflake created from ULong MIN_VALUE has timestamp equal to discordEpoch`() {
val snowflake = Snowflake(ULong.MIN_VALUE)
assertEquals(Snowflake.discordEpoch, snowflake.timeStamp)
assertEquals(Snowflake.discordEpoch, snowflake.timestamp)
}

@Test
fun `Snowflake created from ULong MAX_VALUE has timeStamp equal to endOfTime`() {
fun `Snowflake created from ULong MAX_VALUE has timestamp equal to endOfTime`() {
val snowflake = Snowflake(ULong.MAX_VALUE)
assertEquals(Snowflake.endOfTime, snowflake.timeStamp)
assertEquals(Snowflake.endOfTime, snowflake.timestamp)
}

@Test
fun `Snowflake created from Long MIN_VALUE has timeStamp equal to discordEpoch`() {
fun `Snowflake created from Long MIN_VALUE has timestamp equal to discordEpoch`() {
val snowflake = Snowflake(Long.MIN_VALUE)
assertEquals(Snowflake.discordEpoch, snowflake.timeStamp)
assertEquals(Snowflake.discordEpoch, snowflake.timestamp)
}

@Test
fun `Snowflake created from instant far in the past has timeStamp equal to discordEpoch`() {
fun `Snowflake created from instant far in the past has timestamp equal to discordEpoch`() {
val snowflake = Snowflake(Instant.DISTANT_PAST)
assertEquals(Snowflake.discordEpoch, snowflake.timeStamp)
assertEquals(Snowflake.discordEpoch, snowflake.timestamp)
}

@Test
fun `Snowflake created from instant far in the future has timeStamp equal to endOfTime`() {
fun `Snowflake created from instant far in the future has timestamp equal to endOfTime`() {
val snowflake = Snowflake(Instant.DISTANT_FUTURE)
assertEquals(Snowflake.endOfTime, snowflake.timeStamp)
assertEquals(Snowflake.endOfTime, snowflake.timestamp)
}

@Test
fun `Snowflake's timeStamp calculates an Instant close to the Instant the Snowflake was created from`() {
fun `Snowflake's timestamp calculates an Instant close to the Instant the Snowflake was created from`() {
val instant = Clock.System.now()
val snowflake = Snowflake(instant)

// snowflake timestamps have a millisecond accuracy -> allow +/-1 millisecond from original instant
val validTimeRange = instant.minus(1, MILLISECOND)..instant.plus(1, MILLISECOND)

assertContains(validTimeRange, snowflake.timeStamp)
assertContains(validTimeRange, snowflake.timestamp)
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/kotlin/Util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ internal fun paginateThreads(
paginateByDate(
start,
batchSize,
{ threads -> threads.minOfOrNull { it.archiveTimeStamp } },
{ threads -> threads.minOfOrNull { it.archiveTimestamp } },
request
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
package dev.kord.core.behavior.channel

import dev.kord.common.entity.Snowflake
import dev.kord.common.exception.RequestException
import dev.kord.core.Kord
import dev.kord.core.entity.channel.GuildChannel
import dev.kord.core.entity.channel.GuildMessageChannel
import dev.kord.core.entity.channel.TopGuildMessageChannel
import dev.kord.core.exception.EntityNotFoundException
import dev.kord.core.supplier.EntitySupplier
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.rest.json.request.BulkDeleteRequest
import dev.kord.rest.request.RestRequestException
import kotlinx.datetime.Clock
import java.util.*
import kotlin.time.Duration

/**
Expand All @@ -33,7 +28,7 @@ interface GuildMessageChannelBehavior : GuildChannelBehavior, MessageChannelBeha
//split up in bulk delete and manual delete
// if message.timeMark + 14 days > now, then the message isn't 14 days old yet, and we can add it to the bulk delete
// if message.timeMark + 14 days < now, then the message is more than 14 days old, and we'll have to manually delete them
val (younger, older) = messages.partition { it.timeStamp > daysLimit }
val (younger, older) = messages.partition { it.timestamp > daysLimit }

younger.chunked(100).forEach {
if (it.size < 2) kord.rest.channel.deleteMessage(id, it.first(), reason)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ interface ThreadParentChannelBehavior : TopGuildMessageChannelBehavior {

/**
* Returns archived threads in the channel that are public.
* Threads are ordered by [ThreadChannel.archiveTimeStamp] in descending order.
* Threads are ordered by [ThreadChannel.archiveTimestamp] in descending order.
* Requires the [Read Message History Permission][dev.kord.common.entity.Permission.ReadMessageHistory]
*
* The returned flow is lazily executed, any [RequestException] will be thrown on
Expand Down Expand Up @@ -73,7 +73,7 @@ interface PrivateThreadParentChannelBehavior : ThreadParentChannelBehavior {

/**
* Returns archived threads in the channel that are private.
* Threads are ordered by [archive timestamp][ThreadChannel.archiveTimeStamp] in descending order.
* Threads are ordered by [archive timestamp][ThreadChannel.archiveTimestamp] in descending order.
* Requires the [Read Message History Permission][dev.kord.common.entity.Permission.ReadMessageHistory] and
* [Manage Threads Permission][dev.kord.common.entity.Permission.ManageThreads]
*
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/kotlin/cache/data/ActivityData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ data class ActivityData(
val type: ActivityType,
val url: Optional<String?> = Optional.Missing(),
val createdAt: Long,
val timestamps: Optional<DiscordActivityTimeStamps> = Optional.Missing(),
val timestamps: Optional<DiscordActivityTimestamps> = Optional.Missing(),
val applicationId: OptionalSnowflake = OptionalSnowflake.Missing,
val details: Optional<String?> = Optional.Missing(),
val state: Optional<String?> = Optional.Missing(),
Expand Down Expand Up @@ -47,4 +47,4 @@ data class ActivityData(
}


}
}
14 changes: 12 additions & 2 deletions core/src/main/kotlin/entity/channel/MessageChannel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,18 @@ interface MessageChannel : Channel, MessageChannelBehavior {
/**
* The timestamp of the last pin
*/
@Deprecated(
"lastPinTimeStamp was renamed to lastPinTimestamp.",
ReplaceWith("lastPinTimestamp"),
DeprecationLevel.ERROR,
)
val lastPinTimeStamp: Instant?
get() = data.lastPinTimestamp.value?.toInstant()
get() = lastPinTimestamp

/**
* The timestamp of the last pin
*/
val lastPinTimestamp: Instant? get() = data.lastPinTimestamp.value?.toInstant()

/**
* Requests to get the last message sent to this channel,
Expand All @@ -48,4 +58,4 @@ interface MessageChannel : Channel, MessageChannelBehavior {
*/
override fun withStrategy(strategy: EntitySupplyStrategy<*>): MessageChannel

}
}
15 changes: 13 additions & 2 deletions core/src/main/kotlin/entity/channel/thread/ThreadChannel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,18 @@ interface ThreadChannel : GuildMessageChannel, ThreadChannelBehavior {
/**
* timestamp when the thread's archive status was last changed.
*/
val archiveTimeStamp: Instant get() = threadData.archiveTimestamp.toInstant()
@Deprecated(
"archiveTimeStamp was renamed to archiveTimestamp.",
ReplaceWith("archiveTimestamp"),
DeprecationLevel.ERROR,
)
val archiveTimeStamp: Instant
get() = archiveTimestamp

/**
* timestamp when the thread's archive status was last changed.
*/
val archiveTimestamp: Instant get() = threadData.archiveTimestamp.toInstant()

/**
* The time in which the thread will be auto archived after inactivity.
Expand Down Expand Up @@ -109,4 +120,4 @@ internal fun ThreadChannel(data: ChannelData, kord: Kord, supplier: EntitySuppli
override val guildId: Snowflake
get() = data.guildId.value!!
}
}
}
12 changes: 10 additions & 2 deletions rest/src/main/kotlin/json/request/VoiceStateRequests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@ data class CurrentVoiceStateModifyRequest(
val channelId: Snowflake,
val suppress: OptionalBoolean = OptionalBoolean.Missing,
@SerialName("request_to_speak_timestamp")
val requestToSpeakTimeStamp: Optional<String> = Optional.Missing()
)
val requestToSpeakTimestamp: Optional<String> = Optional.Missing(),
) {
@Deprecated(
"requestToSpeakTimeStamp was renamed to requestToSpeakTimestamp.",
ReplaceWith("requestToSpeakTimestamp"),
DeprecationLevel.ERROR,
)
val requestToSpeakTimeStamp: Optional<String>
get() = requestToSpeakTimestamp
}


@Serializable
Expand Down

0 comments on commit fd4f387

Please sign in to comment.