From 66e344bd5050c7b4844798214cb1bc2d658f95dc Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Thu, 16 Sep 2021 18:38:12 +0200 Subject: [PATCH 01/13] Make MasterGateway an interface and provide DefaultMasterGateway --- core/src/main/kotlin/Kord.kt | 2 +- .../main/kotlin/builder/kord/KordBuilder.kt | 4 +- .../builder/kord/KordRestOnlyBuilder.kt | 4 +- .../kotlin/gateway/DefaultMasterGateway.kt | 42 +++++++++++++++ core/src/main/kotlin/gateway/MasterGateway.kt | 52 ++++++------------- .../test/kotlin/gateway/MasterGatewayTest.kt | 10 ++-- .../kotlin/live/AbstractLiveEntityTest.kt | 4 +- .../kotlin/performance/KordEventDropTest.kt | 4 +- .../kotlin/regression/CacheMissRegression.kt | 4 +- .../supplier/CacheEntitySupplierTest.kt | 4 +- 10 files changed, 77 insertions(+), 53 deletions(-) create mode 100644 core/src/main/kotlin/gateway/DefaultMasterGateway.kt diff --git a/core/src/main/kotlin/Kord.kt b/core/src/main/kotlin/Kord.kt index cbec8526cdf7..8fa884ec4137 100644 --- a/core/src/main/kotlin/Kord.kt +++ b/core/src/main/kotlin/Kord.kt @@ -3,7 +3,6 @@ package dev.kord.core import dev.kord.cache.api.DataCache import dev.kord.common.annotation.DeprecatedSinceKord import dev.kord.common.annotation.KordExperimental -import dev.kord.common.annotation.KordPreview import dev.kord.common.annotation.KordUnsafe import dev.kord.common.entity.DiscordShard import dev.kord.common.entity.PresenceStatus @@ -22,6 +21,7 @@ import dev.kord.core.exception.EntityNotFoundException import dev.kord.core.exception.KordInitializationException import dev.kord.core.gateway.MasterGateway import dev.kord.core.gateway.handler.GatewayEventInterceptor +import dev.kord.core.gateway.start import dev.kord.core.supplier.* import dev.kord.gateway.Gateway import dev.kord.gateway.builder.PresenceBuilder diff --git a/core/src/main/kotlin/builder/kord/KordBuilder.kt b/core/src/main/kotlin/builder/kord/KordBuilder.kt index 910ef1d71c35..e2996704de84 100644 --- a/core/src/main/kotlin/builder/kord/KordBuilder.kt +++ b/core/src/main/kotlin/builder/kord/KordBuilder.kt @@ -13,7 +13,7 @@ import dev.kord.core.cache.createView import dev.kord.core.cache.registerKordData import dev.kord.core.event.Event import dev.kord.core.exception.KordInitializationException -import dev.kord.core.gateway.MasterGateway +import dev.kord.core.gateway.DefaultMasterGateway import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.gateway.DefaultGateway import dev.kord.gateway.Gateway @@ -245,7 +245,7 @@ class KordBuilder(val token: String) { put(shard, gateways[index]) } } - MasterGateway(gateways) + DefaultMasterGateway(gateways) } val self = getBotIdFromToken(token) diff --git a/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt b/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt index c6b267ea1dfb..c2e6bdb0a693 100644 --- a/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt +++ b/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt @@ -7,7 +7,7 @@ import dev.kord.core.ClientResources import dev.kord.core.Kord import dev.kord.core.event.Event import dev.kord.core.exception.KordInitializationException -import dev.kord.core.gateway.MasterGateway +import dev.kord.core.gateway.DefaultMasterGateway import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.gateway.Gateway import dev.kord.gateway.Intents @@ -75,7 +75,7 @@ class KordRestOnlyBuilder(val token: String) { return Kord( resources, DataCache.none(), - MasterGateway(mapOf(0 to Gateway.none())), + DefaultMasterGateway(mapOf(0 to Gateway.none())), rest, selfId, MutableSharedFlow(), diff --git a/core/src/main/kotlin/gateway/DefaultMasterGateway.kt b/core/src/main/kotlin/gateway/DefaultMasterGateway.kt new file mode 100644 index 000000000000..4cb37a902a40 --- /dev/null +++ b/core/src/main/kotlin/gateway/DefaultMasterGateway.kt @@ -0,0 +1,42 @@ +package dev.kord.core.gateway + +import dev.kord.gateway.* +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.asFlow +import kotlinx.coroutines.flow.flattenMerge +import kotlinx.coroutines.flow.map +import kotlin.time.Duration + +data class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) + +class DefaultMasterGateway( + override val gateways: Map, +): MasterGateway { + + /** + * Calculates the average [Gateway.ping] of all running [gateways]. + * + * Gateways that return `null` are not counted into the average, if all [gateways] + * return `null` then this property will return `null` as well. + */ + override val averagePing + get(): Duration? { + val pings = gateways.values.mapNotNull { it.ping.value?.inWholeMicroseconds } + if (pings.isEmpty()) return null + + return Duration.microseconds(pings.average()) + } + + + @OptIn(FlowPreview::class) + override val events: Flow = gateways.entries.asFlow() + .map { (shard, gateway) -> gateway.events.map { ShardEvent(it, gateway, shard) } } + .flattenMerge(gateways.size.coerceAtLeast(1)) + + + override fun toString(): String { + return "MasterGateway(gateways=$gateways)" + } + +} diff --git a/core/src/main/kotlin/gateway/MasterGateway.kt b/core/src/main/kotlin/gateway/MasterGateway.kt index fc1d68a879f1..dc2e190fa45d 100644 --- a/core/src/main/kotlin/gateway/MasterGateway.kt +++ b/core/src/main/kotlin/gateway/MasterGateway.kt @@ -1,21 +1,18 @@ package dev.kord.core.gateway -import dev.kord.gateway.* +import dev.kord.gateway.Command +import dev.kord.gateway.Gateway +import dev.kord.gateway.GatewayConfiguration +import dev.kord.gateway.GatewayConfigurationBuilder import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.asFlow -import kotlinx.coroutines.flow.flattenMerge -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlin.time.Duration -import kotlin.time.microseconds +import kotlin.time.ExperimentalTime -data class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) - -class MasterGateway( - val gateways: Map, -) { +interface MasterGateway { + val gateways: Map /** * Calculates the average [Gateway.ping] of all running [gateways]. @@ -23,24 +20,14 @@ class MasterGateway( * Gateways that return `null` are not counted into the average, if all [gateways] * return `null` then this property will return `null` as well. */ - val averagePing - get(): Duration? { - val pings = gateways.values.mapNotNull { it.ping.value?.inWholeMicroseconds } - if (pings.isEmpty()) return null - - return Duration.microseconds(pings.average()) - } + @OptIn(ExperimentalTime::class) + val averagePing: Duration? @OptIn(FlowPreview::class) - val events: Flow = gateways.entries.asFlow() - .map { (shard, gateway) -> gateway.events.map { ShardEvent(it, gateway, shard) } } - .flattenMerge(gateways.size.coerceAtLeast(1)) + val events: Flow - /** - * Calls [Gateway.start] on each Gateway in [gateways], changing the [GatewayConfiguration.shard] for each Gateway. - */ - suspend fun start(configuration: GatewayConfiguration): Unit = coroutineScope { + suspend fun startWithConfig(configuration: GatewayConfiguration): Unit = coroutineScope { gateways.entries.forEach { (shard, gateway) -> val config = configuration.copy(shard = configuration.shard.copy(index = shard)) launch { @@ -49,20 +36,15 @@ class MasterGateway( } } - suspend inline fun start(token: String, config: GatewayConfigurationBuilder.() -> Unit = {}) { - val builder = GatewayConfigurationBuilder(token) - builder.apply(config) - start(builder.build()) - } - suspend fun sendAll(command: Command) = gateways.values.forEach { it.send(command) } suspend fun detachAll() = gateways.values.forEach { it.detach() } suspend fun stopAll() = gateways.values.forEach { it.stop() } - - override fun toString(): String { - return "MasterGateway(gateways=$gateways)" - } - } + +suspend inline fun MasterGateway.start(token: String, config: GatewayConfigurationBuilder.() -> Unit = {}) { + val builder = GatewayConfigurationBuilder(token) + builder.apply(config) + startWithConfig(builder.build()) +} \ No newline at end of file diff --git a/core/src/test/kotlin/gateway/MasterGatewayTest.kt b/core/src/test/kotlin/gateway/MasterGatewayTest.kt index b39c4c0cae79..14a1dc009930 100644 --- a/core/src/test/kotlin/gateway/MasterGatewayTest.kt +++ b/core/src/test/kotlin/gateway/MasterGatewayTest.kt @@ -1,6 +1,6 @@ package gateway -import dev.kord.core.gateway.MasterGateway +import dev.kord.core.gateway.DefaultMasterGateway import dev.kord.gateway.Command import dev.kord.gateway.Event import dev.kord.gateway.Gateway @@ -14,7 +14,7 @@ import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.time.Duration -internal class MasterGatewayTest { +internal class DefaultMasterGatewayTest { @Test fun `Gateway takes ping of single child`(){ @@ -23,7 +23,7 @@ internal class MasterGatewayTest { dummy.ping.value = ping - val gateway = MasterGateway( + val gateway = DefaultMasterGateway( mapOf(0 to dummy) ) @@ -40,7 +40,7 @@ internal class MasterGatewayTest { dummy1.ping.value = ping1 dummy2.ping.value = ping2 - val gateway = MasterGateway( + val gateway = DefaultMasterGateway( mapOf(0 to dummy1, 1 to dummy2) ) @@ -51,7 +51,7 @@ internal class MasterGatewayTest { fun `Gateway returns null ping when no gateway pings`(){ val dummy = DummyGateway() - val gateway = MasterGateway( + val gateway = DefaultMasterGateway( mapOf(0 to dummy) ) diff --git a/core/src/test/kotlin/live/AbstractLiveEntityTest.kt b/core/src/test/kotlin/live/AbstractLiveEntityTest.kt index a4327a556c85..9b12ba75db9d 100644 --- a/core/src/test/kotlin/live/AbstractLiveEntityTest.kt +++ b/core/src/test/kotlin/live/AbstractLiveEntityTest.kt @@ -6,7 +6,7 @@ import dev.kord.common.entity.Snowflake import dev.kord.core.ClientResources import dev.kord.core.Kord import dev.kord.core.builder.kord.Shards -import dev.kord.core.gateway.MasterGateway +import dev.kord.core.gateway.DefaultMasterGateway import dev.kord.core.live.AbstractLiveKordEntity import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.gateway.* @@ -105,7 +105,7 @@ abstract class AbstractLiveEntityTest { return Kord( resources = ClientResources("token", Snowflake(0u), Shards(1), HttpClient(), EntitySupplyStrategy.cache, Intents.none), cache = DataCache.none(), - MasterGateway(mapOf(0 to gateway)), + DefaultMasterGateway(mapOf(0 to gateway)), RestClient(KtorRequestHandler(token = "token")), randomId(), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), diff --git a/core/src/test/kotlin/performance/KordEventDropTest.kt b/core/src/test/kotlin/performance/KordEventDropTest.kt index a91d9a3f0794..7f2d2986e716 100644 --- a/core/src/test/kotlin/performance/KordEventDropTest.kt +++ b/core/src/test/kotlin/performance/KordEventDropTest.kt @@ -6,7 +6,7 @@ import dev.kord.core.ClientResources import dev.kord.core.Kord import dev.kord.core.builder.kord.Shards import dev.kord.core.event.guild.GuildCreateEvent -import dev.kord.core.gateway.MasterGateway +import dev.kord.core.gateway.DefaultMasterGateway import dev.kord.core.on import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.gateway.* @@ -49,7 +49,7 @@ class KordEventDropTest { val kord = Kord( resources = ClientResources("token", Snowflake(0u), Shards(1), HttpClient(), EntitySupplyStrategy.cache, Intents.none), cache = DataCache.none(), - MasterGateway(mapOf(0 to SpammyGateway)), + DefaultMasterGateway(mapOf(0 to SpammyGateway)), RestClient(KtorRequestHandler("token", clock = Clock.System)), Snowflake("420"), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), diff --git a/core/src/test/kotlin/regression/CacheMissRegression.kt b/core/src/test/kotlin/regression/CacheMissRegression.kt index 34aaa8e4fabe..c5e2bcf60a78 100644 --- a/core/src/test/kotlin/regression/CacheMissRegression.kt +++ b/core/src/test/kotlin/regression/CacheMissRegression.kt @@ -11,7 +11,7 @@ import dev.kord.core.builder.kord.configure import dev.kord.core.builder.kord.getBotIdFromToken import dev.kord.core.cache.data.ChannelData import dev.kord.core.cache.registerKordData -import dev.kord.core.gateway.MasterGateway +import dev.kord.core.gateway.DefaultMasterGateway import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.gateway.* import dev.kord.rest.request.JsonRequest @@ -131,7 +131,7 @@ class CacheMissingRegressions { kord = Kord( resources, MapDataCache().also { it.registerKordData() }, - MasterGateway(mapOf(0 to FakeGateway)), + DefaultMasterGateway(mapOf(0 to FakeGateway)), RestClient(CrashingHandler(resources.httpClient)), getBotIdFromToken(token), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), diff --git a/core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt b/core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt index 45476939e875..b544d89e46fe 100644 --- a/core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt +++ b/core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt @@ -7,7 +7,7 @@ import dev.kord.core.ClientResources import dev.kord.core.Kord import dev.kord.core.builder.kord.Shards import dev.kord.core.cache.KordCacheBuilder -import dev.kord.core.gateway.MasterGateway +import dev.kord.core.gateway.DefaultMasterGateway import dev.kord.gateway.Gateway import dev.kord.gateway.Intents import dev.kord.gateway.PrivilegedIntent @@ -28,7 +28,7 @@ internal class CacheEntitySupplierTest { val kord = Kord( ClientResources("", Snowflake(0u), Shards(0), HttpClient(), EntitySupplyStrategy.cache, Intents.all), KordCacheBuilder().build(), - MasterGateway(mapOf(0 to Gateway.none())), + DefaultMasterGateway(mapOf(0 to Gateway.none())), RestClient(KtorRequestHandler("")), Snowflake(0u), MutableSharedFlow(), From 7c637f36fff833705b274541ec590bf18eddc189 Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Thu, 16 Sep 2021 18:42:17 +0200 Subject: [PATCH 02/13] Declare ShardEvent in MasterGateway instead of DefaultMasterGateway --- core/src/main/kotlin/gateway/DefaultMasterGateway.kt | 2 -- core/src/main/kotlin/gateway/MasterGateway.kt | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/core/src/main/kotlin/gateway/DefaultMasterGateway.kt b/core/src/main/kotlin/gateway/DefaultMasterGateway.kt index 4cb37a902a40..f520722d4967 100644 --- a/core/src/main/kotlin/gateway/DefaultMasterGateway.kt +++ b/core/src/main/kotlin/gateway/DefaultMasterGateway.kt @@ -8,8 +8,6 @@ import kotlinx.coroutines.flow.flattenMerge import kotlinx.coroutines.flow.map import kotlin.time.Duration -data class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) - class DefaultMasterGateway( override val gateways: Map, ): MasterGateway { diff --git a/core/src/main/kotlin/gateway/MasterGateway.kt b/core/src/main/kotlin/gateway/MasterGateway.kt index dc2e190fa45d..4d527377009a 100644 --- a/core/src/main/kotlin/gateway/MasterGateway.kt +++ b/core/src/main/kotlin/gateway/MasterGateway.kt @@ -1,9 +1,6 @@ package dev.kord.core.gateway -import dev.kord.gateway.Command -import dev.kord.gateway.Gateway -import dev.kord.gateway.GatewayConfiguration -import dev.kord.gateway.GatewayConfigurationBuilder +import dev.kord.gateway.* import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow @@ -11,6 +8,8 @@ import kotlinx.coroutines.launch import kotlin.time.Duration import kotlin.time.ExperimentalTime +data class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) + interface MasterGateway { val gateways: Map From eaeb041042443ed8c1b68a66716a9ca93223785c Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Thu, 16 Sep 2021 18:43:20 +0200 Subject: [PATCH 03/13] Remove OptIn: My IDE complained, but it was not in the original source --- core/src/main/kotlin/gateway/MasterGateway.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/main/kotlin/gateway/MasterGateway.kt b/core/src/main/kotlin/gateway/MasterGateway.kt index 4d527377009a..a20ca4e636de 100644 --- a/core/src/main/kotlin/gateway/MasterGateway.kt +++ b/core/src/main/kotlin/gateway/MasterGateway.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import kotlin.time.Duration -import kotlin.time.ExperimentalTime data class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) @@ -19,7 +18,6 @@ interface MasterGateway { * Gateways that return `null` are not counted into the average, if all [gateways] * return `null` then this property will return `null` as well. */ - @OptIn(ExperimentalTime::class) val averagePing: Duration? From 42bf34952eeb4531d59d100cbcca33160aa34d02 Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Thu, 16 Sep 2021 23:40:15 +0200 Subject: [PATCH 04/13] Add extraContext field to kord --- core/src/main/kotlin/Kord.kt | 6 +++++- core/src/main/kotlin/builder/kord/KordBuilder.kt | 3 ++- .../kotlin/builder/kord/KordRestOnlyBuilder.kt | 3 ++- core/src/main/kotlin/event/Event.kt | 2 +- .../test/kotlin/live/AbstractLiveEntityTest.kt | 3 ++- .../test/kotlin/performance/KordEventDropTest.kt | 3 ++- .../test/kotlin/regression/CacheMissRegression.kt | 3 ++- .../kotlin/supplier/CacheEntitySupplierTest.kt | 15 ++++++++------- 8 files changed, 24 insertions(+), 14 deletions(-) diff --git a/core/src/main/kotlin/Kord.kt b/core/src/main/kotlin/Kord.kt index 8fa884ec4137..84f74bb6a37c 100644 --- a/core/src/main/kotlin/Kord.kt +++ b/core/src/main/kotlin/Kord.kt @@ -53,6 +53,7 @@ class Kord( val selfId: Snowflake, private val eventFlow: MutableSharedFlow, dispatcher: CoroutineDispatcher, + val extraContext: (Event.() -> CoroutineContext)? ) : CoroutineScope { private val interceptor = GatewayEventInterceptor(this, gateway, cache, eventFlow) @@ -596,6 +597,9 @@ suspend inline fun Kord(token: String, builder: KordBuilder.() -> Unit = {}): Ko inline fun Kord.on(scope: CoroutineScope = this, noinline consumer: suspend T.() -> Unit): Job = events.buffer(CoroutineChannel.UNLIMITED).filterIsInstance() .onEach { - scope.launch { runCatching { consumer(it) }.onFailure { kordLogger.catching(it) } } + val context = extraContext + ?.let { builder -> scope.coroutineContext + builder.invoke(it) } + ?: scope.coroutineContext + scope.launch(context) { runCatching { consumer(it) }.onFailure { kordLogger.catching(it) } } } .launchIn(scope) diff --git a/core/src/main/kotlin/builder/kord/KordBuilder.kt b/core/src/main/kotlin/builder/kord/KordBuilder.kt index e2996704de84..9b3e3e4f848a 100644 --- a/core/src/main/kotlin/builder/kord/KordBuilder.kt +++ b/core/src/main/kotlin/builder/kord/KordBuilder.kt @@ -265,7 +265,8 @@ class KordBuilder(val token: String) { rest, self, eventFlow, - defaultDispatcher + defaultDispatcher, + null ) } diff --git a/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt b/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt index c2e6bdb0a693..208cdbaa1350 100644 --- a/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt +++ b/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt @@ -79,7 +79,8 @@ class KordRestOnlyBuilder(val token: String) { rest, selfId, MutableSharedFlow(), - defaultDispatcher + defaultDispatcher, + null ) } } \ No newline at end of file diff --git a/core/src/main/kotlin/event/Event.kt b/core/src/main/kotlin/event/Event.kt index e9c5b6d69bfb..3618e140f935 100644 --- a/core/src/main/kotlin/event/Event.kt +++ b/core/src/main/kotlin/event/Event.kt @@ -7,7 +7,7 @@ import kotlin.coroutines.CoroutineContext interface Event : CoroutineScope { override val coroutineContext: CoroutineContext - get() = kord.coroutineContext + get() = kord.extraContext?.let { kord.coroutineContext + it.invoke(this) } ?: kord.coroutineContext /** * The Gateway that spawned this event. diff --git a/core/src/test/kotlin/live/AbstractLiveEntityTest.kt b/core/src/test/kotlin/live/AbstractLiveEntityTest.kt index 9b12ba75db9d..bc625d02dfdb 100644 --- a/core/src/test/kotlin/live/AbstractLiveEntityTest.kt +++ b/core/src/test/kotlin/live/AbstractLiveEntityTest.kt @@ -109,7 +109,8 @@ abstract class AbstractLiveEntityTest { RestClient(KtorRequestHandler(token = "token")), randomId(), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), - Dispatchers.Default + Dispatchers.Default, + null ) } diff --git a/core/src/test/kotlin/performance/KordEventDropTest.kt b/core/src/test/kotlin/performance/KordEventDropTest.kt index 7f2d2986e716..c8e38a4d2724 100644 --- a/core/src/test/kotlin/performance/KordEventDropTest.kt +++ b/core/src/test/kotlin/performance/KordEventDropTest.kt @@ -53,7 +53,8 @@ class KordEventDropTest { RestClient(KtorRequestHandler("token", clock = Clock.System)), Snowflake("420"), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), - Dispatchers.Default + Dispatchers.Default, + null ) @Test diff --git a/core/src/test/kotlin/regression/CacheMissRegression.kt b/core/src/test/kotlin/regression/CacheMissRegression.kt index c5e2bcf60a78..fb945d3ba4a8 100644 --- a/core/src/test/kotlin/regression/CacheMissRegression.kt +++ b/core/src/test/kotlin/regression/CacheMissRegression.kt @@ -135,7 +135,8 @@ class CacheMissingRegressions { RestClient(CrashingHandler(resources.httpClient)), getBotIdFromToken(token), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), - Dispatchers.Default + Dispatchers.Default, + null ) } diff --git a/core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt b/core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt index b544d89e46fe..302529faac22 100644 --- a/core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt +++ b/core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt @@ -26,13 +26,14 @@ internal class CacheEntitySupplierTest { @OptIn(PrivilegedIntent::class, KordUnsafe::class, KordExperimental::class) fun `cache does not throw when accessing unregistered entities`(): Unit = runBlocking { val kord = Kord( - ClientResources("", Snowflake(0u), Shards(0), HttpClient(), EntitySupplyStrategy.cache, Intents.all), - KordCacheBuilder().build(), - DefaultMasterGateway(mapOf(0 to Gateway.none())), - RestClient(KtorRequestHandler("")), - Snowflake(0u), - MutableSharedFlow(), - Dispatchers.Default + ClientResources("", Snowflake(0u), Shards(0), HttpClient(), EntitySupplyStrategy.cache, Intents.all), + KordCacheBuilder().build(), + DefaultMasterGateway(mapOf(0 to Gateway.none())), + RestClient(KtorRequestHandler("")), + Snowflake(0u), + MutableSharedFlow(), + Dispatchers.Default, + null ) kord.unsafe.guild(Snowflake(0u)).regions.toList() From b1c6044b974b563cd648c6d179a7d09fb8b81a04 Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Fri, 17 Sep 2021 16:15:57 +0200 Subject: [PATCH 05/13] Extra-Context can default to null for compat --- core/src/main/kotlin/Kord.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/kotlin/Kord.kt b/core/src/main/kotlin/Kord.kt index 84f74bb6a37c..5d7ae7263675 100644 --- a/core/src/main/kotlin/Kord.kt +++ b/core/src/main/kotlin/Kord.kt @@ -53,7 +53,7 @@ class Kord( val selfId: Snowflake, private val eventFlow: MutableSharedFlow, dispatcher: CoroutineDispatcher, - val extraContext: (Event.() -> CoroutineContext)? + val extraContext: (Event.() -> CoroutineContext)? = null ) : CoroutineScope { private val interceptor = GatewayEventInterceptor(this, gateway, cache, eventFlow) From 946a5c452d5a9ab36897d9dcd912afc15087776f Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Wed, 22 Sep 2021 13:37:22 +0200 Subject: [PATCH 06/13] Make GatewayEventInterceptor customizable --- core/src/main/kotlin/Kord.kt | 20 ++++--- .../handler/DefaultGatewayEventInterceptor.kt | 52 +++++++++++++++++++ .../handler/GatewayEventInterceptor.kt | 50 ++---------------- 3 files changed, 69 insertions(+), 53 deletions(-) create mode 100644 core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt diff --git a/core/src/main/kotlin/Kord.kt b/core/src/main/kotlin/Kord.kt index 5d7ae7263675..4a4e30d47717 100644 --- a/core/src/main/kotlin/Kord.kt +++ b/core/src/main/kotlin/Kord.kt @@ -20,6 +20,7 @@ import dev.kord.core.event.Event import dev.kord.core.exception.EntityNotFoundException import dev.kord.core.exception.KordInitializationException import dev.kord.core.gateway.MasterGateway +import dev.kord.core.gateway.handler.DefaultGatewayEventInterceptor import dev.kord.core.gateway.handler.GatewayEventInterceptor import dev.kord.core.gateway.start import dev.kord.core.supplier.* @@ -53,9 +54,17 @@ class Kord( val selfId: Snowflake, private val eventFlow: MutableSharedFlow, dispatcher: CoroutineDispatcher, - val extraContext: (Event.() -> CoroutineContext)? = null + interceptorBuilder: Kord.() -> GatewayEventInterceptor = { + DefaultGatewayEventInterceptor( + this, + gateway, + cache, + eventFlow + ) + } ) : CoroutineScope { - private val interceptor = GatewayEventInterceptor(this, gateway, cache, eventFlow) + + private val interceptor = interceptorBuilder.invoke(this) /** * Global commands made by the bot under this Kord instance. @@ -596,10 +605,7 @@ suspend inline fun Kord(token: String, builder: KordBuilder.() -> Unit = {}): Ko */ inline fun Kord.on(scope: CoroutineScope = this, noinline consumer: suspend T.() -> Unit): Job = events.buffer(CoroutineChannel.UNLIMITED).filterIsInstance() - .onEach { - val context = extraContext - ?.let { builder -> scope.coroutineContext + builder.invoke(it) } - ?: scope.coroutineContext - scope.launch(context) { runCatching { consumer(it) }.onFailure { kordLogger.catching(it) } } + .onEach { event -> + scope.launch(event.coroutineContext) { runCatching { consumer(event) }.onFailure { kordLogger.catching(it) } } } .launchIn(scope) diff --git a/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt b/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt new file mode 100644 index 000000000000..8273e6f641a2 --- /dev/null +++ b/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt @@ -0,0 +1,52 @@ +package dev.kord.core.gateway.handler + +import dev.kord.cache.api.DataCache +import dev.kord.core.Kord +import dev.kord.core.gateway.MasterGateway +import dev.kord.gateway.Event +import io.ktor.util.* +import kotlinx.coroutines.Job +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.buffer +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import mu.KotlinLogging +import dev.kord.core.event.Event as CoreEvent + +private val logger = KotlinLogging.logger { } + +@Suppress("EXPERIMENTAL_API_USAGE") +class DefaultGatewayEventInterceptor( + private val kord: Kord, + private val gateway: MasterGateway, + cache: DataCache, + coreFlow: MutableSharedFlow, +): GatewayEventInterceptor { + + private val listeners = listOf( + MessageEventHandler(kord, gateway, cache, coreFlow), + ChannelEventHandler(kord, gateway, cache, coreFlow), + ThreadEventHandler(kord, gateway, cache, coreFlow), + GuildEventHandler(kord, gateway, cache, coreFlow), + LifeCycleEventHandler(kord, gateway, cache, coreFlow), + UserEventHandler(kord, gateway, cache, coreFlow), + VoiceEventHandler(kord, gateway, cache, coreFlow), + WebhookEventHandler(kord, gateway, cache, coreFlow), + InteractionEventHandler(kord, gateway, cache, coreFlow) + ) + + override suspend fun start(): Job = gateway.events + .buffer(Channel.UNLIMITED) + .onEach { (event, _, shard) -> dispatch(event, shard) } + .launchIn(kord) + + private suspend fun dispatch(event: Event, shard: Int) { + runCatching { + listeners.forEach { it.handle(event, shard) } + }.onFailure { + logger.error(it) + } + } + +} diff --git a/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt b/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt index dd2b1c492404..de3f724ac7cb 100644 --- a/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt +++ b/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt @@ -1,51 +1,9 @@ package dev.kord.core.gateway.handler -import dev.kord.cache.api.DataCache -import dev.kord.core.Kord -import dev.kord.core.gateway.MasterGateway -import dev.kord.gateway.Event -import io.ktor.util.* -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.buffer -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import mu.KotlinLogging -import dev.kord.core.event.Event as CoreEvent +import kotlinx.coroutines.Job -private val logger = KotlinLogging.logger { } +interface GatewayEventInterceptor { -@Suppress("EXPERIMENTAL_API_USAGE") -class GatewayEventInterceptor( - private val kord: Kord, - private val gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow, -) { + suspend fun start(): Job - private val listeners = listOf( - MessageEventHandler(kord, gateway, cache, coreFlow), - ChannelEventHandler(kord, gateway, cache, coreFlow), - ThreadEventHandler(kord, gateway, cache, coreFlow), - GuildEventHandler(kord, gateway, cache, coreFlow), - LifeCycleEventHandler(kord, gateway, cache, coreFlow), - UserEventHandler(kord, gateway, cache, coreFlow), - VoiceEventHandler(kord, gateway, cache, coreFlow), - WebhookEventHandler(kord, gateway, cache, coreFlow), - InteractionEventHandler(kord, gateway, cache, coreFlow) - ) - - suspend fun start() = gateway.events - .buffer(Channel.UNLIMITED) - .onEach { (event, _, shard) -> dispatch(event, shard) } - .launchIn(kord) - - private suspend fun dispatch(event: Event, shard: Int) { - runCatching { - listeners.forEach { it.handle(event, shard) } - }.onFailure { - logger.error(it) - } - } - -} +} \ No newline at end of file From 4e5ed4f1c2a81f9cfdcde9c159793c476505e5ec Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Wed, 22 Sep 2021 13:40:20 +0200 Subject: [PATCH 07/13] Revert constructor changes in all places --- core/src/main/kotlin/builder/kord/KordBuilder.kt | 3 +-- core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt | 3 +-- core/src/test/kotlin/live/AbstractLiveEntityTest.kt | 3 +-- core/src/test/kotlin/performance/KordEventDropTest.kt | 3 +-- core/src/test/kotlin/regression/CacheMissRegression.kt | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/core/src/main/kotlin/builder/kord/KordBuilder.kt b/core/src/main/kotlin/builder/kord/KordBuilder.kt index 9b3e3e4f848a..e2996704de84 100644 --- a/core/src/main/kotlin/builder/kord/KordBuilder.kt +++ b/core/src/main/kotlin/builder/kord/KordBuilder.kt @@ -265,8 +265,7 @@ class KordBuilder(val token: String) { rest, self, eventFlow, - defaultDispatcher, - null + defaultDispatcher ) } diff --git a/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt b/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt index 208cdbaa1350..c2e6bdb0a693 100644 --- a/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt +++ b/core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt @@ -79,8 +79,7 @@ class KordRestOnlyBuilder(val token: String) { rest, selfId, MutableSharedFlow(), - defaultDispatcher, - null + defaultDispatcher ) } } \ No newline at end of file diff --git a/core/src/test/kotlin/live/AbstractLiveEntityTest.kt b/core/src/test/kotlin/live/AbstractLiveEntityTest.kt index bc625d02dfdb..9b12ba75db9d 100644 --- a/core/src/test/kotlin/live/AbstractLiveEntityTest.kt +++ b/core/src/test/kotlin/live/AbstractLiveEntityTest.kt @@ -109,8 +109,7 @@ abstract class AbstractLiveEntityTest { RestClient(KtorRequestHandler(token = "token")), randomId(), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), - Dispatchers.Default, - null + Dispatchers.Default ) } diff --git a/core/src/test/kotlin/performance/KordEventDropTest.kt b/core/src/test/kotlin/performance/KordEventDropTest.kt index c8e38a4d2724..7f2d2986e716 100644 --- a/core/src/test/kotlin/performance/KordEventDropTest.kt +++ b/core/src/test/kotlin/performance/KordEventDropTest.kt @@ -53,8 +53,7 @@ class KordEventDropTest { RestClient(KtorRequestHandler("token", clock = Clock.System)), Snowflake("420"), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), - Dispatchers.Default, - null + Dispatchers.Default ) @Test diff --git a/core/src/test/kotlin/regression/CacheMissRegression.kt b/core/src/test/kotlin/regression/CacheMissRegression.kt index fb945d3ba4a8..c5e2bcf60a78 100644 --- a/core/src/test/kotlin/regression/CacheMissRegression.kt +++ b/core/src/test/kotlin/regression/CacheMissRegression.kt @@ -135,8 +135,7 @@ class CacheMissingRegressions { RestClient(CrashingHandler(resources.httpClient)), getBotIdFromToken(token), MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), - Dispatchers.Default, - null + Dispatchers.Default ) } From 1be4946fd1f9120dc1876c6044bb883956318f7b Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Wed, 22 Sep 2021 13:41:26 +0200 Subject: [PATCH 08/13] Revert change in Event.kt --- core/src/main/kotlin/event/Event.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/kotlin/event/Event.kt b/core/src/main/kotlin/event/Event.kt index 3618e140f935..e9c5b6d69bfb 100644 --- a/core/src/main/kotlin/event/Event.kt +++ b/core/src/main/kotlin/event/Event.kt @@ -7,7 +7,7 @@ import kotlin.coroutines.CoroutineContext interface Event : CoroutineScope { override val coroutineContext: CoroutineContext - get() = kord.extraContext?.let { kord.coroutineContext + it.invoke(this) } ?: kord.coroutineContext + get() = kord.coroutineContext /** * The Gateway that spawned this event. From bb3f0f4fba4f89929875e4cdcd139a298cd48d4f Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Wed, 22 Sep 2021 15:32:52 +0200 Subject: [PATCH 09/13] move coroutineContext to constructor --- core/src/main/kotlin/event/Event.kt | 3 - .../event/channel/ChannelCreateEvent.kt | 51 ++++++++++++--- .../event/channel/ChannelDeleteEvent.kt | 52 ++++++++++++---- .../event/channel/ChannelPinsUpdateEvent.kt | 4 +- .../event/channel/ChannelUpdateEvent.kt | 49 ++++++++++++--- .../kotlin/event/channel/TypingStartEvent.kt | 2 + .../event/channel/thread/ThreadCreateEvent.kt | 19 +++++- .../event/channel/thread/ThreadDeleteEvent.kt | 8 ++- .../channel/thread/ThreadListSyncEvent.kt | 4 +- .../channel/thread/ThreadMemberUpdateEvent.kt | 4 +- .../thread/ThreadMembersUpdateEvent.kt | 4 +- .../event/channel/thread/ThreadUpdateEvent.kt | 19 +++++- core/src/main/kotlin/event/gateway/Events.kt | 62 +++++++++++++++---- .../main/kotlin/event/guild/BanAddEvent.kt | 4 +- .../main/kotlin/event/guild/BanRemoveEvent.kt | 4 +- .../kotlin/event/guild/EmojisUpdateEvent.kt | 4 +- .../kotlin/event/guild/GuildCreateEvent.kt | 7 ++- .../kotlin/event/guild/GuildDeleteEvent.kt | 4 +- .../kotlin/event/guild/GuildUpdateEvent.kt | 7 ++- .../event/guild/IntegrationsUpdateEvent.kt | 4 +- .../kotlin/event/guild/InviteCreateEvent.kt | 2 + .../kotlin/event/guild/InviteDeleteEvent.kt | 5 +- .../kotlin/event/guild/MemberJoinEvent.kt | 4 +- .../kotlin/event/guild/MemberLeaveEvent.kt | 10 ++- .../kotlin/event/guild/MemberUpdateEvent.kt | 2 + .../kotlin/event/guild/MembersChunkEvent.kt | 7 +-- .../event/guild/VoiceServerUpdateEvent.kt | 4 +- .../kotlin/event/guild/WebhookUpdateEvent.kt | 4 +- .../interaction/ApplicationCommandCreate.kt | 6 +- .../interaction/ApplicationCommandDelete.kt | 6 +- .../interaction/ApplicationCommandUpdate.kt | 6 +- .../event/interaction/ApplicationCreate.kt | 20 +++--- .../event/interaction/ComponentCreate.kt | 3 + .../event/message/MessageBulkDeleteEvent.kt | 4 +- .../event/message/MessageCreateEvent.kt | 4 +- .../event/message/MessageDeleteEvent.kt | 2 + .../event/message/MessageUpdateEvent.kt | 4 +- .../kotlin/event/message/ReactionAddEvent.kt | 4 +- .../event/message/ReactionRemoveAllEvent.kt | 4 +- .../event/message/ReactionRemoveEmojiEvent.kt | 4 +- .../event/message/ReactionRemoveEvent.kt | 4 +- .../main/kotlin/event/role/RoleCreateEvent.kt | 2 + .../main/kotlin/event/role/RoleDeleteEvent.kt | 4 +- .../main/kotlin/event/role/RoleUpdateEvent.kt | 4 +- .../kotlin/event/user/PresenceUpdateEvent.kt | 4 +- .../main/kotlin/event/user/UserUpdateEvent.kt | 4 +- .../event/user/VoiceStateUpdateEvent.kt | 4 +- 47 files changed, 350 insertions(+), 96 deletions(-) diff --git a/core/src/main/kotlin/event/Event.kt b/core/src/main/kotlin/event/Event.kt index e9c5b6d69bfb..180bf71e9c2a 100644 --- a/core/src/main/kotlin/event/Event.kt +++ b/core/src/main/kotlin/event/Event.kt @@ -6,9 +6,6 @@ import kotlinx.coroutines.CoroutineScope import kotlin.coroutines.CoroutineContext interface Event : CoroutineScope { - override val coroutineContext: CoroutineContext - get() = kord.coroutineContext - /** * The Gateway that spawned this event. */ diff --git a/core/src/main/kotlin/event/channel/ChannelCreateEvent.kt b/core/src/main/kotlin/event/channel/ChannelCreateEvent.kt index 8d459da834f0..613194f6d09c 100644 --- a/core/src/main/kotlin/event/channel/ChannelCreateEvent.kt +++ b/core/src/main/kotlin/event/channel/ChannelCreateEvent.kt @@ -2,9 +2,8 @@ package dev.kord.core.event.channel import dev.kord.core.Kord import dev.kord.core.entity.channel.* -import dev.kord.core.entity.channel.thread.NewsChannelThread -import dev.kord.core.entity.channel.thread.TextChannelThread import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext interface ChannelCreateEvent : Event { val channel: Channel @@ -12,50 +11,82 @@ interface ChannelCreateEvent : Event { get() = channel.kord } -class CategoryCreateEvent(override val channel: Category, override val shard: Int) : ChannelCreateEvent { +class CategoryCreateEvent( + override val channel: Category, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "CategoryCreateEvent(channel=$channel, shard=$shard)" } } -class DMChannelCreateEvent(override val channel: DmChannel, override val shard: Int) : ChannelCreateEvent { +class DMChannelCreateEvent( + override val channel: DmChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "DMChannelCreateEvent(channel=$channel, shard=$shard)" } } -class NewsChannelCreateEvent(override val channel: NewsChannel, override val shard: Int) : ChannelCreateEvent { +class NewsChannelCreateEvent( + override val channel: NewsChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "NewsChannelCreateEvent(channel=$channel, shard=$shard)" } } -class StoreChannelCreateEvent(override val channel: StoreChannel, override val shard: Int) : ChannelCreateEvent { +class StoreChannelCreateEvent( + override val channel: StoreChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "StoreChannelCreateEvent(channel=$channel, shard=$shard)" } } -class TextChannelCreateEvent(override val channel: TextChannel, override val shard: Int) : ChannelCreateEvent { +class TextChannelCreateEvent( + override val channel: TextChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "TextChannelCreateEvent(channel=$channel, shard=$shard)" } } -class VoiceChannelCreateEvent(override val channel: VoiceChannel, override val shard: Int) : ChannelCreateEvent { +class VoiceChannelCreateEvent( + override val channel: VoiceChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "VoiceChannelCreateEvent(channel=$channel, shard=$shard)" } } -class StageChannelCreateEvent(override val channel: StageChannel, override val shard: Int) : ChannelCreateEvent { +class StageChannelCreateEvent( + override val channel: StageChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "StageChannelCreateEvent(channel=$channel, shard=$shard)" } } -class UnknownChannelCreateEvent(override val channel: Channel, override val shard: Int) : ChannelCreateEvent { +class UnknownChannelCreateEvent( + override val channel: Channel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "UnknownChannelCreateEvent(channel=$channel, shard=$shard)" } diff --git a/core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt b/core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt index 5f2313dc19c6..f3ec63d4a8e0 100644 --- a/core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt +++ b/core/src/main/kotlin/event/channel/ChannelDeleteEvent.kt @@ -2,10 +2,8 @@ package dev.kord.core.event.channel import dev.kord.core.Kord import dev.kord.core.entity.channel.* -import dev.kord.core.entity.channel.thread.DeletedThreadChannel -import dev.kord.core.entity.channel.thread.NewsChannelThread -import dev.kord.core.entity.channel.thread.TextChannelThread import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext interface ChannelDeleteEvent : Event { val channel: Channel @@ -13,49 +11,81 @@ interface ChannelDeleteEvent : Event { get() = channel.kord } -class CategoryDeleteEvent(override val channel: Category, override val shard: Int) : ChannelDeleteEvent { +class CategoryDeleteEvent( + override val channel: Category, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelDeleteEvent { override fun toString(): String { return "CategoryDeleteEvent(channel=$channel, shard=$shard)" } } -class DMChannelDeleteEvent(override val channel: DmChannel, override val shard: Int) : ChannelDeleteEvent { +class DMChannelDeleteEvent( + override val channel: DmChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelDeleteEvent { override fun toString(): String { return "DMChannelDeleteEvent(channel=$channel, shard=$shard)" } } -class NewsChannelDeleteEvent(override val channel: NewsChannel, override val shard: Int) : ChannelDeleteEvent { +class NewsChannelDeleteEvent( + override val channel: NewsChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelDeleteEvent { override fun toString(): String { return "NewsChannelDeleteEvent(channel=$channel, shard=$shard)" } } -class StoreChannelDeleteEvent(override val channel: StoreChannel, override val shard: Int) : ChannelDeleteEvent { +class StoreChannelDeleteEvent( + override val channel: StoreChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelDeleteEvent { override fun toString(): String { return "StoreChannelDeleteEvent(channel=$channel, shard=$shard)" } } -class TextChannelDeleteEvent(override val channel: TextChannel, override val shard: Int) : ChannelDeleteEvent { +class TextChannelDeleteEvent( + override val channel: TextChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelDeleteEvent { override fun toString(): String { return "TextChannelDeleteEvent(channel=$channel, shard=$shard)" } } -class VoiceChannelDeleteEvent(override val channel: VoiceChannel, override val shard: Int) : ChannelDeleteEvent { +class VoiceChannelDeleteEvent( + override val channel: VoiceChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelDeleteEvent { override fun toString(): String { return "VoiceChannelDeleteEvent(channel=$channel, shard=$shard)" } } -class StageChannelDeleteEvent(override val channel: StageChannel, override val shard: Int) : ChannelDeleteEvent { +class StageChannelDeleteEvent( + override val channel: StageChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelDeleteEvent { override fun toString(): String { return "StageChannelDeleteEvent(channel=$channel, shard=$shard)" } } -class UnknownChannelDeleteEvent(override val channel: Channel, override val shard: Int) : ChannelCreateEvent { +class UnknownChannelDeleteEvent( + override val channel: Channel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "UnknownChannelDeleteEvent(channel=$channel, shard=$shard)" } diff --git a/core/src/main/kotlin/event/channel/ChannelPinsUpdateEvent.kt b/core/src/main/kotlin/event/channel/ChannelPinsUpdateEvent.kt index 875b0a1e40b2..026b04eb009a 100644 --- a/core/src/main/kotlin/event/channel/ChannelPinsUpdateEvent.kt +++ b/core/src/main/kotlin/event/channel/ChannelPinsUpdateEvent.kt @@ -14,12 +14,14 @@ import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull import kotlinx.datetime.Instant import kotlinx.datetime.toInstant +import kotlin.coroutines.CoroutineContext class ChannelPinsUpdateEvent( val data: ChannelPinsUpdateEventData, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val channelId: Snowflake get() = data.channelId diff --git a/core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt b/core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt index a56dc75a2201..0e22f0850941 100644 --- a/core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt +++ b/core/src/main/kotlin/event/channel/ChannelUpdateEvent.kt @@ -5,6 +5,7 @@ import dev.kord.core.entity.channel.* import dev.kord.core.entity.channel.thread.NewsChannelThread import dev.kord.core.entity.channel.thread.TextChannelThread import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext interface ChannelUpdateEvent : Event { val channel: Channel @@ -12,50 +13,82 @@ interface ChannelUpdateEvent : Event { get() = channel.kord } -class CategoryUpdateEvent(override val channel: Category, override val shard: Int) : ChannelUpdateEvent { +class CategoryUpdateEvent( + override val channel: Category, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelUpdateEvent { override fun toString(): String { return "CategoryUpdateEvent(channel=$channel, shard=$shard)" } } -class DMChannelUpdateEvent(override val channel: DmChannel, override val shard: Int) : ChannelUpdateEvent { +class DMChannelUpdateEvent( + override val channel: DmChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelUpdateEvent { override fun toString(): String { return "DMChannelUpdateEvent(channel=$channel, shard=$shard)" } } -class NewsChannelUpdateEvent(override val channel: NewsChannel, override val shard: Int) : ChannelUpdateEvent { +class NewsChannelUpdateEvent( + override val channel: NewsChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelUpdateEvent { override fun toString(): String { return "NewsChannelUpdateEvent(channel=$channel, shard=$shard)" } } -class StoreChannelUpdateEvent(override val channel: StoreChannel, override val shard: Int) : ChannelUpdateEvent { +class StoreChannelUpdateEvent( + override val channel: StoreChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelUpdateEvent { override fun toString(): String { return "StoreChannelUpdateEvent(channel=$channel, shard=$shard)" } } -class TextChannelUpdateEvent(override val channel: TextChannel, override val shard: Int) : ChannelUpdateEvent { +class TextChannelUpdateEvent( + override val channel: TextChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelUpdateEvent { override fun toString(): String { return "TextChannelUpdateEvent(channel=$channel, shard=$shard)" } } -class VoiceChannelUpdateEvent(override val channel: VoiceChannel, override val shard: Int) : ChannelUpdateEvent { +class VoiceChannelUpdateEvent( + override val channel: VoiceChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelUpdateEvent { override fun toString(): String { return "VoiceChannelUpdateEvent(channel=$channel, shard=$shard)" } } -class StageChannelUpdateEvent(override val channel: StageChannel, override val shard: Int) : ChannelUpdateEvent { +class StageChannelUpdateEvent( + override val channel: StageChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelUpdateEvent { override fun toString(): String { return "StageChannelUpdateEvent(channel=$channel, shard=$shard)" } } -class UnknownChannelUpdateEvent(override val channel: Channel, override val shard: Int) : ChannelCreateEvent { +class UnknownChannelUpdateEvent( + override val channel: Channel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ChannelCreateEvent { override fun toString(): String { return "UnknownChannelUpdateEvent(channel=$channel, shard=$shard)" } diff --git a/core/src/main/kotlin/event/channel/TypingStartEvent.kt b/core/src/main/kotlin/event/channel/TypingStartEvent.kt index d44659a2a3c0..abb34898e7ee 100644 --- a/core/src/main/kotlin/event/channel/TypingStartEvent.kt +++ b/core/src/main/kotlin/event/channel/TypingStartEvent.kt @@ -19,12 +19,14 @@ import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull import dev.kord.core.toInstant import kotlinx.datetime.Instant +import kotlin.coroutines.CoroutineContext class TypingStartEvent( val data: TypingStartEventData, override val kord: Kord, override val shard: Int, override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val channelId: Snowflake get() = data.channelId diff --git a/core/src/main/kotlin/event/channel/thread/ThreadCreateEvent.kt b/core/src/main/kotlin/event/channel/thread/ThreadCreateEvent.kt index dff75f91a9a3..3c41b6106ac9 100644 --- a/core/src/main/kotlin/event/channel/thread/ThreadCreateEvent.kt +++ b/core/src/main/kotlin/event/channel/thread/ThreadCreateEvent.kt @@ -4,26 +4,39 @@ import dev.kord.core.entity.channel.thread.NewsChannelThread import dev.kord.core.entity.channel.thread.TextChannelThread import dev.kord.core.entity.channel.thread.ThreadChannel import dev.kord.core.event.channel.ChannelCreateEvent +import kotlin.coroutines.CoroutineContext sealed interface ThreadChannelCreateEvent : ChannelCreateEvent { override val channel: ThreadChannel } -class TextChannelThreadCreateEvent(override val channel: TextChannelThread, override val shard: Int) : ThreadChannelCreateEvent { +class TextChannelThreadCreateEvent( + override val channel: TextChannelThread, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ThreadChannelCreateEvent { override fun toString(): String { return "TextThreadChannelCreateEvent(channel=$channel, shard=$shard)" } } -class NewsChannelThreadCreateEvent(override val channel: NewsChannelThread, override val shard: Int) : ThreadChannelCreateEvent { +class NewsChannelThreadCreateEvent( + override val channel: NewsChannelThread, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ThreadChannelCreateEvent { override fun toString(): String { return "NewsThreadChannelCreateEvent(channel=$channel, shard=$shard)" } } -class UnknownChannelThreadCreateEvent(override val channel: ThreadChannel, override val shard: Int) : ThreadChannelCreateEvent { +class UnknownChannelThreadCreateEvent( + override val channel: ThreadChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ThreadChannelCreateEvent { override fun toString(): String { return "UnknownChannelThreadCreateEvent(channel=$channel, shard=$shard)" } diff --git a/core/src/main/kotlin/event/channel/thread/ThreadDeleteEvent.kt b/core/src/main/kotlin/event/channel/thread/ThreadDeleteEvent.kt index 4a51d51bee18..cff5babe128e 100644 --- a/core/src/main/kotlin/event/channel/thread/ThreadDeleteEvent.kt +++ b/core/src/main/kotlin/event/channel/thread/ThreadDeleteEvent.kt @@ -8,6 +8,7 @@ import dev.kord.core.entity.channel.thread.ThreadChannel import dev.kord.core.event.Event import dev.kord.core.event.channel.ChannelCreateEvent import dev.kord.core.event.channel.ChannelDeleteEvent +import kotlin.coroutines.CoroutineContext sealed interface ThreadChannelDeleteEvent : Event { val channel: DeletedThreadChannel @@ -24,6 +25,7 @@ class TextChannelThreadDeleteEvent( override val channel: DeletedThreadChannel, override val old: TextChannelThread?, override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, ) : ThreadChannelDeleteEvent { override fun toString(): String { return "TextThreadChannelDeleteEvent(channel=$channel, shard=$shard)" @@ -34,7 +36,8 @@ class TextChannelThreadDeleteEvent( class NewsChannelThreadDeleteEvent( override val channel: DeletedThreadChannel, override val old: NewsChannelThread?, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, ) : ThreadChannelDeleteEvent { override fun toString(): String { return "NewsThreadChannelDeleteEvent(channel=$channel, shard=$shard)" @@ -45,7 +48,8 @@ class NewsChannelThreadDeleteEvent( class UnknownChannelThreadDeleteEvent( override val channel: DeletedThreadChannel, override val old: ThreadChannel?, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, ) : ThreadChannelDeleteEvent { override fun toString(): String { return "UnknownChannelThreadDeleteEvent(channel=$channel, shard=$shard)" diff --git a/core/src/main/kotlin/event/channel/thread/ThreadListSyncEvent.kt b/core/src/main/kotlin/event/channel/thread/ThreadListSyncEvent.kt index bed9cd574523..a8ad7cd3f06d 100644 --- a/core/src/main/kotlin/event/channel/thread/ThreadListSyncEvent.kt +++ b/core/src/main/kotlin/event/channel/thread/ThreadListSyncEvent.kt @@ -17,13 +17,15 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.filter +import kotlin.coroutines.CoroutineContext class ThreadListSyncEvent( val data: ThreadListSyncData, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val guildId: Snowflake get() = data.guildId diff --git a/core/src/main/kotlin/event/channel/thread/ThreadMemberUpdateEvent.kt b/core/src/main/kotlin/event/channel/thread/ThreadMemberUpdateEvent.kt index 486e866719bb..393dbd518f48 100644 --- a/core/src/main/kotlin/event/channel/thread/ThreadMemberUpdateEvent.kt +++ b/core/src/main/kotlin/event/channel/thread/ThreadMemberUpdateEvent.kt @@ -3,9 +3,11 @@ package dev.kord.core.event.channel.thread import dev.kord.core.Kord import dev.kord.core.entity.channel.thread.ThreadMember import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext class ThreadMemberUpdateEvent( val member: ThreadMember, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event \ No newline at end of file diff --git a/core/src/main/kotlin/event/channel/thread/ThreadMembersUpdateEvent.kt b/core/src/main/kotlin/event/channel/thread/ThreadMembersUpdateEvent.kt index 6124276fac0b..0eedbe5d3e37 100644 --- a/core/src/main/kotlin/event/channel/thread/ThreadMembersUpdateEvent.kt +++ b/core/src/main/kotlin/event/channel/thread/ThreadMembersUpdateEvent.kt @@ -7,11 +7,13 @@ import dev.kord.core.behavior.MemberBehavior import dev.kord.core.cache.data.ThreadMembersUpdateEventData import dev.kord.core.entity.channel.thread.ThreadMember import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext class ThreadMembersUpdateEvent( val data: ThreadMembersUpdateEventData, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event { val id: Snowflake get() = data.id diff --git a/core/src/main/kotlin/event/channel/thread/ThreadUpdateEvent.kt b/core/src/main/kotlin/event/channel/thread/ThreadUpdateEvent.kt index 078d92888c26..96c2befce047 100644 --- a/core/src/main/kotlin/event/channel/thread/ThreadUpdateEvent.kt +++ b/core/src/main/kotlin/event/channel/thread/ThreadUpdateEvent.kt @@ -4,13 +4,18 @@ import dev.kord.core.entity.channel.thread.NewsChannelThread import dev.kord.core.entity.channel.thread.TextChannelThread import dev.kord.core.entity.channel.thread.ThreadChannel import dev.kord.core.event.channel.ChannelUpdateEvent +import kotlin.coroutines.CoroutineContext sealed interface ThreadUpdateEvent : ChannelUpdateEvent { override val channel: ThreadChannel } -class TextChannelThreadUpdateEvent(override val channel: TextChannelThread, override val shard: Int) : +class TextChannelThreadUpdateEvent( + override val channel: TextChannelThread, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ThreadUpdateEvent { override fun toString(): String { return "TextThreadChannelUpdateEvent(channel=$channel, shard=$shard)" @@ -18,7 +23,11 @@ class TextChannelThreadUpdateEvent(override val channel: TextChannelThread, over } -class NewsChannelThreadUpdateEvent(override val channel: NewsChannelThread, override val shard: Int) : +class NewsChannelThreadUpdateEvent( + override val channel: NewsChannelThread, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ThreadUpdateEvent { override fun toString(): String { return "NewsThreadChannelUpdateEvent(channel=$channel, shard=$shard)" @@ -26,7 +35,11 @@ class NewsChannelThreadUpdateEvent(override val channel: NewsChannelThread, over } -class UnknownChannelThreadUpdateEvent(override val channel: ThreadChannel, override val shard: Int) : +class UnknownChannelThreadUpdateEvent( + override val channel: ThreadChannel, + override val shard: Int, + override val coroutineContext: CoroutineContext = channel.kord.coroutineContext, +) : ThreadUpdateEvent { override fun toString(): String { return "UnknownChannelThreadUpdateEvent(channel=$channel, shard=$shard)" diff --git a/core/src/main/kotlin/event/gateway/Events.kt b/core/src/main/kotlin/event/gateway/Events.kt index ee238fc84cde..63e5a66593ff 100644 --- a/core/src/main/kotlin/event/gateway/Events.kt +++ b/core/src/main/kotlin/event/gateway/Events.kt @@ -9,23 +9,31 @@ import dev.kord.core.entity.User import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy -import dev.kord.gateway.Close import dev.kord.gateway.Command import dev.kord.gateway.Gateway import dev.kord.gateway.GatewayCloseCode import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.filter +import kotlin.coroutines.CoroutineContext sealed class GatewayEvent : Event -class ConnectEvent(override val kord: Kord, override val shard: Int) : GatewayEvent() +class ConnectEvent( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, +) : GatewayEvent() sealed class DisconnectEvent : GatewayEvent() { /** * A Gateway was detached, all resources tied to that gateway should be freed. */ - class DetachEvent(override val kord: Kord, override val shard: Int) : DisconnectEvent() { + class DetachEvent( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, + ) : DisconnectEvent() { override fun toString(): String { return "DetachEvent(kord=$kord, shard=$shard)" } @@ -34,7 +42,11 @@ sealed class DisconnectEvent : GatewayEvent() { /** * The user closed the Gateway connection. */ - class UserCloseEvent(override val kord: Kord, override val shard: Int) : DisconnectEvent() { + class UserCloseEvent( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, + ) : DisconnectEvent() { override fun toString(): String { return "UserCloseEvent(kord=$kord, shard=$shard)" } @@ -43,7 +55,11 @@ sealed class DisconnectEvent : GatewayEvent() { /** * The connection was closed because of a timeout, probably due to a loss of internet connection. */ - class TimeoutEvent(override val kord: Kord, override val shard: Int) : DisconnectEvent() { + class TimeoutEvent( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, + ) : DisconnectEvent() { override fun toString(): String { return "TimeoutEvent(kord=$kord, shard=$shard)" } @@ -58,7 +74,8 @@ sealed class DisconnectEvent : GatewayEvent() { override val kord: Kord, override val shard: Int, val closeCode: GatewayCloseCode, - val recoverable: Boolean + val recoverable: Boolean, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : DisconnectEvent() { override fun toString(): String { return "DiscordCloseEvent(kord=$kord, shard=$shard, closeCode=$closeCode, recoverable=$recoverable)" @@ -69,7 +86,11 @@ sealed class DisconnectEvent : GatewayEvent() { * The Gateway has failed to establish a connection too many times and will not try to reconnect anymore. * The user is free to manually connect again using [Gateway.start], otherwise all resources linked to the Gateway should free and the Gateway [detached][Gateway.detach]. */ - class RetryLimitReachedEvent(override val kord: Kord, override val shard: Int) : DisconnectEvent() { + class RetryLimitReachedEvent( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, + ) : DisconnectEvent() { override fun toString(): String { return "RetryLimitReachedEvent(kord=$kord, shard=$shard)" } @@ -78,7 +99,11 @@ sealed class DisconnectEvent : GatewayEvent() { /** * Discord requested a reconnect, the gateway will close and attempt to resume the session. */ - class ReconnectingEvent(override val kord: Kord, override val shard: Int) : DisconnectEvent() { + class ReconnectingEvent( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, + ) : DisconnectEvent() { override fun toString(): String { return "ReconnectingEvent(kord=$kord, shard=$shard)" } @@ -87,7 +112,11 @@ sealed class DisconnectEvent : GatewayEvent() { /** * The gateway closed and will attempt to start a new session. */ - class SessionReset(override val kord: Kord, override val shard: Int) : DisconnectEvent() { + class SessionReset( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, + ) : DisconnectEvent() { override fun toString(): String { return "SessionReset(kord=$kord, shard=$shard)" } @@ -97,7 +126,11 @@ sealed class DisconnectEvent : GatewayEvent() { * Discord is no longer responding to the gateway commands, the connection will be closed and an attempt to resume the session will be made. * Any [commands][Command] send recently might not complete, and won't be automatically requeued. */ - class ZombieConnectionEvent(override val kord: Kord, override val shard: Int) : DisconnectEvent() { + class ZombieConnectionEvent( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, + ) : DisconnectEvent() { override fun toString(): String { return "ZombieConnectionEvent(kord=$kord, shard=$shard)" } @@ -112,7 +145,8 @@ class ReadyEvent( val sessionId: String, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : GatewayEvent(), Strategizable { val guilds: Set get() = guildIds.map { GuildBehavior(it, kord) }.toSet() @@ -127,7 +161,11 @@ class ReadyEvent( } } -class ResumedEvent(override val kord: Kord, override val shard: Int) : GatewayEvent() { +class ResumedEvent( + override val kord: Kord, + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, +) : GatewayEvent() { override fun toString(): String { return "ResumedEvent(kord=$kord, shard=$shard)" } diff --git a/core/src/main/kotlin/event/guild/BanAddEvent.kt b/core/src/main/kotlin/event/guild/BanAddEvent.kt index 6dfe92eea8b6..b9b0b8fba06b 100644 --- a/core/src/main/kotlin/event/guild/BanAddEvent.kt +++ b/core/src/main/kotlin/event/guild/BanAddEvent.kt @@ -12,12 +12,14 @@ import dev.kord.core.event.Event import dev.kord.core.exception.EntityNotFoundException import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class BanAddEvent( val user: User, val guildId: Snowflake, override val shard: Int, - override val supplier: EntitySupplier = user.kord.defaultSupplier + override val supplier: EntitySupplier = user.kord.defaultSupplier, + override val coroutineContext: CoroutineContext = user.kord.coroutineContext, ) : Event, Strategizable { override val kord: Kord get() = user.kord diff --git a/core/src/main/kotlin/event/guild/BanRemoveEvent.kt b/core/src/main/kotlin/event/guild/BanRemoveEvent.kt index d5cbedf300df..8e8f364c330c 100644 --- a/core/src/main/kotlin/event/guild/BanRemoveEvent.kt +++ b/core/src/main/kotlin/event/guild/BanRemoveEvent.kt @@ -9,12 +9,14 @@ import dev.kord.core.entity.User import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class BanRemoveEvent( val user: User, val guildId: Snowflake, override val shard: Int, - override val supplier: EntitySupplier = user.kord.defaultSupplier + override val supplier: EntitySupplier = user.kord.defaultSupplier, + override val coroutineContext: CoroutineContext = user.kord.coroutineContext, ) : Event, Strategizable { override val kord: Kord get() = user.kord diff --git a/core/src/main/kotlin/event/guild/EmojisUpdateEvent.kt b/core/src/main/kotlin/event/guild/EmojisUpdateEvent.kt index 852c5dcab447..cbe23965e8ac 100644 --- a/core/src/main/kotlin/event/guild/EmojisUpdateEvent.kt +++ b/core/src/main/kotlin/event/guild/EmojisUpdateEvent.kt @@ -9,13 +9,15 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class EmojisUpdateEvent( val guildId: Snowflake, val emojis: Set, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val guild: GuildBehavior get() = GuildBehavior(guildId, kord) diff --git a/core/src/main/kotlin/event/guild/GuildCreateEvent.kt b/core/src/main/kotlin/event/guild/GuildCreateEvent.kt index 43cb02728c34..ab98fbca33e1 100644 --- a/core/src/main/kotlin/event/guild/GuildCreateEvent.kt +++ b/core/src/main/kotlin/event/guild/GuildCreateEvent.kt @@ -3,8 +3,13 @@ package dev.kord.core.event.guild import dev.kord.core.Kord import dev.kord.core.entity.Guild import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext -class GuildCreateEvent(val guild: Guild, override val shard: Int) : Event { +class GuildCreateEvent( + val guild: Guild, + override val shard: Int, + override val coroutineContext: CoroutineContext = guild.kord.coroutineContext, +) : Event { override val kord: Kord get() = guild.kord override fun toString(): String { diff --git a/core/src/main/kotlin/event/guild/GuildDeleteEvent.kt b/core/src/main/kotlin/event/guild/GuildDeleteEvent.kt index a5785a0194b3..d5f982defb8e 100644 --- a/core/src/main/kotlin/event/guild/GuildDeleteEvent.kt +++ b/core/src/main/kotlin/event/guild/GuildDeleteEvent.kt @@ -4,13 +4,15 @@ import dev.kord.common.entity.Snowflake import dev.kord.core.Kord import dev.kord.core.entity.Guild import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext class GuildDeleteEvent( val guildId: Snowflake, val unavailable: Boolean, val guild: Guild?, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event { override fun toString(): String { diff --git a/core/src/main/kotlin/event/guild/GuildUpdateEvent.kt b/core/src/main/kotlin/event/guild/GuildUpdateEvent.kt index 844a3261e6df..65d6b61d2d63 100644 --- a/core/src/main/kotlin/event/guild/GuildUpdateEvent.kt +++ b/core/src/main/kotlin/event/guild/GuildUpdateEvent.kt @@ -3,8 +3,13 @@ package dev.kord.core.event.guild import dev.kord.core.Kord import dev.kord.core.entity.Guild import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext -class GuildUpdateEvent(val guild: Guild, override val shard: Int) : Event { +class GuildUpdateEvent( + val guild: Guild, + override val shard: Int, + override val coroutineContext: CoroutineContext = guild.kord.coroutineContext, +) : Event { override val kord: Kord get() = guild.kord override fun toString(): String { return "GuildUpdateEvent(guild=$guild, shard=$shard)" diff --git a/core/src/main/kotlin/event/guild/IntegrationsUpdateEvent.kt b/core/src/main/kotlin/event/guild/IntegrationsUpdateEvent.kt index d10b19d1139e..578d2b7a1d57 100644 --- a/core/src/main/kotlin/event/guild/IntegrationsUpdateEvent.kt +++ b/core/src/main/kotlin/event/guild/IntegrationsUpdateEvent.kt @@ -8,12 +8,14 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class IntegrationsUpdateEvent( val guildId: Snowflake, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val guild: GuildBehavior get() = GuildBehavior(guildId, kord) diff --git a/core/src/main/kotlin/event/guild/InviteCreateEvent.kt b/core/src/main/kotlin/event/guild/InviteCreateEvent.kt index 39a1d24dafb5..6d0e5774cdc1 100644 --- a/core/src/main/kotlin/event/guild/InviteCreateEvent.kt +++ b/core/src/main/kotlin/event/guild/InviteCreateEvent.kt @@ -22,6 +22,7 @@ import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull import kotlinx.datetime.Instant import kotlinx.datetime.toInstant +import kotlin.coroutines.CoroutineContext import kotlin.time.Duration /** @@ -32,6 +33,7 @@ class InviteCreateEvent( override val kord: Kord, override val shard: Int, override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { /** diff --git a/core/src/main/kotlin/event/guild/InviteDeleteEvent.kt b/core/src/main/kotlin/event/guild/InviteDeleteEvent.kt index f5bd327c30ee..09b69fbb6304 100644 --- a/core/src/main/kotlin/event/guild/InviteDeleteEvent.kt +++ b/core/src/main/kotlin/event/guild/InviteDeleteEvent.kt @@ -3,7 +3,6 @@ package dev.kord.core.event.guild import dev.kord.common.entity.Snowflake import dev.kord.core.Kord import dev.kord.core.behavior.GuildBehavior -import dev.kord.core.behavior.channel.GuildChannelBehavior import dev.kord.core.behavior.channel.TopGuildChannelBehavior import dev.kord.core.cache.data.InviteDeleteData import dev.kord.core.entity.Guild @@ -14,6 +13,7 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull +import kotlin.coroutines.CoroutineContext /** * Sent when an invite is deleted. @@ -22,7 +22,8 @@ class InviteDeleteEvent( val data: InviteDeleteData, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { /** diff --git a/core/src/main/kotlin/event/guild/MemberJoinEvent.kt b/core/src/main/kotlin/event/guild/MemberJoinEvent.kt index ea10369d2856..f18d10db136b 100644 --- a/core/src/main/kotlin/event/guild/MemberJoinEvent.kt +++ b/core/src/main/kotlin/event/guild/MemberJoinEvent.kt @@ -9,11 +9,13 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class MemberJoinEvent( val member: Member, override val shard: Int, - override val supplier: EntitySupplier = member.kord.defaultSupplier + override val supplier: EntitySupplier = member.kord.defaultSupplier, + override val coroutineContext: CoroutineContext = member.kord.coroutineContext, ) : Event, Strategizable { override val kord: Kord get() = member.kord diff --git a/core/src/main/kotlin/event/guild/MemberLeaveEvent.kt b/core/src/main/kotlin/event/guild/MemberLeaveEvent.kt index 1cd6c2d24fea..bbe9594714d6 100644 --- a/core/src/main/kotlin/event/guild/MemberLeaveEvent.kt +++ b/core/src/main/kotlin/event/guild/MemberLeaveEvent.kt @@ -6,8 +6,14 @@ import dev.kord.core.behavior.GuildBehavior import dev.kord.core.entity.Guild import dev.kord.core.entity.User import dev.kord.core.event.Event - -class MemberLeaveEvent(val user: User, val guildId: Snowflake, override val shard: Int) : Event { +import kotlin.coroutines.CoroutineContext + +class MemberLeaveEvent( + val user: User, + val guildId: Snowflake, + override val shard: Int, + override val coroutineContext: CoroutineContext = user.kord.coroutineContext, +) : Event { override val kord: Kord get() = user.kord diff --git a/core/src/main/kotlin/event/guild/MemberUpdateEvent.kt b/core/src/main/kotlin/event/guild/MemberUpdateEvent.kt index c42ce7a0811f..a9f9254df35c 100644 --- a/core/src/main/kotlin/event/guild/MemberUpdateEvent.kt +++ b/core/src/main/kotlin/event/guild/MemberUpdateEvent.kt @@ -10,6 +10,7 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import kotlinx.coroutines.flow.Flow import kotlinx.datetime.Instant +import kotlin.coroutines.CoroutineContext private const val deprecationMessage = "The full member is now available in this Event." @@ -19,6 +20,7 @@ class MemberUpdateEvent( override val kord: Kord, override val shard: Int, override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val guildId: Snowflake get() = member.guildId diff --git a/core/src/main/kotlin/event/guild/MembersChunkEvent.kt b/core/src/main/kotlin/event/guild/MembersChunkEvent.kt index a87c6e68d7ac..8d465e247d3a 100644 --- a/core/src/main/kotlin/event/guild/MembersChunkEvent.kt +++ b/core/src/main/kotlin/event/guild/MembersChunkEvent.kt @@ -2,13 +2,10 @@ package dev.kord.core.event.guild import dev.kord.common.annotation.DeprecatedSinceKord import dev.kord.common.entity.Snowflake -import dev.kord.common.entity.optional.Optional import dev.kord.common.entity.optional.orEmpty import dev.kord.core.Kord import dev.kord.core.behavior.GuildBehavior -import dev.kord.core.cache.data.MemberData import dev.kord.core.cache.data.MembersChunkData -import dev.kord.core.cache.data.PresenceData import dev.kord.core.entity.Guild import dev.kord.core.entity.Member import dev.kord.core.entity.Presence @@ -16,6 +13,7 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext @DeprecatedSinceKord("0.7.0") @@ -26,7 +24,8 @@ class MembersChunkEvent( val data: MembersChunkData, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val guildId: Snowflake get() = data.guildId diff --git a/core/src/main/kotlin/event/guild/VoiceServerUpdateEvent.kt b/core/src/main/kotlin/event/guild/VoiceServerUpdateEvent.kt index 8741dcda336b..f7b566a0ba23 100644 --- a/core/src/main/kotlin/event/guild/VoiceServerUpdateEvent.kt +++ b/core/src/main/kotlin/event/guild/VoiceServerUpdateEvent.kt @@ -8,6 +8,7 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class VoiceServerUpdateEvent( val token: String, @@ -15,7 +16,8 @@ class VoiceServerUpdateEvent( val endpoint: String?, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val guild: GuildBehavior get() = GuildBehavior(guildId, kord) diff --git a/core/src/main/kotlin/event/guild/WebhookUpdateEvent.kt b/core/src/main/kotlin/event/guild/WebhookUpdateEvent.kt index 634d925ec282..f3433620dd91 100644 --- a/core/src/main/kotlin/event/guild/WebhookUpdateEvent.kt +++ b/core/src/main/kotlin/event/guild/WebhookUpdateEvent.kt @@ -13,13 +13,15 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull +import kotlin.coroutines.CoroutineContext class WebhookUpdateEvent( val guildId: Snowflake, val channelId: Snowflake, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val channel: TopGuildMessageChannelBehavior get() = TopGuildMessageChannelBehavior(guildId, channelId, kord) diff --git a/core/src/main/kotlin/event/interaction/ApplicationCommandCreate.kt b/core/src/main/kotlin/event/interaction/ApplicationCommandCreate.kt index b1fdc19fc722..d7bddbae5e0e 100644 --- a/core/src/main/kotlin/event/interaction/ApplicationCommandCreate.kt +++ b/core/src/main/kotlin/event/interaction/ApplicationCommandCreate.kt @@ -1,9 +1,9 @@ package dev.kord.core.event.interaction -import dev.kord.common.annotation.KordPreview import dev.kord.core.Kord import dev.kord.core.entity.application.* import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext sealed interface ApplicationCommandCreateEvent : Event { @@ -14,6 +14,7 @@ class ChatInputCommandCreateEvent( override val command: GuildChatInputCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandCreateEvent @@ -21,6 +22,7 @@ class UserCommandCreateEvent( override val command: GuildUserCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandCreateEvent @@ -28,6 +30,7 @@ class MessageCommandCreateEvent( override val command: GuildMessageCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandCreateEvent @@ -35,4 +38,5 @@ class UnknownApplicationCommandCreateEvent( override val command: UnknownGuildApplicationCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandCreateEvent \ No newline at end of file diff --git a/core/src/main/kotlin/event/interaction/ApplicationCommandDelete.kt b/core/src/main/kotlin/event/interaction/ApplicationCommandDelete.kt index f76957994ab5..aba66f3debf5 100644 --- a/core/src/main/kotlin/event/interaction/ApplicationCommandDelete.kt +++ b/core/src/main/kotlin/event/interaction/ApplicationCommandDelete.kt @@ -1,9 +1,9 @@ package dev.kord.core.event.interaction -import dev.kord.common.annotation.KordPreview import dev.kord.core.Kord import dev.kord.core.entity.application.* import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext sealed interface ApplicationCommandDeleteEvent : Event { @@ -14,6 +14,7 @@ class ChatInputCommandDeleteEvent( override val command: GuildChatInputCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandDeleteEvent @@ -21,6 +22,7 @@ class UserCommandDeleteEvent( override val command: GuildUserCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandDeleteEvent @@ -28,6 +30,7 @@ class MessageCommandDeleteEvent( override val command: GuildMessageCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandDeleteEvent @@ -35,4 +38,5 @@ class UnknownApplicationCommandDeleteEvent( override val command: UnknownGuildApplicationCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandDeleteEvent diff --git a/core/src/main/kotlin/event/interaction/ApplicationCommandUpdate.kt b/core/src/main/kotlin/event/interaction/ApplicationCommandUpdate.kt index 5369df6d22b8..62f5d20226d8 100644 --- a/core/src/main/kotlin/event/interaction/ApplicationCommandUpdate.kt +++ b/core/src/main/kotlin/event/interaction/ApplicationCommandUpdate.kt @@ -1,9 +1,9 @@ package dev.kord.core.event.interaction -import dev.kord.common.annotation.KordPreview import dev.kord.core.Kord import dev.kord.core.entity.application.* import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext sealed interface ApplicationCommandUpdateEvent : Event { @@ -14,6 +14,7 @@ class ChatInputCommandUpdateEvent( override val command: GuildChatInputCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandUpdateEvent @@ -21,6 +22,7 @@ class UserCommandUpdateEvent( override val command: GuildUserCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandUpdateEvent @@ -28,11 +30,13 @@ class MessageCommandUpdateEvent( override val command: GuildMessageCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandUpdateEvent class UnknownApplicationCommandUpdateEvent( override val command: UnknownGuildApplicationCommand, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ApplicationCommandUpdateEvent diff --git a/core/src/main/kotlin/event/interaction/ApplicationCreate.kt b/core/src/main/kotlin/event/interaction/ApplicationCreate.kt index be05dd782d26..e3881ddba210 100644 --- a/core/src/main/kotlin/event/interaction/ApplicationCreate.kt +++ b/core/src/main/kotlin/event/interaction/ApplicationCreate.kt @@ -4,7 +4,7 @@ import dev.kord.core.Kord import dev.kord.core.behavior.interaction.* import dev.kord.core.entity.application.* import dev.kord.core.entity.interaction.* -import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext /** * This event fires when an interaction is created. @@ -51,13 +51,15 @@ sealed interface UserCommandInteractionCreateEvent : ApplicationInteractionCrea class GuildUserCommandInteractionCreateEvent( override val interaction: GuildUserCommandInteraction, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : GuildApplicationInteractionCreateEvent, UserCommandInteractionCreateEvent class GlobalUserCommandInteractionCreateEvent( override val interaction: GlobalUserCommandInteraction, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : GlobalApplicationInteractionCreateEvent, UserCommandInteractionCreateEvent @@ -68,13 +70,15 @@ sealed interface MessageCommandInteractionCreateEvent : ApplicationInteractionC class GuildMessageCommandInteractionCreateEvent( override val interaction: GuildMessageCommandInteraction, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : GuildApplicationInteractionCreateEvent, MessageCommandInteractionCreateEvent class GlobalMessageCommandInteractionCreateEvent( override val interaction: GlobalMessageCommandInteraction, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : GlobalApplicationInteractionCreateEvent, MessageCommandInteractionCreateEvent @@ -86,11 +90,13 @@ sealed interface ChatInputCommandInteractionCreateEvent : ApplicationInteractio class GuildChatInputCommandInteractionCreateEvent( override val interaction: GuildChatInputCommandInteraction, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : GuildApplicationInteractionCreateEvent, ChatInputCommandInteractionCreateEvent class GlobalChatInputCommandInteractionCreateEvent( override val interaction: GlobalChatInputCommandInteraction, override val kord: Kord, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : GlobalApplicationInteractionCreateEvent, ChatInputCommandInteractionCreateEvent diff --git a/core/src/main/kotlin/event/interaction/ComponentCreate.kt b/core/src/main/kotlin/event/interaction/ComponentCreate.kt index 80ba4bc8a8b2..fd0f9386b874 100644 --- a/core/src/main/kotlin/event/interaction/ComponentCreate.kt +++ b/core/src/main/kotlin/event/interaction/ComponentCreate.kt @@ -4,6 +4,7 @@ import dev.kord.core.Kord import dev.kord.core.entity.interaction.ButtonInteraction import dev.kord.core.entity.interaction.ComponentInteraction import dev.kord.core.entity.interaction.SelectMenuInteraction +import kotlin.coroutines.CoroutineContext sealed interface ComponentInteractionCreateEvent : InteractionCreateEvent { @@ -15,6 +16,7 @@ class ButtonInteractionCreateEvent( override val interaction: ButtonInteraction, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ComponentInteractionCreateEvent @@ -22,4 +24,5 @@ class SelectMenuInteractionCreateEvent( override val interaction: SelectMenuInteraction, override val kord: Kord, override val shard: Int, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : ComponentInteractionCreateEvent \ No newline at end of file diff --git a/core/src/main/kotlin/event/message/MessageBulkDeleteEvent.kt b/core/src/main/kotlin/event/message/MessageBulkDeleteEvent.kt index 26ce489fcd4c..5d29afa06ab8 100644 --- a/core/src/main/kotlin/event/message/MessageBulkDeleteEvent.kt +++ b/core/src/main/kotlin/event/message/MessageBulkDeleteEvent.kt @@ -13,6 +13,7 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull +import kotlin.coroutines.CoroutineContext class MessageBulkDeleteEvent( val messageIds: Set, @@ -21,7 +22,8 @@ class MessageBulkDeleteEvent( val guildId: Snowflake?, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val channel: MessageChannelBehavior get() = MessageChannelBehavior(channelId, kord) diff --git a/core/src/main/kotlin/event/message/MessageCreateEvent.kt b/core/src/main/kotlin/event/message/MessageCreateEvent.kt index 3699322aa9ff..e7bdec7b6e99 100644 --- a/core/src/main/kotlin/event/message/MessageCreateEvent.kt +++ b/core/src/main/kotlin/event/message/MessageCreateEvent.kt @@ -11,13 +11,15 @@ import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.entity.channel.DmChannel +import kotlin.coroutines.CoroutineContext class MessageCreateEvent( val message: Message, val guildId: Snowflake?, val member: Member?, override val shard: Int, - override val supplier: EntitySupplier = message.kord.defaultSupplier + override val supplier: EntitySupplier = message.kord.defaultSupplier, + override val coroutineContext: CoroutineContext = message.kord.coroutineContext, ) : Event, Strategizable { override val kord: Kord get() = message.kord diff --git a/core/src/main/kotlin/event/message/MessageDeleteEvent.kt b/core/src/main/kotlin/event/message/MessageDeleteEvent.kt index 8fb89c956f10..b69578ba3f4d 100644 --- a/core/src/main/kotlin/event/message/MessageDeleteEvent.kt +++ b/core/src/main/kotlin/event/message/MessageDeleteEvent.kt @@ -13,6 +13,7 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull +import kotlin.coroutines.CoroutineContext class MessageDeleteEvent( val messageId: Snowflake, @@ -22,6 +23,7 @@ class MessageDeleteEvent( override val kord: Kord, override val shard: Int, override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val channel: MessageChannelBehavior get() = MessageChannelBehavior(channelId, kord) diff --git a/core/src/main/kotlin/event/message/MessageUpdateEvent.kt b/core/src/main/kotlin/event/message/MessageUpdateEvent.kt index 21232036c38d..1a4d9cb7153e 100644 --- a/core/src/main/kotlin/event/message/MessageUpdateEvent.kt +++ b/core/src/main/kotlin/event/message/MessageUpdateEvent.kt @@ -10,6 +10,7 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class MessageUpdateEvent( val messageId: Snowflake, @@ -18,7 +19,8 @@ class MessageUpdateEvent( val old: Message?, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { /** diff --git a/core/src/main/kotlin/event/message/ReactionAddEvent.kt b/core/src/main/kotlin/event/message/ReactionAddEvent.kt index 33fd0b1fc458..a106a3f24170 100644 --- a/core/src/main/kotlin/event/message/ReactionAddEvent.kt +++ b/core/src/main/kotlin/event/message/ReactionAddEvent.kt @@ -14,6 +14,7 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull +import kotlin.coroutines.CoroutineContext class ReactionAddEvent( val userId: Snowflake, @@ -23,7 +24,8 @@ class ReactionAddEvent( val emoji: ReactionEmoji, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val channel: MessageChannelBehavior get() = MessageChannelBehavior(channelId, kord) diff --git a/core/src/main/kotlin/event/message/ReactionRemoveAllEvent.kt b/core/src/main/kotlin/event/message/ReactionRemoveAllEvent.kt index 8c5c072cb6e7..1b1a904e80ea 100644 --- a/core/src/main/kotlin/event/message/ReactionRemoveAllEvent.kt +++ b/core/src/main/kotlin/event/message/ReactionRemoveAllEvent.kt @@ -14,6 +14,7 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull +import kotlin.coroutines.CoroutineContext class ReactionRemoveAllEvent( val channelId: Snowflake, @@ -21,7 +22,8 @@ class ReactionRemoveAllEvent( val guildId: Snowflake?, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val channel: MessageChannelBehavior get() = MessageChannelBehavior(channelId, kord) diff --git a/core/src/main/kotlin/event/message/ReactionRemoveEmojiEvent.kt b/core/src/main/kotlin/event/message/ReactionRemoveEmojiEvent.kt index 3a86b933a4d1..8c8c16e5c5f5 100644 --- a/core/src/main/kotlin/event/message/ReactionRemoveEmojiEvent.kt +++ b/core/src/main/kotlin/event/message/ReactionRemoveEmojiEvent.kt @@ -17,12 +17,14 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull +import kotlin.coroutines.CoroutineContext class ReactionRemoveEmojiEvent( val data: ReactionRemoveEmojiData, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { /** diff --git a/core/src/main/kotlin/event/message/ReactionRemoveEvent.kt b/core/src/main/kotlin/event/message/ReactionRemoveEvent.kt index da10b2ee74af..2ab0490274ff 100644 --- a/core/src/main/kotlin/event/message/ReactionRemoveEvent.kt +++ b/core/src/main/kotlin/event/message/ReactionRemoveEvent.kt @@ -14,6 +14,7 @@ import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull +import kotlin.coroutines.CoroutineContext class ReactionRemoveEvent( val userId: Snowflake, @@ -23,7 +24,8 @@ class ReactionRemoveEvent( val emoji: ReactionEmoji, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val channel: MessageChannelBehavior get() = MessageChannelBehavior(channelId, kord) diff --git a/core/src/main/kotlin/event/role/RoleCreateEvent.kt b/core/src/main/kotlin/event/role/RoleCreateEvent.kt index d6a7f17ee7a3..6ca9bd34a85d 100644 --- a/core/src/main/kotlin/event/role/RoleCreateEvent.kt +++ b/core/src/main/kotlin/event/role/RoleCreateEvent.kt @@ -9,11 +9,13 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class RoleCreateEvent( val role: Role, override val shard: Int, override val supplier: EntitySupplier = role.kord.defaultSupplier, + override val coroutineContext: CoroutineContext = role.kord.coroutineContext, ) : Event, Strategizable { override val kord: Kord get() = role.kord diff --git a/core/src/main/kotlin/event/role/RoleDeleteEvent.kt b/core/src/main/kotlin/event/role/RoleDeleteEvent.kt index 2484772f95c1..9e8a34c15f12 100644 --- a/core/src/main/kotlin/event/role/RoleDeleteEvent.kt +++ b/core/src/main/kotlin/event/role/RoleDeleteEvent.kt @@ -9,6 +9,7 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class RoleDeleteEvent( val guildId: Snowflake, @@ -16,7 +17,8 @@ class RoleDeleteEvent( val role: Role?, override val kord: Kord, override val shard: Int, - override val supplier: EntitySupplier = kord.defaultSupplier + override val supplier: EntitySupplier = kord.defaultSupplier, + override val coroutineContext: CoroutineContext = kord.coroutineContext, ) : Event, Strategizable { val guild: GuildBehavior get() = GuildBehavior(guildId, kord) diff --git a/core/src/main/kotlin/event/role/RoleUpdateEvent.kt b/core/src/main/kotlin/event/role/RoleUpdateEvent.kt index a7c1ad4c7311..908713ffe567 100644 --- a/core/src/main/kotlin/event/role/RoleUpdateEvent.kt +++ b/core/src/main/kotlin/event/role/RoleUpdateEvent.kt @@ -9,11 +9,13 @@ import dev.kord.core.entity.Strategizable import dev.kord.core.event.Event import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class RoleUpdateEvent( val role: Role, override val shard: Int, - override val supplier: EntitySupplier = role.kord.defaultSupplier + override val supplier: EntitySupplier = role.kord.defaultSupplier, + override val coroutineContext: CoroutineContext = role.kord.coroutineContext, ) : Event, Strategizable { override val kord: Kord get() = role.kord diff --git a/core/src/main/kotlin/event/user/PresenceUpdateEvent.kt b/core/src/main/kotlin/event/user/PresenceUpdateEvent.kt index bff7a579b0e2..a301a4338945 100644 --- a/core/src/main/kotlin/event/user/PresenceUpdateEvent.kt +++ b/core/src/main/kotlin/event/user/PresenceUpdateEvent.kt @@ -11,6 +11,7 @@ import dev.kord.core.event.Event import dev.kord.core.exception.EntityNotFoundException import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy +import kotlin.coroutines.CoroutineContext class PresenceUpdateEvent( val oldUser: User?, @@ -19,7 +20,8 @@ class PresenceUpdateEvent( val old: Presence?, val presence: Presence, override val shard: Int, - override val supplier: EntitySupplier = presence.kord.defaultSupplier + override val supplier: EntitySupplier = presence.kord.defaultSupplier, + override val coroutineContext: CoroutineContext = presence.kord.coroutineContext, ) : Event, Strategizable { override val kord: Kord get() = presence.kord diff --git a/core/src/main/kotlin/event/user/UserUpdateEvent.kt b/core/src/main/kotlin/event/user/UserUpdateEvent.kt index 674428b2dda6..38ff0487af70 100644 --- a/core/src/main/kotlin/event/user/UserUpdateEvent.kt +++ b/core/src/main/kotlin/event/user/UserUpdateEvent.kt @@ -3,11 +3,13 @@ package dev.kord.core.event.user import dev.kord.core.Kord import dev.kord.core.entity.User import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext class UserUpdateEvent( val old: User?, val user: User, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = user.kord.coroutineContext, ) : Event { override val kord: Kord get() = user.kord diff --git a/core/src/main/kotlin/event/user/VoiceStateUpdateEvent.kt b/core/src/main/kotlin/event/user/VoiceStateUpdateEvent.kt index 42b9a582519f..d2cb01108286 100644 --- a/core/src/main/kotlin/event/user/VoiceStateUpdateEvent.kt +++ b/core/src/main/kotlin/event/user/VoiceStateUpdateEvent.kt @@ -3,11 +3,13 @@ package dev.kord.core.event.user import dev.kord.core.Kord import dev.kord.core.entity.VoiceState import dev.kord.core.event.Event +import kotlin.coroutines.CoroutineContext class VoiceStateUpdateEvent( val old: VoiceState?, val state: VoiceState, - override val shard: Int + override val shard: Int, + override val coroutineContext: CoroutineContext = state.kord.coroutineContext, ) : Event { override val kord: Kord get() = state.kord From f2467bf633d77e24bbdde1f4fd508c3b352845a1 Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Thu, 23 Sep 2021 15:18:20 +0200 Subject: [PATCH 10/13] Event interceptor changes --- core/src/main/kotlin/Kord.kt | 13 +- core/src/main/kotlin/gateway/MasterGateway.kt | 2 +- .../handler/BaseGatewayEventHandler.kt | 11 +- .../gateway/handler/ChannelEventHandler.kt | 62 +++--- .../handler/DefaultGatewayEventInterceptor.kt | 53 ++--- .../handler/GatewayEventInterceptor.kt | 16 +- .../gateway/handler/GuildEventHandler.kt | 183 ++++++++-------- .../handler/InteractionEventHandler.kt | 53 +++-- .../gateway/handler/LifeCycleEventHandler.kt | 51 ++--- .../gateway/handler/MessageEventHandler.kt | 207 +++++++++--------- .../gateway/handler/ThreadEventHandler.kt | 63 +++--- .../gateway/handler/UserEventHandler.kt | 21 +- .../gateway/handler/VoiceEventHandler.kt | 31 ++- .../gateway/handler/WebhookEventHandler.kt | 22 +- 14 files changed, 366 insertions(+), 422 deletions(-) diff --git a/core/src/main/kotlin/Kord.kt b/core/src/main/kotlin/Kord.kt index 4a4e30d47717..8e601fde3e86 100644 --- a/core/src/main/kotlin/Kord.kt +++ b/core/src/main/kotlin/Kord.kt @@ -54,17 +54,12 @@ class Kord( val selfId: Snowflake, private val eventFlow: MutableSharedFlow, dispatcher: CoroutineDispatcher, - interceptorBuilder: Kord.() -> GatewayEventInterceptor = { - DefaultGatewayEventInterceptor( - this, - gateway, - cache, - eventFlow - ) + interceptorBuilder: () -> GatewayEventInterceptor = { + DefaultGatewayEventInterceptor(cache) } ) : CoroutineScope { - private val interceptor = interceptorBuilder.invoke(this) + private val interceptor = interceptorBuilder.invoke() /** * Global commands made by the bot under this Kord instance. @@ -114,7 +109,7 @@ class Kord( get() = defaultSupplier.guilds init { - launch { interceptor.start() } + launch { interceptor.start(gateway.events, eventFlow, this@Kord) } } /** diff --git a/core/src/main/kotlin/gateway/MasterGateway.kt b/core/src/main/kotlin/gateway/MasterGateway.kt index a20ca4e636de..5c8b76d13dff 100644 --- a/core/src/main/kotlin/gateway/MasterGateway.kt +++ b/core/src/main/kotlin/gateway/MasterGateway.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import kotlin.time.Duration -data class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) +open class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) interface MasterGateway { val gateways: Map diff --git a/core/src/main/kotlin/gateway/handler/BaseGatewayEventHandler.kt b/core/src/main/kotlin/gateway/handler/BaseGatewayEventHandler.kt index 654fb8cd6a1a..f0618adf4640 100644 --- a/core/src/main/kotlin/gateway/handler/BaseGatewayEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/BaseGatewayEventHandler.kt @@ -2,20 +2,13 @@ package dev.kord.core.gateway.handler import dev.kord.cache.api.DataCache import dev.kord.core.Kord -import dev.kord.core.gateway.MasterGateway -import dev.kord.gateway.Gateway -import kotlinx.coroutines.channels.SendChannel -import kotlinx.coroutines.flow.MutableSharedFlow import dev.kord.core.event.Event as CoreEvent import dev.kord.gateway.Event as GatewayEvent abstract class BaseGatewayEventHandler( - protected val kord: Kord, - protected val gateway: MasterGateway, - protected val cache: DataCache, - protected val coreFlow: MutableSharedFlow + protected val cache: DataCache ) { - abstract suspend fun handle(event: GatewayEvent, shard: Int) + abstract suspend fun handle(event: GatewayEvent, shard: Int, kord: Kord): CoreEvent? } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt b/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt index 2a0b1a475e2f..b57bea8f9fb1 100644 --- a/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt @@ -13,29 +13,24 @@ import dev.kord.core.entity.channel.thread.ThreadChannel import dev.kord.core.event.channel.* import dev.kord.core.event.channel.data.ChannelPinsUpdateEventData import dev.kord.core.event.channel.data.TypingStartEventData -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.* -import kotlinx.coroutines.flow.MutableSharedFlow import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") internal class ChannelEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { - - override suspend fun handle(event: Event, shard: Int) = when (event) { - is ChannelCreate -> handle(event, shard) - is ChannelUpdate -> handle(event, shard) - is ChannelDelete -> handle(event, shard) - is ChannelPinsUpdate -> handle(event, shard) - is TypingStart -> handle(event, shard) - else -> Unit + cache: DataCache +) : BaseGatewayEventHandler(cache) { + + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is ChannelCreate -> handle(event, shard, kord) + is ChannelUpdate -> handle(event, shard, kord) + is ChannelDelete -> handle(event, shard, kord) + is ChannelPinsUpdate -> handle(event, shard, kord) + is TypingStart -> handle(event, shard, kord) + else -> null } - private suspend fun handle(event: ChannelCreate, shard: Int) { + private suspend fun handle(event: ChannelCreate, shard: Int, kord: Kord): CoreEvent? { val data = ChannelData.from(event.channel) cache.put(data) @@ -47,15 +42,15 @@ internal class ChannelEventHandler( is StageChannel -> StageChannelCreateEvent(channel, shard) is VoiceChannel -> VoiceChannelCreateEvent(channel, shard) is Category -> CategoryCreateEvent(channel, shard) - is ThreadChannel -> return + is ThreadChannel -> return null else -> UnknownChannelCreateEvent(channel, shard) } - coreFlow.emit(coreEvent) + return coreEvent } - private suspend fun handle(event: ChannelUpdate, shard: Int) { + private suspend fun handle(event: ChannelUpdate, shard: Int, kord: Kord): CoreEvent? { val data = ChannelData.from(event.channel) cache.put(data) @@ -67,15 +62,15 @@ internal class ChannelEventHandler( is StageChannel -> StageChannelUpdateEvent(channel, shard) is VoiceChannel -> VoiceChannelUpdateEvent(channel, shard) is Category -> CategoryUpdateEvent(channel, shard) - is ThreadChannel -> return + is ThreadChannel -> return null else -> UnknownChannelUpdateEvent(channel, shard) } - coreFlow.emit(coreEvent) + return coreEvent } - private suspend fun handle(event: ChannelDelete, shard: Int) { + private suspend fun handle(event: ChannelDelete, shard: Int, kord: Kord): CoreEvent? { cache.remove { idEq(ChannelData::id, event.channel.id) } val data = ChannelData.from(event.channel) @@ -87,24 +82,25 @@ internal class ChannelEventHandler( is StageChannel -> StageChannelDeleteEvent(channel, shard) is VoiceChannel -> VoiceChannelDeleteEvent(channel, shard) is Category -> CategoryDeleteEvent(channel, shard) - is ThreadChannel -> return + is ThreadChannel -> return null else -> UnknownChannelDeleteEvent(channel, shard) } - coreFlow.emit(coreEvent) + return coreEvent } - private suspend fun handle(event: ChannelPinsUpdate, shard: Int) = with(event.pins) { - val coreEvent = ChannelPinsUpdateEvent(ChannelPinsUpdateEventData.from(this), kord, shard) + private suspend fun handle(event: ChannelPinsUpdate, shard: Int, kord: Kord): ChannelPinsUpdateEvent = + with(event.pins) { + val coreEvent = ChannelPinsUpdateEvent(ChannelPinsUpdateEventData.from(this), kord, shard) - cache.query { idEq(ChannelData::id, channelId) }.update { - it.copy(lastPinTimestamp = lastPinTimestamp) - } + cache.query { idEq(ChannelData::id, channelId) }.update { + it.copy(lastPinTimestamp = lastPinTimestamp) + } - coreFlow.emit(coreEvent) - } + return coreEvent + } - private suspend fun handle(event: TypingStart, shard: Int) = with(event.data) { + private suspend fun handle(event: TypingStart, shard: Int, kord: Kord): TypingStartEvent = with(event.data) { member.value?.let { cache.put(MemberData.from(userId = it.user.value!!.id, guildId = guildId.value!!, it)) } @@ -115,7 +111,7 @@ internal class ChannelEventHandler( shard ) - coreFlow.emit(coreEvent) + return coreEvent } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt b/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt index 8273e6f641a2..84ffd7db9e3f 100644 --- a/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt +++ b/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt @@ -2,15 +2,8 @@ package dev.kord.core.gateway.handler import dev.kord.cache.api.DataCache import dev.kord.core.Kord -import dev.kord.core.gateway.MasterGateway -import dev.kord.gateway.Event +import dev.kord.core.gateway.ShardEvent import io.ktor.util.* -import kotlinx.coroutines.Job -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.buffer -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach import mu.KotlinLogging import dev.kord.core.event.Event as CoreEvent @@ -18,35 +11,33 @@ private val logger = KotlinLogging.logger { } @Suppress("EXPERIMENTAL_API_USAGE") class DefaultGatewayEventInterceptor( - private val kord: Kord, - private val gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow, -): GatewayEventInterceptor { + cache: DataCache +) : GatewayEventInterceptor() { private val listeners = listOf( - MessageEventHandler(kord, gateway, cache, coreFlow), - ChannelEventHandler(kord, gateway, cache, coreFlow), - ThreadEventHandler(kord, gateway, cache, coreFlow), - GuildEventHandler(kord, gateway, cache, coreFlow), - LifeCycleEventHandler(kord, gateway, cache, coreFlow), - UserEventHandler(kord, gateway, cache, coreFlow), - VoiceEventHandler(kord, gateway, cache, coreFlow), - WebhookEventHandler(kord, gateway, cache, coreFlow), - InteractionEventHandler(kord, gateway, cache, coreFlow) + MessageEventHandler(cache), + ChannelEventHandler(cache), + ThreadEventHandler(cache), + GuildEventHandler(cache), + LifeCycleEventHandler(cache), + UserEventHandler(cache), + VoiceEventHandler(cache), + WebhookEventHandler(cache), + InteractionEventHandler(cache) ) - override suspend fun start(): Job = gateway.events - .buffer(Channel.UNLIMITED) - .onEach { (event, _, shard) -> dispatch(event, shard) } - .launchIn(kord) - - private suspend fun dispatch(event: Event, shard: Int) { - runCatching { - listeners.forEach { it.handle(event, shard) } + override suspend fun handle(event: ShardEvent, kord: Kord): CoreEvent? { + return runCatching { + for (listener in listeners) { + val coreEvent = listener.handle(event.event, event.shard, kord) + if (coreEvent != null) { + return coreEvent + } + } + return null }.onFailure { logger.error(it) - } + }.getOrNull() } } diff --git a/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt b/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt index de3f724ac7cb..cc1dcb71d89a 100644 --- a/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt +++ b/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt @@ -1,9 +1,21 @@ package dev.kord.core.gateway.handler +import dev.kord.core.Kord +import dev.kord.core.gateway.ShardEvent import kotlinx.coroutines.Job +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.* +import dev.kord.core.event.Event as CoreEvent -interface GatewayEventInterceptor { +abstract class GatewayEventInterceptor { - suspend fun start(): Job + suspend fun start(events: Flow, coreEvents: MutableSharedFlow, kord: Kord): Job = events + .buffer(Channel.UNLIMITED) + .onEach { event -> + val coreEvent = handle(event, kord) + coreEvent?.let { coreEvents.emit(it) } + } + .launchIn(kord) + abstract suspend fun handle(event: ShardEvent, kord: Kord): CoreEvent? } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/GuildEventHandler.kt b/core/src/main/kotlin/gateway/handler/GuildEventHandler.kt index 8b64ce64f632..d98e4b1f04dc 100644 --- a/core/src/main/kotlin/gateway/handler/GuildEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/GuildEventHandler.kt @@ -4,7 +4,6 @@ import dev.kord.cache.api.DataCache import dev.kord.cache.api.put import dev.kord.cache.api.putAll import dev.kord.cache.api.query -import dev.kord.common.entity.Snowflake import dev.kord.common.entity.optional.optionalSnowflake import dev.kord.common.entity.optional.orEmpty import dev.kord.core.Kord @@ -16,7 +15,6 @@ import dev.kord.core.event.role.RoleCreateEvent import dev.kord.core.event.role.RoleDeleteEvent import dev.kord.core.event.role.RoleUpdateEvent import dev.kord.core.event.user.PresenceUpdateEvent -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.* import kotlinx.coroutines.flow.* import dev.kord.common.entity.DiscordGuild as GatewayGuild @@ -24,31 +22,28 @@ import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") internal class GuildEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { - - override suspend fun handle(event: Event, shard: Int) = when (event) { - is GuildCreate -> handle(event, shard) - is GuildUpdate -> handle(event, shard) - is GuildDelete -> handle(event, shard) - is GuildBanAdd -> handle(event, shard) - is GuildBanRemove -> handle(event, shard) - is GuildEmojisUpdate -> handle(event, shard) - is GuildIntegrationsUpdate -> handle(event, shard) - is GuildMemberAdd -> handle(event, shard) - is GuildMemberRemove -> handle(event, shard) - is GuildMemberUpdate -> handle(event, shard) - is GuildRoleCreate -> handle(event, shard) - is GuildRoleUpdate -> handle(event, shard) - is GuildRoleDelete -> handle(event, shard) - is GuildMembersChunk -> handle(event, shard) - is PresenceUpdate -> handle(event, shard) - is InviteCreate -> handle(event, shard) - is InviteDelete -> handle(event, shard) - else -> Unit + cache: DataCache +) : BaseGatewayEventHandler(cache) { + + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is GuildCreate -> handle(event, shard, kord) + is GuildUpdate -> handle(event, shard, kord) + is GuildDelete -> handle(event, shard, kord) + is GuildBanAdd -> handle(event, shard, kord) + is GuildBanRemove -> handle(event, shard, kord) + is GuildEmojisUpdate -> handle(event, shard, kord) + is GuildIntegrationsUpdate -> handle(event, shard, kord) + is GuildMemberAdd -> handle(event, shard, kord) + is GuildMemberRemove -> handle(event, shard, kord) + is GuildMemberUpdate -> handle(event, shard, kord) + is GuildRoleCreate -> handle(event, shard, kord) + is GuildRoleUpdate -> handle(event, shard, kord) + is GuildRoleDelete -> handle(event, shard, kord) + is GuildMembersChunk -> handle(event, shard, kord) + is PresenceUpdate -> handle(event, shard, kord) + is InviteCreate -> handle(event, shard, kord) + is InviteDelete -> handle(event, shard, kord) + else -> null } private suspend fun GatewayGuild.cache() { @@ -77,66 +72,67 @@ internal class GuildEventHandler( } } - private suspend fun handle(event: GuildCreate, shard: Int) { + private suspend fun handle(event: GuildCreate, shard: Int, kord: Kord): GuildCreateEvent { val data = GuildData.from(event.guild) cache.put(data) event.guild.cache() - coreFlow.emit(GuildCreateEvent(Guild(data, kord), shard)) + return GuildCreateEvent(Guild(data, kord), shard) } - private suspend fun handle(event: GuildUpdate, shard: Int) { + private suspend fun handle(event: GuildUpdate, shard: Int, kord: Kord): GuildUpdateEvent { val data = GuildData.from(event.guild) cache.put(data) event.guild.cache() - coreFlow.emit(GuildUpdateEvent(Guild(data, kord), shard)) + return GuildUpdateEvent(Guild(data, kord), shard) } - private suspend fun handle(event: GuildDelete, shard: Int) = with(event.guild) { + private suspend fun handle(event: GuildDelete, shard: Int, kord: Kord): GuildDeleteEvent = with(event.guild) { val query = cache.query { idEq(GuildData::id, id) } val old = query.asFlow().map { Guild(it, kord) }.singleOrNull() query.remove() - coreFlow.emit(GuildDeleteEvent(id, unavailable.orElse(false), old, kord, shard)) + return GuildDeleteEvent(id, unavailable.orElse(false), old, kord, shard) } - private suspend fun handle(event: GuildBanAdd, shard: Int) = with(event.ban) { + private suspend fun handle(event: GuildBanAdd, shard: Int, kord: Kord): BanAddEvent = with(event.ban) { val data = UserData.from(user) cache.put(user) val user = User(data, kord) - coreFlow.emit(BanAddEvent(user, guildId, shard)) + return BanAddEvent(user, guildId, shard) } - private suspend fun handle(event: GuildBanRemove, shard: Int) = with(event.ban) { + private suspend fun handle(event: GuildBanRemove, shard: Int, kord: Kord): BanRemoveEvent = with(event.ban) { val data = UserData.from(user) cache.put(user) val user = User(data, kord) - coreFlow.emit(BanRemoveEvent(user, guildId, shard)) + return BanRemoveEvent(user, guildId, shard) } - private suspend fun handle(event: GuildEmojisUpdate, shard: Int) = with(event.emoji) { - val data = emojis.map { EmojiData.from(guildId, it.id!!, it) } - cache.putAll(data) + private suspend fun handle(event: GuildEmojisUpdate, shard: Int, kord: Kord): EmojisUpdateEvent = + with(event.emoji) { + val data = emojis.map { EmojiData.from(guildId, it.id!!, it) } + cache.putAll(data) - val emojis = data.map { GuildEmoji(it, kord) } + val emojis = data.map { GuildEmoji(it, kord) } - cache.query { idEq(GuildData::id, guildId) }.update { - it.copy(emojis = emojis.map { emoji -> emoji.id }) - } + cache.query { idEq(GuildData::id, guildId) }.update { + it.copy(emojis = emojis.map { emoji -> emoji.id }) + } - coreFlow.emit(EmojisUpdateEvent(guildId, emojis.toSet(), kord, shard)) - } + return EmojisUpdateEvent(guildId, emojis.toSet(), kord, shard) + } - private suspend fun handle(event: GuildIntegrationsUpdate, shard: Int) { - coreFlow.emit(IntegrationsUpdateEvent(event.integrations.guildId, kord, shard)) + private fun handle(event: GuildIntegrationsUpdate, shard: Int, kord: Kord): IntegrationsUpdateEvent { + return IntegrationsUpdateEvent(event.integrations.guildId, kord, shard) } - private suspend fun handle(event: GuildMemberAdd, shard: Int) = with(event.member) { + private suspend fun handle(event: GuildMemberAdd, shard: Int, kord: Kord): MemberJoinEvent = with(event.member) { val userData = UserData.from(user.value!!) val memberData = MemberData.from(user.value!!.id, event.member) @@ -145,48 +141,50 @@ internal class GuildEventHandler( val member = Member(memberData, userData, kord) - coreFlow.emit(MemberJoinEvent(member, shard)) + return MemberJoinEvent(member, shard) } - private suspend fun handle(event: GuildMemberRemove, shard: Int) = with(event.member) { - val userData = UserData.from(user) - cache.query { idEq(UserData::id, userData.id) }.remove() - val user = User(userData, kord) + private suspend fun handle(event: GuildMemberRemove, shard: Int, kord: Kord): MemberLeaveEvent = + with(event.member) { + val userData = UserData.from(user) + cache.query { idEq(UserData::id, userData.id) }.remove() + val user = User(userData, kord) - coreFlow.emit(MemberLeaveEvent(user, guildId, shard)) - } + return MemberLeaveEvent(user, guildId, shard) + } - private suspend fun handle(event: GuildMemberUpdate, shard: Int) = with(event.member) { - val userData = UserData.from(user) - cache.put(userData) + private suspend fun handle(event: GuildMemberUpdate, shard: Int, kord: Kord): MemberUpdateEvent = + with(event.member) { + val userData = UserData.from(user) + cache.put(userData) - val query = cache.query { - idEq(MemberData::userId, userData.id) - idEq(MemberData::guildId, guildId) - } - val old = query.asFlow().map { Member(it, userData, kord) }.singleOrNull() + val query = cache.query { + idEq(MemberData::userId, userData.id) + idEq(MemberData::guildId, guildId) + } + val old = query.asFlow().map { Member(it, userData, kord) }.singleOrNull() - val new = Member(MemberData.from(this), userData, kord) - cache.put(new.memberData) + val new = Member(MemberData.from(this), userData, kord) + cache.put(new.memberData) - coreFlow.emit(MemberUpdateEvent(new, old, kord, shard)) - } + return MemberUpdateEvent(new, old, kord, shard) + } - private suspend fun handle(event: GuildRoleCreate, shard: Int) { + private suspend fun handle(event: GuildRoleCreate, shard: Int, kord: Kord): RoleCreateEvent { val data = RoleData.from(event.role) cache.put(data) - coreFlow.emit(RoleCreateEvent(Role(data, kord), shard)) + return RoleCreateEvent(Role(data, kord), shard) } - private suspend fun handle(event: GuildRoleUpdate, shard: Int) { + private suspend fun handle(event: GuildRoleUpdate, shard: Int, kord: Kord): RoleUpdateEvent { val data = RoleData.from(event.role) cache.put(data) - coreFlow.emit(RoleUpdateEvent(Role(data, kord), shard)) + return RoleUpdateEvent(Role(data, kord), shard) } - private suspend fun handle(event: GuildRoleDelete, shard: Int) = with(event.role) { + private suspend fun handle(event: GuildRoleDelete, shard: Int, kord: Kord): RoleDeleteEvent = with(event.role) { val query = cache.query { idEq(RoleData::id, event.role.id) } val old = run { @@ -196,10 +194,10 @@ internal class GuildEventHandler( query.remove() - coreFlow.emit(RoleDeleteEvent(guildId, id, old, kord, shard)) + return RoleDeleteEvent(guildId, id, old, kord, shard) } - private suspend fun handle(event: GuildMembersChunk, shard: Int) = with(event.data) { + private suspend fun handle(event: GuildMembersChunk, shard: Int, kord: Kord): MembersChunkEvent = with(event.data) { val presences = presences.orEmpty().map { PresenceData.from(guildId, it) } cache.putAll(presences) @@ -210,37 +208,38 @@ internal class GuildEventHandler( cache.put(userData) } - coreFlow.emit(MembersChunkEvent(MembersChunkData.from(this), kord, shard)) + return MembersChunkEvent(MembersChunkData.from(this), kord, shard) } - private suspend fun handle(event: PresenceUpdate, shard: Int) = with(event.presence) { - val data = PresenceData.from(this.guildId.value!!, this) + private suspend fun handle(event: PresenceUpdate, shard: Int, kord: Kord): PresenceUpdateEvent = + with(event.presence) { + val data = PresenceData.from(this.guildId.value!!, this) - val old = cache.query { idEq(PresenceData::id, data.id) } - .asFlow().map { Presence(it, kord) }.singleOrNull() + val old = cache.query { idEq(PresenceData::id, data.id) } + .asFlow().map { Presence(it, kord) }.singleOrNull() - cache.put(data) - val new = Presence(data, kord) + cache.put(data) + val new = Presence(data, kord) - val user = cache - .query { idEq(UserData::id, event.presence.user.id) } - .singleOrNull() - ?.let { User(it, kord) } + val user = cache + .query { idEq(UserData::id, event.presence.user.id) } + .singleOrNull() + ?.let { User(it, kord) } - coreFlow.emit(PresenceUpdateEvent(user, this.user, guildId.value!!, old, new, shard)) - } + return PresenceUpdateEvent(user, this.user, guildId.value!!, old, new, shard) + } - private suspend fun handle(event: InviteCreate, shard: Int) = with(event) { + private suspend fun handle(event: InviteCreate, shard: Int, kord: Kord): InviteCreateEvent = with(event) { val data = InviteCreateData.from(invite) invite.inviter.value?.let { cache.put(UserData.from(it)) } invite.targetUser.value?.let { cache.put(UserData.from(it)) } - coreFlow.emit(InviteCreateEvent(data, kord, shard)) + return InviteCreateEvent(data, kord, shard) } - private suspend fun handle(event: InviteDelete, shard: Int) = with(event) { + private suspend fun handle(event: InviteDelete, shard: Int, kord: Kord): InviteDeleteEvent = with(event) { val data = InviteDeleteData.from(invite) - coreFlow.emit(InviteDeleteEvent(data, kord, shard)) + return InviteDeleteEvent(data, kord, shard) } } diff --git a/core/src/main/kotlin/gateway/handler/InteractionEventHandler.kt b/core/src/main/kotlin/gateway/handler/InteractionEventHandler.kt index f640e717a6d9..21476acdf9bf 100644 --- a/core/src/main/kotlin/gateway/handler/InteractionEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/InteractionEventHandler.kt @@ -10,34 +10,31 @@ import dev.kord.core.cache.idEq import dev.kord.core.entity.application.* import dev.kord.core.entity.interaction.* import dev.kord.core.event.interaction.* -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.* -import kotlinx.coroutines.flow.MutableSharedFlow import dev.kord.core.event.Event as CoreEvent class InteractionEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow, -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { - override suspend fun handle(event: Event, shard: Int) { - when (event) { - is InteractionCreate -> handle(event, shard) - is ApplicationCommandCreate -> handle(event, shard) - is ApplicationCommandUpdate -> handle(event, shard) - is ApplicationCommandDelete -> handle(event, shard) - else -> Unit - } + cache: DataCache +) : BaseGatewayEventHandler(cache) { + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is InteractionCreate -> handle(event, shard, kord) + is ApplicationCommandCreate -> handle(event, shard, kord) + is ApplicationCommandUpdate -> handle(event, shard, kord) + is ApplicationCommandDelete -> handle(event, shard, kord) + else -> null } - private suspend fun handle(event: InteractionCreate, shard: Int) { + private suspend fun handle(event: InteractionCreate, shard: Int, kord: Kord): CoreEvent { val data = InteractionData.from(event.interaction) val interaction = Interaction.from(data, kord) - val coreEvent = when(interaction) { - is GlobalChatInputCommandInteraction -> GlobalChatInputCommandInteractionCreateEvent(interaction, kord, shard) + val coreEvent = when (interaction) { + is GlobalChatInputCommandInteraction -> GlobalChatInputCommandInteractionCreateEvent( + interaction, + kord, + shard + ) is GlobalUserCommandInteraction -> GlobalUserCommandInteractionCreateEvent(interaction, kord, shard) is GlobalMessageCommandInteraction -> GlobalMessageCommandInteractionCreateEvent(interaction, kord, shard) is GuildChatInputCommandInteraction -> GuildChatInputCommandInteractionCreateEvent(interaction, kord, shard) @@ -48,47 +45,47 @@ class InteractionEventHandler( is UnknownComponentInteraction -> error("Unknown component.") is UnknownApplicationCommandInteraction -> error("Unknown component.") } - coreFlow.emit(coreEvent) + return coreEvent } - private suspend fun handle(event: ApplicationCommandCreate, shard: Int) { + private suspend fun handle(event: ApplicationCommandCreate, shard: Int, kord: Kord): CoreEvent { val data = ApplicationCommandData.from(event.application) cache.put(data) val application = GuildApplicationCommand(data, kord.rest.interaction) - val coreEvent = when(application) { + val coreEvent = when (application) { is GuildChatInputCommand -> ChatInputCommandCreateEvent(application, kord, shard) is GuildMessageCommand -> MessageCommandCreateEvent(application, kord, shard) is GuildUserCommand -> UserCommandCreateEvent(application, kord, shard) is UnknownGuildApplicationCommand -> UnknownApplicationCommandCreateEvent(application, kord, shard) } - coreFlow.emit(coreEvent) + return coreEvent } - private suspend fun handle(event: ApplicationCommandUpdate, shard: Int) { + private suspend fun handle(event: ApplicationCommandUpdate, shard: Int, kord: Kord): CoreEvent { val data = ApplicationCommandData.from(event.application) cache.put(data) val application = GuildApplicationCommand(data, kord.rest.interaction) - val coreEvent = when(application) { + val coreEvent = when (application) { is GuildChatInputCommand -> ChatInputCommandUpdateEvent(application, kord, shard) is GuildMessageCommand -> MessageCommandUpdateEvent(application, kord, shard) is GuildUserCommand -> UserCommandUpdateEvent(application, kord, shard) is UnknownGuildApplicationCommand -> UnknownApplicationCommandUpdateEvent(application, kord, shard) } - coreFlow.emit(coreEvent) + return coreEvent } - private suspend fun handle(event: ApplicationCommandDelete, shard: Int) { + private suspend fun handle(event: ApplicationCommandDelete, shard: Int, kord: Kord): CoreEvent { val data = ApplicationCommandData.from(event.application) cache.remove { idEq(ApplicationCommandData::id, data.id) } val application = GuildApplicationCommand(data, kord.rest.interaction) - val coreEvent = when(application) { + val coreEvent = when (application) { is GuildChatInputCommand -> ChatInputCommandDeleteEvent(application, kord, shard) is GuildMessageCommand -> MessageCommandDeleteEvent(application, kord, shard) is GuildUserCommand -> UserCommandDeleteEvent(application, kord, shard) is UnknownGuildApplicationCommand -> UnknownApplicationCommandDeleteEvent(application, kord, shard) } - coreFlow.emit(coreEvent) + return coreEvent } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/LifeCycleEventHandler.kt b/core/src/main/kotlin/gateway/handler/LifeCycleEventHandler.kt index 54e0256c3ad1..347a482c245c 100644 --- a/core/src/main/kotlin/gateway/handler/LifeCycleEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/LifeCycleEventHandler.kt @@ -2,7 +2,6 @@ package dev.kord.core.gateway.handler import dev.kord.cache.api.DataCache import dev.kord.cache.api.put -import dev.kord.common.entity.Snowflake import dev.kord.core.Kord import dev.kord.core.cache.data.UserData import dev.kord.core.entity.User @@ -10,50 +9,42 @@ import dev.kord.core.event.gateway.ConnectEvent import dev.kord.core.event.gateway.DisconnectEvent import dev.kord.core.event.gateway.ReadyEvent import dev.kord.core.event.gateway.ResumedEvent -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.* -import kotlinx.coroutines.flow.MutableSharedFlow import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") internal class LifeCycleEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { + cache: DataCache +) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int) = when (event) { - is Ready -> handle(event, shard) - is Resumed -> coreFlow.emit(ResumedEvent(kord, shard)) - Reconnect -> coreFlow.emit(ConnectEvent(kord, shard)) + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is Ready -> handle(event, shard, kord) + is Resumed -> ResumedEvent(kord, shard) + Reconnect -> ConnectEvent(kord, shard) is Close -> when (event) { - Close.Detach -> coreFlow.emit(DisconnectEvent.DetachEvent(kord, shard)) - Close.UserClose -> coreFlow.emit(DisconnectEvent.UserCloseEvent(kord, shard)) - Close.Timeout -> coreFlow.emit(DisconnectEvent.TimeoutEvent(kord, shard)) - is Close.DiscordClose -> coreFlow.emit( - DisconnectEvent.DiscordCloseEvent( - kord, - shard, - event.closeCode, - event.recoverable - ) + Close.Detach -> DisconnectEvent.DetachEvent(kord, shard) + Close.UserClose -> DisconnectEvent.UserCloseEvent(kord, shard) + Close.Timeout -> DisconnectEvent.TimeoutEvent(kord, shard) + is Close.DiscordClose -> DisconnectEvent.DiscordCloseEvent( + kord, + shard, + event.closeCode, + event.recoverable ) - Close.Reconnecting -> coreFlow.emit(DisconnectEvent.ReconnectingEvent(kord, shard)) - Close.ZombieConnection -> coreFlow.emit(DisconnectEvent.ZombieConnectionEvent(kord, shard)) - Close.RetryLimitReached -> coreFlow.emit(DisconnectEvent.RetryLimitReachedEvent(kord, shard)) - Close.SessionReset -> coreFlow.emit(DisconnectEvent.SessionReset(kord, shard)) + Close.Reconnecting -> DisconnectEvent.ReconnectingEvent(kord, shard) + Close.ZombieConnection -> DisconnectEvent.ZombieConnectionEvent(kord, shard) + Close.RetryLimitReached -> DisconnectEvent.RetryLimitReachedEvent(kord, shard) + Close.SessionReset -> DisconnectEvent.SessionReset(kord, shard) } - - else -> Unit + else -> null } - private suspend fun handle(event: Ready, shard: Int) = with(event.data) { + private suspend fun handle(event: Ready, shard: Int, kord: Kord): ReadyEvent = with(event.data) { val guilds = guilds.map { it.id }.toSet() val self = UserData.from(event.data.user) cache.put(self) - coreFlow.emit(ReadyEvent(event.data.version, guilds, User(self, kord), sessionId, kord, shard)) + return ReadyEvent(event.data.version, guilds, User(self, kord), sessionId, kord, shard) } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt b/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt index c3b737047628..22143d9bf7cc 100644 --- a/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt @@ -1,6 +1,5 @@ package dev.kord.core.gateway.handler -import cache.data.MessageInteractionData import dev.kord.cache.api.DataCache import dev.kord.cache.api.put import dev.kord.cache.api.query @@ -11,11 +10,8 @@ import dev.kord.core.cache.idEq import dev.kord.core.entity.Member import dev.kord.core.entity.Message import dev.kord.core.entity.ReactionEmoji -import dev.kord.core.entity.interaction.MessageInteraction import dev.kord.core.event.message.* -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.* -import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.singleOrNull import kotlinx.coroutines.flow.toSet @@ -23,25 +19,22 @@ import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") internal class MessageEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { - - override suspend fun handle(event: Event, shard: Int) = when (event) { - is MessageCreate -> handle(event, shard) - is MessageUpdate -> handle(event, shard) - is MessageDelete -> handle(event, shard) - is MessageDeleteBulk -> handle(event, shard) - is MessageReactionAdd -> handle(event, shard) - is MessageReactionRemove -> handle(event, shard) - is MessageReactionRemoveAll -> handle(event, shard) - is MessageReactionRemoveEmoji -> handle(event, shard) - else -> Unit + cache: DataCache +) : BaseGatewayEventHandler(cache) { + + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is MessageCreate -> handle(event, shard, kord) + is MessageUpdate -> handle(event, shard, kord) + is MessageDelete -> handle(event, shard, kord) + is MessageDeleteBulk -> handle(event, shard, kord) + is MessageReactionAdd -> handle(event, shard, kord) + is MessageReactionRemove -> handle(event, shard, kord) + is MessageReactionRemoveAll -> handle(event, shard, kord) + is MessageReactionRemoveEmoji -> handle(event, shard, kord) + else -> null } - private suspend fun handle(event: MessageCreate, shard: Int) = with(event.message) { + private suspend fun handle(event: MessageCreate, shard: Int, kord: Kord): MessageCreateEvent = with(event.message) { val data = MessageData.from(this) cache.put(data) @@ -62,7 +55,7 @@ internal class MessageEventHandler( } else null //cache interaction user if present. - if(interaction is Optional.Value) { + if (interaction is Optional.Value) { val userData = UserData.from(interaction.value!!.user) cache.put(userData) } @@ -75,10 +68,10 @@ internal class MessageEventHandler( } } - coreFlow.emit(MessageCreateEvent(Message(data, kord), guildId.value, member, shard)) + return MessageCreateEvent(Message(data, kord), guildId.value, member, shard) } - private suspend fun handle(event: MessageUpdate, shard: Int) = with(event.message) { + private suspend fun handle(event: MessageUpdate, shard: Int, kord: Kord): MessageUpdateEvent = with(event.message) { val query = cache.query { idEq(MessageData::id, id) } val old = query.asFlow().map { Message(it, kord) }.singleOrNull() @@ -92,66 +85,66 @@ internal class MessageEventHandler( } } - coreFlow.emit(MessageUpdateEvent(id, channelId, this, old, kord, shard)) + MessageUpdateEvent(id, channelId, this, old, kord, shard) } - private suspend fun handle(event: MessageDelete, shard: Int) = with(event.message) { + private suspend fun handle(event: MessageDelete, shard: Int, kord: Kord): MessageDeleteEvent = with(event.message) { val query = cache.query { idEq(MessageData::id, id) } val removed = query.singleOrNull()?.let { Message(it, kord) } query.remove() - coreFlow.emit( - MessageDeleteEvent(id, channelId, guildId.value, removed, kord, shard) - ) + return MessageDeleteEvent(id, channelId, guildId.value, removed, kord, shard) } - private suspend fun handle(event: MessageDeleteBulk, shard: Int) = with(event.messageBulk) { - val query = cache.query { MessageData::id `in` ids } + private suspend fun handle(event: MessageDeleteBulk, shard: Int, kord: Kord): MessageBulkDeleteEvent = + with(event.messageBulk) { + val query = cache.query { MessageData::id `in` ids } - val removed = query.asFlow().map { Message(it, kord) }.toSet() - query.remove() - - val ids = ids.asSequence().map { it }.toSet() + val removed = query.asFlow().map { Message(it, kord) }.toSet() + query.remove() - coreFlow.emit( - MessageBulkDeleteEvent(ids, removed, channelId, guildId.value, kord, shard) - ) - } + val ids = ids.asSequence().map { it }.toSet() - private suspend fun handle(event: MessageReactionAdd, shard: Int) = with(event.reaction) { - /** - * Reactions added will *always* have a name, the only case in which name is null is when a guild reaction - * no longer exists (only id is kept). Reacting with a non-existing reaction *should* be impossible. - **/ - val reaction = when (val id = emoji.id) { - null -> ReactionEmoji.Unicode(emoji.name!!) - else -> ReactionEmoji.Custom(id, emoji.name!!, emoji.animated.orElse(false)) + return MessageBulkDeleteEvent(ids, removed, channelId, guildId.value, kord, shard) } - cache.query { idEq(MessageData::id, messageId) }.update { - val isMe = kord.selfId == event.reaction.userId + private suspend fun handle(event: MessageReactionAdd, shard: Int, kord: Kord): ReactionAddEvent = + with(event.reaction) { + /** + * Reactions added will *always* have a name, the only case in which name is null is when a guild reaction + * no longer exists (only id is kept). Reacting with a non-existing reaction *should* be impossible. + **/ + val reaction = when (val id = emoji.id) { + null -> ReactionEmoji.Unicode(emoji.name!!) + else -> ReactionEmoji.Custom(id, emoji.name!!, emoji.animated.orElse(false)) + } - val reactions = if (it.reactions.value.isNullOrEmpty()) { - listOf(ReactionData.from(1, isMe, emoji)) - } else { - val reactions = it.reactions.orEmpty() - val reactionData = reactions.firstOrNull { reaction -> - if (emoji.id == null) reaction.emojiName == emoji.name - else reaction.emojiId == emoji.id && reaction.emojiName == emoji.name + cache.query { idEq(MessageData::id, messageId) }.update { + val isMe = kord.selfId == event.reaction.userId + + val reactions = if (it.reactions.value.isNullOrEmpty()) { + listOf(ReactionData.from(1, isMe, emoji)) + } else { + val reactions = it.reactions.orEmpty() + val reactionData = reactions.firstOrNull { reaction -> + if (emoji.id == null) reaction.emojiName == emoji.name + else reaction.emojiId == emoji.id && reaction.emojiName == emoji.name + } + + when (reactionData) { + null -> reactions + ReactionData.from(1, isMe, emoji) + else -> (reactions - reactionData) + reactionData.copy( + count = reactionData.count + 1, + me = isMe + ) + } } - when (reactionData) { - null -> reactions + ReactionData.from(1, isMe, emoji) - else -> (reactions - reactionData) + reactionData.copy(count = reactionData.count + 1, me = isMe) - } + it.copy(reactions = Optional.Value(reactions)) } - it.copy(reactions = Optional.Value(reactions)) - } - - coreFlow.emit( - ReactionAddEvent( + return ReactionAddEvent( userId, channelId, messageId, @@ -160,40 +153,42 @@ internal class MessageEventHandler( kord, shard ) - ) - } - - private suspend fun handle(event: MessageReactionRemove, shard: Int) = with(event.reaction) { - /** - * Reactions removed will *sometimes* have a name, the only case in which name is null is when a guild reaction - * no longer exists (only id is kept). Removing a non-existing reaction *should* be possible. - **/ - val reaction = when (val id = emoji.id) { - null -> ReactionEmoji.Unicode(emoji.name!!) - else -> ReactionEmoji.Custom(id, emoji.name ?: "", emoji.animated.orElse(false)) } - cache.query { idEq(MessageData::id, messageId) }.update { - val oldReactions = it.reactions.value ?: return@update it - if (oldReactions.isEmpty()) return@update it + private suspend fun handle(event: MessageReactionRemove, shard: Int, kord: Kord): ReactionRemoveEvent = + with(event.reaction) { + /** + * Reactions removed will *sometimes* have a name, the only case in which name is null is when a guild reaction + * no longer exists (only id is kept). Removing a non-existing reaction *should* be possible. + **/ + val reaction = when (val id = emoji.id) { + null -> ReactionEmoji.Unicode(emoji.name!!) + else -> ReactionEmoji.Custom(id, emoji.name ?: "", emoji.animated.orElse(false)) + } + + cache.query { idEq(MessageData::id, messageId) }.update { + val oldReactions = it.reactions.value ?: return@update it + if (oldReactions.isEmpty()) return@update it - val me = kord.selfId == event.reaction.userId + val me = kord.selfId == event.reaction.userId - val reactionData = oldReactions.firstOrNull { reaction -> - if (emoji.id == null) reaction.emojiName == emoji.name - else reaction.emojiId == emoji.id && reaction.emojiName == emoji.name - } ?: return@update it + val reactionData = oldReactions.firstOrNull { reaction -> + if (emoji.id == null) reaction.emojiName == emoji.name + else reaction.emojiId == emoji.id && reaction.emojiName == emoji.name + } ?: return@update it + + val reactions = when (val count = reactionData.count - 1) { + 0 -> (oldReactions - reactionData) + else -> (oldReactions - reactionData) + reactionData.copy( + count = count, + me = reactionData.me xor me + ) + } - val reactions = when (val count = reactionData.count - 1) { - 0 -> (oldReactions - reactionData) - else -> (oldReactions - reactionData) + reactionData.copy(count = count, me = reactionData.me xor me) + it.copy(reactions = Optional.Value(reactions)) } - it.copy(reactions = Optional.Value(reactions)) - } - - coreFlow.emit( - ReactionRemoveEvent( + return ReactionRemoveEvent( userId, channelId, messageId, @@ -202,29 +197,29 @@ internal class MessageEventHandler( kord, shard ) - ) - } + } - private suspend fun handle(event: MessageReactionRemoveAll, shard: Int) = with(event.reactions) { - cache.query { idEq(MessageData::id, messageId) }.update { it.copy(reactions = Optional.Missing()) } + private suspend fun handle(event: MessageReactionRemoveAll, shard: Int, kord: Kord): ReactionRemoveAllEvent = + with(event.reactions) { + cache.query { idEq(MessageData::id, messageId) } + .update { it.copy(reactions = Optional.Missing()) } - coreFlow.emit( - ReactionRemoveAllEvent( + return ReactionRemoveAllEvent( channelId, messageId, guildId.value, kord, shard ) - ) - } + } - private suspend fun handle(event: MessageReactionRemoveEmoji, shard: Int) = with(event.reaction) { - cache.query { idEq(MessageData::id, messageId) } - .update { it.copy(reactions = it.reactions.map { list -> list.filter { data -> data.emojiName != emoji.name } }) } + private suspend fun handle(event: MessageReactionRemoveEmoji, shard: Int, kord: Kord): ReactionRemoveEmojiEvent = + with(event.reaction) { + cache.query { idEq(MessageData::id, messageId) } + .update { it.copy(reactions = it.reactions.map { list -> list.filter { data -> data.emojiName != emoji.name } }) } - val data = ReactionRemoveEmojiData.from(this) - coreFlow.emit(ReactionRemoveEmojiEvent(data, kord, shard)) - } + val data = ReactionRemoveEmojiData.from(this) + return ReactionRemoveEmojiEvent(data, kord, shard) + } } diff --git a/core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt b/core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt index 8cbe5087f1e6..eadf176d3d3a 100644 --- a/core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt @@ -5,7 +5,6 @@ import dev.kord.cache.api.put import dev.kord.cache.api.query import dev.kord.cache.api.remove import dev.kord.common.entity.ChannelType -import dev.kord.common.entity.optional.Optional import dev.kord.common.entity.optional.orEmpty import dev.kord.core.Kord import dev.kord.core.cache.data.* @@ -13,30 +12,24 @@ import dev.kord.core.cache.idEq import dev.kord.core.entity.channel.Channel import dev.kord.core.entity.channel.thread.* import dev.kord.core.event.channel.thread.* -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.* -import kotlinx.coroutines.flow.MutableSharedFlow +import dev.kord.core.event.Event as CoreEvent class ThreadEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { - override suspend fun handle(event: Event, shard: Int) { - when (event) { - is ThreadCreate -> handle(event, shard) - is ThreadUpdate -> handle(event, shard) - is ThreadDelete -> handle(event, shard) - is ThreadListSync -> handle(event, shard) - is ThreadMemberUpdate -> handle(event, shard) - is ThreadMembersUpdate -> handle(event, shard) - else -> Unit - - } + cache: DataCache +) : BaseGatewayEventHandler(cache) { + + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is ThreadCreate -> handle(event, shard, kord) + is ThreadUpdate -> handle(event, shard, kord) + is ThreadDelete -> handle(event, shard, kord) + is ThreadListSync -> handle(event, shard, kord) + is ThreadMemberUpdate -> handle(event, shard, kord) + is ThreadMembersUpdate -> handle(event, shard, kord) + else -> null } - suspend fun handle(event: ThreadCreate, shard: Int) { + suspend fun handle(event: ThreadCreate, shard: Int, kord: Kord): CoreEvent? { val channelData = event.channel.toData() cache.put(channelData) @@ -44,12 +37,12 @@ class ThreadEventHandler( is NewsChannelThread -> NewsChannelThreadCreateEvent(channel, shard) is TextChannelThread -> TextChannelThreadCreateEvent(channel, shard) is ThreadChannel -> UnknownChannelThreadCreateEvent(channel, shard) - else -> return + else -> return null } - coreFlow.emit(coreEvent) + return coreEvent } - suspend fun handle(event: ThreadUpdate, shard: Int) { + suspend fun handle(event: ThreadUpdate, shard: Int, kord: Kord): CoreEvent? { val channelData = event.channel.toData() cache.put(channelData) @@ -57,14 +50,14 @@ class ThreadEventHandler( is NewsChannelThread -> NewsChannelThreadUpdateEvent(channel, shard) is TextChannelThread -> TextChannelThreadUpdateEvent(channel, shard) is ThreadChannel -> UnknownChannelThreadUpdateEvent(channel, shard) - else -> return + else -> return null } - coreFlow.emit(coreEvent) + return coreEvent } - suspend fun handle(event: ThreadDelete, shard: Int) { + suspend fun handle(event: ThreadDelete, shard: Int, kord: Kord): CoreEvent? { val channelData = event.channel.toData() val cachedData = cache.query { idEq(ChannelData::id, channelData.id) }.singleOrNull() @@ -77,12 +70,12 @@ class ThreadEventHandler( is ChannelType.GuildText -> TextChannelThreadDeleteEvent(channel, old as? TextChannelThread, shard) else -> UnknownChannelThreadDeleteEvent(channel, old as? ThreadChannel, shard) } - coreFlow.emit(coreEvent) cache.remove { idEq(ChannelData::id, channel.id) } + return coreEvent } - suspend fun handle(event: ThreadListSync, shard: Int) { + suspend fun handle(event: ThreadListSync, shard: Int, kord: Kord): CoreEvent? { val data = ThreadListSyncData.from(event) data.threads.forEach { thread -> @@ -92,19 +85,16 @@ class ThreadEventHandler( cache.put(member) } - val coreEvent = ThreadListSyncEvent(data, kord, shard) - - coreFlow.emit(coreEvent) + return ThreadListSyncEvent(data, kord, shard) } - suspend fun handle(event: ThreadMemberUpdate, shard: Int) { + fun handle(event: ThreadMemberUpdate, shard: Int, kord: Kord): CoreEvent? { val data = ThreadMemberData.from(event.member) val member = ThreadMember(data, kord) - val coreEvent = ThreadMemberUpdateEvent(member, kord, shard) - coreFlow.emit(coreEvent) + return ThreadMemberUpdateEvent(member, kord, shard) } - suspend fun handle(event: ThreadMembersUpdate, shard: Int) { + suspend fun handle(event: ThreadMembersUpdate, shard: Int, kord: Kord): CoreEvent? { val data = ThreadMembersUpdateEventData.from(event) for (removedMemberId in data.removedMemberIds.orEmpty()) { cache.remove { @@ -115,7 +105,6 @@ class ThreadEventHandler( for (addedMember in data.addedMembers.orEmpty()) { cache.put(addedMember) } - val coreEvent = ThreadMembersUpdateEvent(data, kord, shard) - coreFlow.emit(coreEvent) + return ThreadMembersUpdateEvent(data, kord, shard) } } diff --git a/core/src/main/kotlin/gateway/handler/UserEventHandler.kt b/core/src/main/kotlin/gateway/handler/UserEventHandler.kt index cdc45a026418..19888dcfb775 100644 --- a/core/src/main/kotlin/gateway/handler/UserEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/UserEventHandler.kt @@ -8,28 +8,23 @@ import dev.kord.core.cache.data.UserData import dev.kord.core.cache.idEq import dev.kord.core.entity.User import dev.kord.core.event.user.UserUpdateEvent -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.Event import dev.kord.gateway.UserUpdate -import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.singleOrNull import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") internal class UserEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { - - override suspend fun handle(event: Event, shard: Int) = when (event) { - is UserUpdate -> handle(event, shard) - else -> Unit + cache: DataCache +) : BaseGatewayEventHandler(cache) { + + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is UserUpdate -> handle(event, shard, kord) + else -> null } - private suspend fun handle(event: UserUpdate, shard: Int) { + private suspend fun handle(event: UserUpdate, shard: Int, kord: Kord): UserUpdateEvent { val data = UserData.from(event.user) val old = cache.query { idEq(UserData::id, data.id) } @@ -38,7 +33,7 @@ internal class UserEventHandler( cache.put(data) val new = User(data, kord) - coreFlow.emit(UserUpdateEvent(old, new, shard)) + return UserUpdateEvent(old, new, shard) } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/VoiceEventHandler.kt b/core/src/main/kotlin/gateway/handler/VoiceEventHandler.kt index 539bf82b0d9c..7c7f701be67c 100644 --- a/core/src/main/kotlin/gateway/handler/VoiceEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/VoiceEventHandler.kt @@ -3,37 +3,31 @@ package dev.kord.core.gateway.handler import dev.kord.cache.api.DataCache import dev.kord.cache.api.put import dev.kord.cache.api.query -import dev.kord.common.entity.optional.optional import dev.kord.core.Kord import dev.kord.core.cache.data.* import dev.kord.core.cache.idEq import dev.kord.core.entity.VoiceState import dev.kord.core.event.guild.VoiceServerUpdateEvent import dev.kord.core.event.user.VoiceStateUpdateEvent -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.Event import dev.kord.gateway.VoiceServerUpdate import dev.kord.gateway.VoiceStateUpdate -import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.singleOrNull import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") internal class VoiceEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { - - override suspend fun handle(event: Event, shard: Int) = when (event) { - is VoiceStateUpdate -> handle(event, shard) - is VoiceServerUpdate -> handle(event, shard) - else -> Unit + cache: DataCache +) : BaseGatewayEventHandler(cache) { + + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is VoiceStateUpdate -> handle(event, shard, kord) + is VoiceServerUpdate -> handle(event, shard, kord) + else -> null } - private suspend fun handle(event: VoiceStateUpdate, shard: Int) { + private suspend fun handle(event: VoiceStateUpdate, shard: Int, kord: Kord): VoiceStateUpdateEvent { val data = VoiceStateData.from(event.voiceState.guildId.value!!, event.voiceState) val old = cache.query { idEq(VoiceStateData::id, data.id) } @@ -42,11 +36,12 @@ internal class VoiceEventHandler( cache.put(data) val new = VoiceState(data, kord) - coreFlow.emit(VoiceStateUpdateEvent(old, new, shard)) + return VoiceStateUpdateEvent(old, new, shard) } - private suspend fun handle(event: VoiceServerUpdate, shard: Int) = with(event.voiceServerUpdateData) { - coreFlow.emit(VoiceServerUpdateEvent(token, guildId, endpoint, kord, shard)) - } + private fun handle(event: VoiceServerUpdate, shard: Int, kord: Kord): VoiceServerUpdateEvent = + with(event.voiceServerUpdateData) { + return VoiceServerUpdateEvent(token, guildId, endpoint, kord, shard) + } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/WebhookEventHandler.kt b/core/src/main/kotlin/gateway/handler/WebhookEventHandler.kt index f7141bfeae74..9c040dbdb623 100644 --- a/core/src/main/kotlin/gateway/handler/WebhookEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/WebhookEventHandler.kt @@ -3,27 +3,23 @@ package dev.kord.core.gateway.handler import dev.kord.cache.api.DataCache import dev.kord.core.Kord import dev.kord.core.event.guild.WebhookUpdateEvent -import dev.kord.core.gateway.MasterGateway import dev.kord.gateway.Event import dev.kord.gateway.WebhooksUpdate -import kotlinx.coroutines.flow.MutableSharedFlow import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") internal class WebhookEventHandler( - kord: Kord, - gateway: MasterGateway, - cache: DataCache, - coreFlow: MutableSharedFlow -) : BaseGatewayEventHandler(kord, gateway, cache, coreFlow) { + cache: DataCache +) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int) = when (event) { - is WebhooksUpdate -> handle(event, shard) - else -> Unit + override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { + is WebhooksUpdate -> handle(event, shard, kord) + else -> null } - private suspend fun handle(event: WebhooksUpdate, shard: Int) = with(event.webhooksUpdateData) { - coreFlow.emit(WebhookUpdateEvent(guildId, channelId, kord, shard)) - } + private fun handle(event: WebhooksUpdate, shard: Int, kord: Kord): WebhookUpdateEvent = + with(event.webhooksUpdateData) { + return WebhookUpdateEvent(guildId, channelId, kord, shard) + } } \ No newline at end of file From f5d4a29d023d3ccbd0c08b1ddd0c73e316c16b33 Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Thu, 23 Sep 2021 16:18:13 +0200 Subject: [PATCH 11/13] Events run as own job + scope customization --- .../handler/BaseGatewayEventHandler.kt | 3 +- .../gateway/handler/ChannelEventHandler.kt | 100 +++++---- .../handler/DefaultGatewayEventInterceptor.kt | 17 +- .../gateway/handler/GuildEventHandler.kt | 199 +++++++++++++----- .../handler/InteractionEventHandler.kt | 112 ++++++---- .../gateway/handler/LifeCycleEventHandler.kt | 64 +++--- .../gateway/handler/MessageEventHandler.kt | 108 +++++++--- .../gateway/handler/ThreadEventHandler.kt | 61 +++--- .../gateway/handler/UserEventHandler.kt | 9 +- .../gateway/handler/VoiceEventHandler.kt | 30 ++- .../gateway/handler/WebhookEventHandler.kt | 14 +- 11 files changed, 479 insertions(+), 238 deletions(-) diff --git a/core/src/main/kotlin/gateway/handler/BaseGatewayEventHandler.kt b/core/src/main/kotlin/gateway/handler/BaseGatewayEventHandler.kt index f0618adf4640..dc36a9496999 100644 --- a/core/src/main/kotlin/gateway/handler/BaseGatewayEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/BaseGatewayEventHandler.kt @@ -2,6 +2,7 @@ package dev.kord.core.gateway.handler import dev.kord.cache.api.DataCache import dev.kord.core.Kord +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent import dev.kord.gateway.Event as GatewayEvent @@ -9,6 +10,6 @@ abstract class BaseGatewayEventHandler( protected val cache: DataCache ) { - abstract suspend fun handle(event: GatewayEvent, shard: Int, kord: Kord): CoreEvent? + abstract suspend fun handle(event: GatewayEvent, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt b/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt index b57bea8f9fb1..85eb1df4980c 100644 --- a/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/ChannelEventHandler.kt @@ -14,6 +14,7 @@ import dev.kord.core.event.channel.* import dev.kord.core.event.channel.data.ChannelPinsUpdateEventData import dev.kord.core.event.channel.data.TypingStartEventData import dev.kord.gateway.* +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") @@ -21,77 +22,92 @@ internal class ChannelEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is ChannelCreate -> handle(event, shard, kord) - is ChannelUpdate -> handle(event, shard, kord) - is ChannelDelete -> handle(event, shard, kord) - is ChannelPinsUpdate -> handle(event, shard, kord) - is TypingStart -> handle(event, shard, kord) + override suspend fun handle( + event: Event, + shard: Int, + kord: Kord, + context: CoroutineContext + ): dev.kord.core.event.Event? = when (event) { + is ChannelCreate -> handle(event, shard, kord, context) + is ChannelUpdate -> handle(event, shard, kord, context) + is ChannelDelete -> handle(event, shard, kord, context) + is ChannelPinsUpdate -> handle(event, shard, kord, context) + is TypingStart -> handle(event, shard, kord, context) else -> null } - private suspend fun handle(event: ChannelCreate, shard: Int, kord: Kord): CoreEvent? { + private suspend fun handle(event: ChannelCreate, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { val data = ChannelData.from(event.channel) cache.put(data) val coreEvent = when (val channel = Channel.from(data, kord)) { - is NewsChannel -> NewsChannelCreateEvent(channel, shard) - is StoreChannel -> StoreChannelCreateEvent(channel, shard) - is DmChannel -> DMChannelCreateEvent(channel, shard) - is TextChannel -> TextChannelCreateEvent(channel, shard) - is StageChannel -> StageChannelCreateEvent(channel, shard) - is VoiceChannel -> VoiceChannelCreateEvent(channel, shard) - is Category -> CategoryCreateEvent(channel, shard) + is NewsChannel -> NewsChannelCreateEvent(channel, shard, context) + is StoreChannel -> StoreChannelCreateEvent(channel, shard, context) + is DmChannel -> DMChannelCreateEvent(channel, shard, context) + is TextChannel -> TextChannelCreateEvent(channel, shard, context) + is StageChannel -> StageChannelCreateEvent(channel, shard, context) + is VoiceChannel -> VoiceChannelCreateEvent(channel, shard, context) + is Category -> CategoryCreateEvent(channel, shard, context) is ThreadChannel -> return null - else -> UnknownChannelCreateEvent(channel, shard) + else -> UnknownChannelCreateEvent(channel, shard, context) } return coreEvent } - private suspend fun handle(event: ChannelUpdate, shard: Int, kord: Kord): CoreEvent? { + private suspend fun handle(event: ChannelUpdate, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { val data = ChannelData.from(event.channel) cache.put(data) val coreEvent = when (val channel = Channel.from(data, kord)) { - is NewsChannel -> NewsChannelUpdateEvent(channel, shard) - is StoreChannel -> StoreChannelUpdateEvent(channel, shard) - is DmChannel -> DMChannelUpdateEvent(channel, shard) - is TextChannel -> TextChannelUpdateEvent(channel, shard) - is StageChannel -> StageChannelUpdateEvent(channel, shard) - is VoiceChannel -> VoiceChannelUpdateEvent(channel, shard) - is Category -> CategoryUpdateEvent(channel, shard) + is NewsChannel -> NewsChannelUpdateEvent(channel, shard, context) + is StoreChannel -> StoreChannelUpdateEvent(channel, shard, context) + is DmChannel -> DMChannelUpdateEvent(channel, shard, context) + is TextChannel -> TextChannelUpdateEvent(channel, shard, context) + is StageChannel -> StageChannelUpdateEvent(channel, shard, context) + is VoiceChannel -> VoiceChannelUpdateEvent(channel, shard, context) + is Category -> CategoryUpdateEvent(channel, shard, context) is ThreadChannel -> return null - else -> UnknownChannelUpdateEvent(channel, shard) + else -> UnknownChannelUpdateEvent(channel, shard, context) } return coreEvent } - private suspend fun handle(event: ChannelDelete, shard: Int, kord: Kord): CoreEvent? { + private suspend fun handle(event: ChannelDelete, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { cache.remove { idEq(ChannelData::id, event.channel.id) } val data = ChannelData.from(event.channel) val coreEvent = when (val channel = Channel.from(data, kord)) { - is NewsChannel -> NewsChannelDeleteEvent(channel, shard) - is StoreChannel -> StoreChannelDeleteEvent(channel, shard) - is DmChannel -> DMChannelDeleteEvent(channel, shard) - is TextChannel -> TextChannelDeleteEvent(channel, shard) - is StageChannel -> StageChannelDeleteEvent(channel, shard) - is VoiceChannel -> VoiceChannelDeleteEvent(channel, shard) - is Category -> CategoryDeleteEvent(channel, shard) + is NewsChannel -> NewsChannelDeleteEvent(channel, shard, context) + is StoreChannel -> StoreChannelDeleteEvent(channel, shard, context) + is DmChannel -> DMChannelDeleteEvent(channel, shard, context) + is TextChannel -> TextChannelDeleteEvent(channel, shard, context) + is StageChannel -> StageChannelDeleteEvent(channel, shard, context) + is VoiceChannel -> VoiceChannelDeleteEvent(channel, shard, context) + is Category -> CategoryDeleteEvent(channel, shard, context) is ThreadChannel -> return null - else -> UnknownChannelDeleteEvent(channel, shard) + else -> UnknownChannelDeleteEvent(channel, shard, context) } return coreEvent } - private suspend fun handle(event: ChannelPinsUpdate, shard: Int, kord: Kord): ChannelPinsUpdateEvent = + private suspend fun handle( + event: ChannelPinsUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): ChannelPinsUpdateEvent = with(event.pins) { - val coreEvent = ChannelPinsUpdateEvent(ChannelPinsUpdateEventData.from(this), kord, shard) + val coreEvent = ChannelPinsUpdateEvent( + ChannelPinsUpdateEventData.from(this), + kord, + shard, + coroutineContext = context + ) cache.query { idEq(ChannelData::id, channelId) }.update { it.copy(lastPinTimestamp = lastPinTimestamp) @@ -100,18 +116,22 @@ internal class ChannelEventHandler( return coreEvent } - private suspend fun handle(event: TypingStart, shard: Int, kord: Kord): TypingStartEvent = with(event.data) { + private suspend fun handle( + event: TypingStart, + shard: Int, + kord: Kord, + context: CoroutineContext + ): TypingStartEvent = with(event.data) { member.value?.let { cache.put(MemberData.from(userId = it.user.value!!.id, guildId = guildId.value!!, it)) } - val coreEvent = TypingStartEvent( + return TypingStartEvent( TypingStartEventData.from(this), kord, - shard + shard, + coroutineContext = context ) - - return coreEvent } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt b/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt index 84ffd7db9e3f..acb218087e24 100644 --- a/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt +++ b/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt @@ -4,14 +4,18 @@ import dev.kord.cache.api.DataCache import dev.kord.core.Kord import dev.kord.core.gateway.ShardEvent import io.ktor.util.* +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.job import mu.KotlinLogging +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent private val logger = KotlinLogging.logger { } @Suppress("EXPERIMENTAL_API_USAGE") class DefaultGatewayEventInterceptor( - cache: DataCache + cache: DataCache, + private val eventScope: ((ShardEvent, Kord) -> CoroutineContext)? = null ) : GatewayEventInterceptor() { private val listeners = listOf( @@ -29,7 +33,13 @@ class DefaultGatewayEventInterceptor( override suspend fun handle(event: ShardEvent, kord: Kord): CoreEvent? { return runCatching { for (listener in listeners) { - val coreEvent = listener.handle(event.event, event.shard, kord) + val coreEvent = listener.handle( + event.event, + event.shard, + kord, + (eventScope?.invoke(event, kord) ?: kord.coroutineContext) + + SupervisorJob(kord.coroutineContext.job) + ) if (coreEvent != null) { return coreEvent } @@ -39,5 +49,4 @@ class DefaultGatewayEventInterceptor( logger.error(it) }.getOrNull() } - -} +} \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/GuildEventHandler.kt b/core/src/main/kotlin/gateway/handler/GuildEventHandler.kt index df9937c45868..0bed5cc523ed 100644 --- a/core/src/main/kotlin/gateway/handler/GuildEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/GuildEventHandler.kt @@ -17,6 +17,7 @@ import dev.kord.core.event.role.RoleUpdateEvent import dev.kord.core.event.user.PresenceUpdateEvent import dev.kord.gateway.* import kotlinx.coroutines.flow.* +import kotlin.coroutines.CoroutineContext import dev.kord.common.entity.DiscordGuild as GatewayGuild import dev.kord.core.event.Event as CoreEvent @@ -25,26 +26,27 @@ internal class GuildEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is GuildCreate -> handle(event, shard, kord) - is GuildUpdate -> handle(event, shard, kord) - is GuildDelete -> handle(event, shard, kord) - is GuildBanAdd -> handle(event, shard, kord) - is GuildBanRemove -> handle(event, shard, kord) - is GuildEmojisUpdate -> handle(event, shard, kord) - is GuildIntegrationsUpdate -> handle(event, shard, kord) - is GuildMemberAdd -> handle(event, shard, kord) - is GuildMemberRemove -> handle(event, shard, kord) - is GuildMemberUpdate -> handle(event, shard, kord) - is GuildRoleCreate -> handle(event, shard, kord) - is GuildRoleUpdate -> handle(event, shard, kord) - is GuildRoleDelete -> handle(event, shard, kord) - is GuildMembersChunk -> handle(event, shard, kord) - is PresenceUpdate -> handle(event, shard, kord) - is InviteCreate -> handle(event, shard, kord) - is InviteDelete -> handle(event, shard, kord) - else -> null - } + override suspend fun handle(event: Event, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? = + when (event) { + is GuildCreate -> handle(event, shard, kord, context) + is GuildUpdate -> handle(event, shard, kord, context) + is GuildDelete -> handle(event, shard, kord, context) + is GuildBanAdd -> handle(event, shard, kord, context) + is GuildBanRemove -> handle(event, shard, kord, context) + is GuildEmojisUpdate -> handle(event, shard, kord, context) + is GuildIntegrationsUpdate -> handle(event, shard, kord, context) + is GuildMemberAdd -> handle(event, shard, kord, context) + is GuildMemberRemove -> handle(event, shard, kord, context) + is GuildMemberUpdate -> handle(event, shard, kord, context) + is GuildRoleCreate -> handle(event, shard, kord, context) + is GuildRoleUpdate -> handle(event, shard, kord, context) + is GuildRoleDelete -> handle(event, shard, kord, context) + is GuildMembersChunk -> handle(event, shard, kord, context) + is PresenceUpdate -> handle(event, shard, kord, context) + is InviteCreate -> handle(event, shard, kord, context) + is InviteDelete -> handle(event, shard, kord, context) + else -> null + } private suspend fun GatewayGuild.cache() { for (member in members.orEmpty()) { @@ -72,49 +74,75 @@ internal class GuildEventHandler( } } - private suspend fun handle(event: GuildCreate, shard: Int, kord: Kord): GuildCreateEvent { + private suspend fun handle( + event: GuildCreate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): GuildCreateEvent { val data = GuildData.from(event.guild) cache.put(data) event.guild.cache() - return GuildCreateEvent(Guild(data, kord), shard) + return GuildCreateEvent(Guild(data, kord), shard, context) } - private suspend fun handle(event: GuildUpdate, shard: Int, kord: Kord): GuildUpdateEvent { + private suspend fun handle( + event: GuildUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): GuildUpdateEvent { val data = GuildData.from(event.guild) val old = cache.query { idEq(GuildData::id, event.guild.id) }.singleOrNull() cache.put(data) event.guild.cache() - return GuildUpdateEvent(Guild(data, kord), old?.let { Guild(it, kord) }, shard) + return GuildUpdateEvent(Guild(data, kord), old?.let { Guild(it, kord) }, shard, context) } - private suspend fun handle(event: GuildDelete, shard: Int, kord: Kord): GuildDeleteEvent = with(event.guild) { + private suspend fun handle( + event: GuildDelete, + shard: Int, + kord: Kord, + context: CoroutineContext + ): GuildDeleteEvent = with(event.guild) { val query = cache.query { idEq(GuildData::id, id) } val old = query.asFlow().map { Guild(it, kord) }.singleOrNull() query.remove() - return GuildDeleteEvent(id, unavailable.orElse(false), old, kord, shard) + return GuildDeleteEvent(id, unavailable.orElse(false), old, kord, shard, context) } - private suspend fun handle(event: GuildBanAdd, shard: Int, kord: Kord): BanAddEvent = with(event.ban) { - val data = UserData.from(user) - cache.put(user) - val user = User(data, kord) + private suspend fun handle(event: GuildBanAdd, shard: Int, kord: Kord, context: CoroutineContext): BanAddEvent = + with(event.ban) { + val data = UserData.from(user) + cache.put(user) + val user = User(data, kord) - return BanAddEvent(user, guildId, shard) - } + return BanAddEvent(user, guildId, shard, coroutineContext = context) + } - private suspend fun handle(event: GuildBanRemove, shard: Int, kord: Kord): BanRemoveEvent = with(event.ban) { + private suspend fun handle( + event: GuildBanRemove, + shard: Int, + kord: Kord, + context: CoroutineContext + ): BanRemoveEvent = with(event.ban) { val data = UserData.from(user) cache.put(user) val user = User(data, kord) - return BanRemoveEvent(user, guildId, shard) + return BanRemoveEvent(user, guildId, shard, coroutineContext = context) } - private suspend fun handle(event: GuildEmojisUpdate, shard: Int, kord: Kord): EmojisUpdateEvent = + private suspend fun handle( + event: GuildEmojisUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): EmojisUpdateEvent = with(event.emoji) { val data = emojis.map { EmojiData.from(guildId, it.id!!, it) } cache.putAll(data) @@ -125,15 +153,25 @@ internal class GuildEventHandler( it.copy(emojis = emojis.map { emoji -> emoji.id }) } - return EmojisUpdateEvent(guildId, emojis.toSet(), kord, shard) + return EmojisUpdateEvent(guildId, emojis.toSet(), kord, shard, coroutineContext = context) } - private fun handle(event: GuildIntegrationsUpdate, shard: Int, kord: Kord): IntegrationsUpdateEvent { - return IntegrationsUpdateEvent(event.integrations.guildId, kord, shard) + private fun handle( + event: GuildIntegrationsUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): IntegrationsUpdateEvent { + return IntegrationsUpdateEvent(event.integrations.guildId, kord, shard, coroutineContext = context) } - private suspend fun handle(event: GuildMemberAdd, shard: Int, kord: Kord): MemberJoinEvent = with(event.member) { + private suspend fun handle( + event: GuildMemberAdd, + shard: Int, + kord: Kord, + context: CoroutineContext + ): MemberJoinEvent = with(event.member) { val userData = UserData.from(user.value!!) val memberData = MemberData.from(user.value!!.id, event.member) @@ -142,19 +180,29 @@ internal class GuildEventHandler( val member = Member(memberData, userData, kord) - return MemberJoinEvent(member, shard) + return MemberJoinEvent(member, shard, coroutineContext = context) } - private suspend fun handle(event: GuildMemberRemove, shard: Int, kord: Kord): MemberLeaveEvent = + private suspend fun handle( + event: GuildMemberRemove, + shard: Int, + kord: Kord, + context: CoroutineContext + ): MemberLeaveEvent = with(event.member) { val userData = UserData.from(user) cache.query { idEq(UserData::id, userData.id) }.remove() val user = User(userData, kord) - return MemberLeaveEvent(user, guildId, shard) + return MemberLeaveEvent(user, guildId, shard, context) } - private suspend fun handle(event: GuildMemberUpdate, shard: Int, kord: Kord): MemberUpdateEvent = + private suspend fun handle( + event: GuildMemberUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): MemberUpdateEvent = with(event.member) { val userData = UserData.from(user) cache.put(userData) @@ -168,24 +216,39 @@ internal class GuildEventHandler( val new = Member(MemberData.from(this), userData, kord) cache.put(new.memberData) - return MemberUpdateEvent(new, old, kord, shard) + return MemberUpdateEvent(new, old, kord, shard, coroutineContext = context) } - private suspend fun handle(event: GuildRoleCreate, shard: Int, kord: Kord): RoleCreateEvent { + private suspend fun handle( + event: GuildRoleCreate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): RoleCreateEvent { val data = RoleData.from(event.role) cache.put(data) - return RoleCreateEvent(Role(data, kord), shard) + return RoleCreateEvent(Role(data, kord), shard, coroutineContext = context) } - private suspend fun handle(event: GuildRoleUpdate, shard: Int, kord: Kord): RoleUpdateEvent { + private suspend fun handle( + event: GuildRoleUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): RoleUpdateEvent { val data = RoleData.from(event.role) cache.put(data) - return RoleUpdateEvent(Role(data, kord), shard) + return RoleUpdateEvent(Role(data, kord), shard, coroutineContext = context) } - private suspend fun handle(event: GuildRoleDelete, shard: Int, kord: Kord): RoleDeleteEvent = with(event.role) { + private suspend fun handle( + event: GuildRoleDelete, + shard: Int, + kord: Kord, + context: CoroutineContext + ): RoleDeleteEvent = with(event.role) { val query = cache.query { idEq(RoleData::id, event.role.id) } val old = run { @@ -195,10 +258,15 @@ internal class GuildEventHandler( query.remove() - return RoleDeleteEvent(guildId, id, old, kord, shard) + return RoleDeleteEvent(guildId, id, old, kord, shard, coroutineContext = context) } - private suspend fun handle(event: GuildMembersChunk, shard: Int, kord: Kord): MembersChunkEvent = with(event.data) { + private suspend fun handle( + event: GuildMembersChunk, + shard: Int, + kord: Kord, + context: CoroutineContext + ): MembersChunkEvent = with(event.data) { val presences = presences.orEmpty().map { PresenceData.from(guildId, it) } cache.putAll(presences) @@ -209,10 +277,15 @@ internal class GuildEventHandler( cache.put(userData) } - return MembersChunkEvent(MembersChunkData.from(this), kord, shard) + return MembersChunkEvent(MembersChunkData.from(this), kord, shard, coroutineContext = context) } - private suspend fun handle(event: PresenceUpdate, shard: Int, kord: Kord): PresenceUpdateEvent = + private suspend fun handle( + event: PresenceUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): PresenceUpdateEvent = with(event.presence) { val data = PresenceData.from(this.guildId.value!!, this) @@ -227,20 +300,30 @@ internal class GuildEventHandler( .singleOrNull() ?.let { User(it, kord) } - return PresenceUpdateEvent(user, this.user, guildId.value!!, old, new, shard) + return PresenceUpdateEvent(user, this.user, guildId.value!!, old, new, shard, coroutineContext = context) } - private suspend fun handle(event: InviteCreate, shard: Int, kord: Kord): InviteCreateEvent = with(event) { + private suspend fun handle( + event: InviteCreate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): InviteCreateEvent = with(event) { val data = InviteCreateData.from(invite) invite.inviter.value?.let { cache.put(UserData.from(it)) } invite.targetUser.value?.let { cache.put(UserData.from(it)) } - return InviteCreateEvent(data, kord, shard) + return InviteCreateEvent(data, kord, shard, coroutineContext = context) } - private suspend fun handle(event: InviteDelete, shard: Int, kord: Kord): InviteDeleteEvent = with(event) { + private fun handle( + event: InviteDelete, + shard: Int, + kord: Kord, + context: CoroutineContext + ): InviteDeleteEvent = with(event) { val data = InviteDeleteData.from(invite) - return InviteDeleteEvent(data, kord, shard) + return InviteDeleteEvent(data, kord, shard, coroutineContext = context) } } diff --git a/core/src/main/kotlin/gateway/handler/InteractionEventHandler.kt b/core/src/main/kotlin/gateway/handler/InteractionEventHandler.kt index 21476acdf9bf..d4af0b3fdaa8 100644 --- a/core/src/main/kotlin/gateway/handler/InteractionEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/InteractionEventHandler.kt @@ -11,6 +11,7 @@ import dev.kord.core.entity.application.* import dev.kord.core.entity.interaction.* import dev.kord.core.event.interaction.* import dev.kord.gateway.* +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent @@ -18,73 +19,106 @@ class InteractionEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is InteractionCreate -> handle(event, shard, kord) - is ApplicationCommandCreate -> handle(event, shard, kord) - is ApplicationCommandUpdate -> handle(event, shard, kord) - is ApplicationCommandDelete -> handle(event, shard, kord) - else -> null - } + override suspend fun handle(event: Event, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? = + when (event) { + is InteractionCreate -> handle(event, shard, kord, context) + is ApplicationCommandCreate -> handle(event, shard, kord, context) + is ApplicationCommandUpdate -> handle(event, shard, kord, context) + is ApplicationCommandDelete -> handle(event, shard, kord, context) + else -> null + } - private suspend fun handle(event: InteractionCreate, shard: Int, kord: Kord): CoreEvent { + private fun handle(event: InteractionCreate, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent { val data = InteractionData.from(event.interaction) - val interaction = Interaction.from(data, kord) - val coreEvent = when (interaction) { + val coreEvent = when (val interaction = Interaction.from(data, kord)) { is GlobalChatInputCommandInteraction -> GlobalChatInputCommandInteractionCreateEvent( interaction, kord, - shard + shard, + context + ) + is GlobalUserCommandInteraction -> GlobalUserCommandInteractionCreateEvent( + interaction, + kord, + shard, + context + ) + is GlobalMessageCommandInteraction -> GlobalMessageCommandInteractionCreateEvent( + interaction, + kord, + shard, + context + ) + is GuildChatInputCommandInteraction -> GuildChatInputCommandInteractionCreateEvent( + interaction, + kord, + shard, + context + ) + is GuildMessageCommandInteraction -> GuildMessageCommandInteractionCreateEvent( + interaction, + kord, + shard, + context ) - is GlobalUserCommandInteraction -> GlobalUserCommandInteractionCreateEvent(interaction, kord, shard) - is GlobalMessageCommandInteraction -> GlobalMessageCommandInteractionCreateEvent(interaction, kord, shard) - is GuildChatInputCommandInteraction -> GuildChatInputCommandInteractionCreateEvent(interaction, kord, shard) - is GuildMessageCommandInteraction -> GuildMessageCommandInteractionCreateEvent(interaction, kord, shard) - is GuildUserCommandInteraction -> GuildUserCommandInteractionCreateEvent(interaction, kord, shard) - is ButtonInteraction -> ButtonInteractionCreateEvent(interaction, kord, shard) - is SelectMenuInteraction -> SelectMenuInteractionCreateEvent(interaction, kord, shard) + is GuildUserCommandInteraction -> GuildUserCommandInteractionCreateEvent(interaction, kord, shard, context) + is ButtonInteraction -> ButtonInteractionCreateEvent(interaction, kord, shard, context) + is SelectMenuInteraction -> SelectMenuInteractionCreateEvent(interaction, kord, shard, context) is UnknownComponentInteraction -> error("Unknown component.") is UnknownApplicationCommandInteraction -> error("Unknown component.") } return coreEvent } - private suspend fun handle(event: ApplicationCommandCreate, shard: Int, kord: Kord): CoreEvent { + private suspend fun handle( + event: ApplicationCommandCreate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): CoreEvent { val data = ApplicationCommandData.from(event.application) cache.put(data) - val application = GuildApplicationCommand(data, kord.rest.interaction) - val coreEvent = when (application) { - is GuildChatInputCommand -> ChatInputCommandCreateEvent(application, kord, shard) - is GuildMessageCommand -> MessageCommandCreateEvent(application, kord, shard) - is GuildUserCommand -> UserCommandCreateEvent(application, kord, shard) - is UnknownGuildApplicationCommand -> UnknownApplicationCommandCreateEvent(application, kord, shard) + val coreEvent = when (val application = GuildApplicationCommand(data, kord.rest.interaction)) { + is GuildChatInputCommand -> ChatInputCommandCreateEvent(application, kord, shard, context) + is GuildMessageCommand -> MessageCommandCreateEvent(application, kord, shard, context) + is GuildUserCommand -> UserCommandCreateEvent(application, kord, shard, context) + is UnknownGuildApplicationCommand -> UnknownApplicationCommandCreateEvent(application, kord, shard, context) } return coreEvent } - private suspend fun handle(event: ApplicationCommandUpdate, shard: Int, kord: Kord): CoreEvent { + private suspend fun handle( + event: ApplicationCommandUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): CoreEvent { val data = ApplicationCommandData.from(event.application) cache.put(data) - val application = GuildApplicationCommand(data, kord.rest.interaction) - val coreEvent = when (application) { - is GuildChatInputCommand -> ChatInputCommandUpdateEvent(application, kord, shard) - is GuildMessageCommand -> MessageCommandUpdateEvent(application, kord, shard) - is GuildUserCommand -> UserCommandUpdateEvent(application, kord, shard) - is UnknownGuildApplicationCommand -> UnknownApplicationCommandUpdateEvent(application, kord, shard) + val coreEvent = when (val application = GuildApplicationCommand(data, kord.rest.interaction)) { + is GuildChatInputCommand -> ChatInputCommandUpdateEvent(application, kord, shard, context) + is GuildMessageCommand -> MessageCommandUpdateEvent(application, kord, shard, context) + is GuildUserCommand -> UserCommandUpdateEvent(application, kord, shard, context) + is UnknownGuildApplicationCommand -> UnknownApplicationCommandUpdateEvent(application, kord, shard, context) } return coreEvent } - private suspend fun handle(event: ApplicationCommandDelete, shard: Int, kord: Kord): CoreEvent { + private suspend fun handle( + event: ApplicationCommandDelete, + shard: Int, + kord: Kord, + context: CoroutineContext + ): CoreEvent { val data = ApplicationCommandData.from(event.application) cache.remove { idEq(ApplicationCommandData::id, data.id) } - val application = GuildApplicationCommand(data, kord.rest.interaction) - val coreEvent = when (application) { - is GuildChatInputCommand -> ChatInputCommandDeleteEvent(application, kord, shard) - is GuildMessageCommand -> MessageCommandDeleteEvent(application, kord, shard) - is GuildUserCommand -> UserCommandDeleteEvent(application, kord, shard) - is UnknownGuildApplicationCommand -> UnknownApplicationCommandDeleteEvent(application, kord, shard) + val coreEvent = when (val application = GuildApplicationCommand(data, kord.rest.interaction)) { + is GuildChatInputCommand -> ChatInputCommandDeleteEvent(application, kord, shard, context) + is GuildMessageCommand -> MessageCommandDeleteEvent(application, kord, shard, context) + is GuildUserCommand -> UserCommandDeleteEvent(application, kord, shard, context) + is UnknownGuildApplicationCommand -> UnknownApplicationCommandDeleteEvent(application, kord, shard, context) } return coreEvent } diff --git a/core/src/main/kotlin/gateway/handler/LifeCycleEventHandler.kt b/core/src/main/kotlin/gateway/handler/LifeCycleEventHandler.kt index 347a482c245c..fd6b422b6538 100644 --- a/core/src/main/kotlin/gateway/handler/LifeCycleEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/LifeCycleEventHandler.kt @@ -10,6 +10,7 @@ import dev.kord.core.event.gateway.DisconnectEvent import dev.kord.core.event.gateway.ReadyEvent import dev.kord.core.event.gateway.ResumedEvent import dev.kord.gateway.* +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") @@ -17,34 +18,45 @@ internal class LifeCycleEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is Ready -> handle(event, shard, kord) - is Resumed -> ResumedEvent(kord, shard) - Reconnect -> ConnectEvent(kord, shard) - is Close -> when (event) { - Close.Detach -> DisconnectEvent.DetachEvent(kord, shard) - Close.UserClose -> DisconnectEvent.UserCloseEvent(kord, shard) - Close.Timeout -> DisconnectEvent.TimeoutEvent(kord, shard) - is Close.DiscordClose -> DisconnectEvent.DiscordCloseEvent( - kord, - shard, - event.closeCode, - event.recoverable - ) - Close.Reconnecting -> DisconnectEvent.ReconnectingEvent(kord, shard) - Close.ZombieConnection -> DisconnectEvent.ZombieConnectionEvent(kord, shard) - Close.RetryLimitReached -> DisconnectEvent.RetryLimitReachedEvent(kord, shard) - Close.SessionReset -> DisconnectEvent.SessionReset(kord, shard) + override suspend fun handle(event: Event, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? = + when (event) { + is Ready -> handle(event, shard, kord, context) + is Resumed -> ResumedEvent(kord, shard, context) + Reconnect -> ConnectEvent(kord, shard, context) + is Close -> when (event) { + Close.Detach -> DisconnectEvent.DetachEvent(kord, shard, context) + Close.UserClose -> DisconnectEvent.UserCloseEvent(kord, shard, context) + Close.Timeout -> DisconnectEvent.TimeoutEvent(kord, shard, context) + is Close.DiscordClose -> DisconnectEvent.DiscordCloseEvent( + kord, + shard, + event.closeCode, + event.recoverable, + context + ) + Close.Reconnecting -> DisconnectEvent.ReconnectingEvent(kord, shard, context) + Close.ZombieConnection -> DisconnectEvent.ZombieConnectionEvent(kord, shard, context) + Close.RetryLimitReached -> DisconnectEvent.RetryLimitReachedEvent(kord, shard, context) + Close.SessionReset -> DisconnectEvent.SessionReset(kord, shard, context) + } + else -> null } - else -> null - } - private suspend fun handle(event: Ready, shard: Int, kord: Kord): ReadyEvent = with(event.data) { - val guilds = guilds.map { it.id }.toSet() - val self = UserData.from(event.data.user) + private suspend fun handle(event: Ready, shard: Int, kord: Kord, context: CoroutineContext): ReadyEvent = + with(event.data) { + val guilds = guilds.map { it.id }.toSet() + val self = UserData.from(event.data.user) - cache.put(self) + cache.put(self) - return ReadyEvent(event.data.version, guilds, User(self, kord), sessionId, kord, shard) - } + return ReadyEvent( + event.data.version, + guilds, + User(self, kord), + sessionId, + kord, + shard, + coroutineContext = context + ) + } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt b/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt index 22143d9bf7cc..7b3f45677566 100644 --- a/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/MessageEventHandler.kt @@ -15,26 +15,36 @@ import dev.kord.gateway.* import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.singleOrNull import kotlinx.coroutines.flow.toSet -import dev.kord.core.event.Event as CoreEvent +import kotlin.coroutines.CoroutineContext @Suppress("EXPERIMENTAL_API_USAGE") internal class MessageEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is MessageCreate -> handle(event, shard, kord) - is MessageUpdate -> handle(event, shard, kord) - is MessageDelete -> handle(event, shard, kord) - is MessageDeleteBulk -> handle(event, shard, kord) - is MessageReactionAdd -> handle(event, shard, kord) - is MessageReactionRemove -> handle(event, shard, kord) - is MessageReactionRemoveAll -> handle(event, shard, kord) - is MessageReactionRemoveEmoji -> handle(event, shard, kord) + override suspend fun handle( + event: Event, + shard: Int, + kord: Kord, + context: CoroutineContext + ): dev.kord.core.event.Event? = when (event) { + is MessageCreate -> handle(event, shard, kord, context) + is MessageUpdate -> handle(event, shard, kord, context) + is MessageDelete -> handle(event, shard, kord, context) + is MessageDeleteBulk -> handle(event, shard, kord, context) + is MessageReactionAdd -> handle(event, shard, kord, context) + is MessageReactionRemove -> handle(event, shard, kord, context) + is MessageReactionRemoveAll -> handle(event, shard, kord, context) + is MessageReactionRemoveEmoji -> handle(event, shard, kord, context) else -> null } - private suspend fun handle(event: MessageCreate, shard: Int, kord: Kord): MessageCreateEvent = with(event.message) { + private suspend fun handle( + event: MessageCreate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): MessageCreateEvent = with(event.message) { val data = MessageData.from(this) cache.put(data) @@ -68,10 +78,15 @@ internal class MessageEventHandler( } } - return MessageCreateEvent(Message(data, kord), guildId.value, member, shard) + return MessageCreateEvent(Message(data, kord), guildId.value, member, shard, coroutineContext = context) } - private suspend fun handle(event: MessageUpdate, shard: Int, kord: Kord): MessageUpdateEvent = with(event.message) { + private suspend fun handle( + event: MessageUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): MessageUpdateEvent = with(event.message) { val query = cache.query { idEq(MessageData::id, id) } val old = query.asFlow().map { Message(it, kord) }.singleOrNull() @@ -85,19 +100,29 @@ internal class MessageEventHandler( } } - MessageUpdateEvent(id, channelId, this, old, kord, shard) + MessageUpdateEvent(id, channelId, this, old, kord, shard, coroutineContext = context) } - private suspend fun handle(event: MessageDelete, shard: Int, kord: Kord): MessageDeleteEvent = with(event.message) { + private suspend fun handle( + event: MessageDelete, + shard: Int, + kord: Kord, + context: CoroutineContext + ): MessageDeleteEvent = with(event.message) { val query = cache.query { idEq(MessageData::id, id) } val removed = query.singleOrNull()?.let { Message(it, kord) } query.remove() - return MessageDeleteEvent(id, channelId, guildId.value, removed, kord, shard) + return MessageDeleteEvent(id, channelId, guildId.value, removed, kord, shard, coroutineContext = context) } - private suspend fun handle(event: MessageDeleteBulk, shard: Int, kord: Kord): MessageBulkDeleteEvent = + private suspend fun handle( + event: MessageDeleteBulk, + shard: Int, + kord: Kord, + context: CoroutineContext + ): MessageBulkDeleteEvent = with(event.messageBulk) { val query = cache.query { MessageData::id `in` ids } @@ -106,10 +131,23 @@ internal class MessageEventHandler( val ids = ids.asSequence().map { it }.toSet() - return MessageBulkDeleteEvent(ids, removed, channelId, guildId.value, kord, shard) + return MessageBulkDeleteEvent( + ids, + removed, + channelId, + guildId.value, + kord, + shard, + coroutineContext = context + ) } - private suspend fun handle(event: MessageReactionAdd, shard: Int, kord: Kord): ReactionAddEvent = + private suspend fun handle( + event: MessageReactionAdd, + shard: Int, + kord: Kord, + context: CoroutineContext + ): ReactionAddEvent = with(event.reaction) { /** * Reactions added will *always* have a name, the only case in which name is null is when a guild reaction @@ -151,11 +189,17 @@ internal class MessageEventHandler( guildId.value, reaction, kord, - shard + shard, + coroutineContext = context ) } - private suspend fun handle(event: MessageReactionRemove, shard: Int, kord: Kord): ReactionRemoveEvent = + private suspend fun handle( + event: MessageReactionRemove, + shard: Int, + kord: Kord, + context: CoroutineContext + ): ReactionRemoveEvent = with(event.reaction) { /** * Reactions removed will *sometimes* have a name, the only case in which name is null is when a guild reaction @@ -195,11 +239,17 @@ internal class MessageEventHandler( guildId.value, reaction, kord, - shard + shard, + coroutineContext = context ) } - private suspend fun handle(event: MessageReactionRemoveAll, shard: Int, kord: Kord): ReactionRemoveAllEvent = + private suspend fun handle( + event: MessageReactionRemoveAll, + shard: Int, + kord: Kord, + context: CoroutineContext + ): ReactionRemoveAllEvent = with(event.reactions) { cache.query { idEq(MessageData::id, messageId) } .update { it.copy(reactions = Optional.Missing()) } @@ -209,17 +259,23 @@ internal class MessageEventHandler( messageId, guildId.value, kord, - shard + shard, + coroutineContext = context ) } - private suspend fun handle(event: MessageReactionRemoveEmoji, shard: Int, kord: Kord): ReactionRemoveEmojiEvent = + private suspend fun handle( + event: MessageReactionRemoveEmoji, + shard: Int, + kord: Kord, + context: CoroutineContext + ): ReactionRemoveEmojiEvent = with(event.reaction) { cache.query { idEq(MessageData::id, messageId) } .update { it.copy(reactions = it.reactions.map { list -> list.filter { data -> data.emojiName != emoji.name } }) } val data = ReactionRemoveEmojiData.from(this) - return ReactionRemoveEmojiEvent(data, kord, shard) + return ReactionRemoveEmojiEvent(data, kord, shard, coroutineContext = context) } } diff --git a/core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt b/core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt index eadf176d3d3a..f3e012fc9127 100644 --- a/core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/ThreadEventHandler.kt @@ -13,43 +13,49 @@ import dev.kord.core.entity.channel.Channel import dev.kord.core.entity.channel.thread.* import dev.kord.core.event.channel.thread.* import dev.kord.gateway.* +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent class ThreadEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is ThreadCreate -> handle(event, shard, kord) - is ThreadUpdate -> handle(event, shard, kord) - is ThreadDelete -> handle(event, shard, kord) - is ThreadListSync -> handle(event, shard, kord) - is ThreadMemberUpdate -> handle(event, shard, kord) - is ThreadMembersUpdate -> handle(event, shard, kord) + override suspend fun handle( + event: Event, + shard: Int, + kord: Kord, + context: CoroutineContext + ): dev.kord.core.event.Event? = when (event) { + is ThreadCreate -> handle(event, shard, kord, context) + is ThreadUpdate -> handle(event, shard, kord, context) + is ThreadDelete -> handle(event, shard, kord, context) + is ThreadListSync -> handle(event, shard, kord, context) + is ThreadMemberUpdate -> handle(event, shard, kord, context) + is ThreadMembersUpdate -> handle(event, shard, kord, context) else -> null } - suspend fun handle(event: ThreadCreate, shard: Int, kord: Kord): CoreEvent? { + suspend fun handle(event: ThreadCreate, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { val channelData = event.channel.toData() cache.put(channelData) val coreEvent = when (val channel = Channel.from(channelData, kord)) { - is NewsChannelThread -> NewsChannelThreadCreateEvent(channel, shard) - is TextChannelThread -> TextChannelThreadCreateEvent(channel, shard) - is ThreadChannel -> UnknownChannelThreadCreateEvent(channel, shard) + is NewsChannelThread -> NewsChannelThreadCreateEvent(channel, shard, context) + is TextChannelThread -> TextChannelThreadCreateEvent(channel, shard, context) + is ThreadChannel -> UnknownChannelThreadCreateEvent(channel, shard, context) else -> return null } return coreEvent } - suspend fun handle(event: ThreadUpdate, shard: Int, kord: Kord): CoreEvent? { + suspend fun handle(event: ThreadUpdate, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { val channelData = event.channel.toData() cache.put(channelData) val coreEvent = when (val channel = Channel.from(channelData, kord)) { - is NewsChannelThread -> NewsChannelThreadUpdateEvent(channel, shard) - is TextChannelThread -> TextChannelThreadUpdateEvent(channel, shard) - is ThreadChannel -> UnknownChannelThreadUpdateEvent(channel, shard) + is NewsChannelThread -> NewsChannelThreadUpdateEvent(channel, shard, context) + is TextChannelThread -> TextChannelThreadUpdateEvent(channel, shard, context) + is ThreadChannel -> UnknownChannelThreadUpdateEvent(channel, shard, context) else -> return null } @@ -57,7 +63,7 @@ class ThreadEventHandler( } - suspend fun handle(event: ThreadDelete, shard: Int, kord: Kord): CoreEvent? { + suspend fun handle(event: ThreadDelete, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { val channelData = event.channel.toData() val cachedData = cache.query { idEq(ChannelData::id, channelData.id) }.singleOrNull() @@ -65,17 +71,22 @@ class ThreadEventHandler( val channel = DeletedThreadChannel(channelData, kord) val old = cachedData?.let { Channel.from(cachedData, kord) } val coreEvent = when (channel.type) { - is ChannelType.PublicNewsThread -> NewsChannelThreadDeleteEvent(channel, old as? NewsChannelThread, shard) + is ChannelType.PublicNewsThread -> NewsChannelThreadDeleteEvent( + channel, + old as? NewsChannelThread, + shard, + context + ) is ChannelType.PrivateThread, - is ChannelType.GuildText -> TextChannelThreadDeleteEvent(channel, old as? TextChannelThread, shard) - else -> UnknownChannelThreadDeleteEvent(channel, old as? ThreadChannel, shard) + is ChannelType.GuildText -> TextChannelThreadDeleteEvent(channel, old as? TextChannelThread, shard, context) + else -> UnknownChannelThreadDeleteEvent(channel, old as? ThreadChannel, shard, context) } cache.remove { idEq(ChannelData::id, channel.id) } return coreEvent } - suspend fun handle(event: ThreadListSync, shard: Int, kord: Kord): CoreEvent? { + suspend fun handle(event: ThreadListSync, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { val data = ThreadListSyncData.from(event) data.threads.forEach { thread -> @@ -85,16 +96,16 @@ class ThreadEventHandler( cache.put(member) } - return ThreadListSyncEvent(data, kord, shard) + return ThreadListSyncEvent(data, kord, shard, coroutineContext = context) } - fun handle(event: ThreadMemberUpdate, shard: Int, kord: Kord): CoreEvent? { + fun handle(event: ThreadMemberUpdate, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { val data = ThreadMemberData.from(event.member) val member = ThreadMember(data, kord) - return ThreadMemberUpdateEvent(member, kord, shard) + return ThreadMemberUpdateEvent(member, kord, shard, context) } - suspend fun handle(event: ThreadMembersUpdate, shard: Int, kord: Kord): CoreEvent? { + suspend fun handle(event: ThreadMembersUpdate, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? { val data = ThreadMembersUpdateEventData.from(event) for (removedMemberId in data.removedMemberIds.orEmpty()) { cache.remove { @@ -105,6 +116,6 @@ class ThreadEventHandler( for (addedMember in data.addedMembers.orEmpty()) { cache.put(addedMember) } - return ThreadMembersUpdateEvent(data, kord, shard) + return ThreadMembersUpdateEvent(data, kord, shard, context) } } diff --git a/core/src/main/kotlin/gateway/handler/UserEventHandler.kt b/core/src/main/kotlin/gateway/handler/UserEventHandler.kt index 19888dcfb775..f9a42009149f 100644 --- a/core/src/main/kotlin/gateway/handler/UserEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/UserEventHandler.kt @@ -12,6 +12,7 @@ import dev.kord.gateway.Event import dev.kord.gateway.UserUpdate import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.singleOrNull +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") @@ -19,12 +20,12 @@ internal class UserEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is UserUpdate -> handle(event, shard, kord) + override suspend fun handle(event: Event, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? = when (event) { + is UserUpdate -> handle(event, shard, kord, context) else -> null } - private suspend fun handle(event: UserUpdate, shard: Int, kord: Kord): UserUpdateEvent { + private suspend fun handle(event: UserUpdate, shard: Int, kord: Kord, context: CoroutineContext): UserUpdateEvent { val data = UserData.from(event.user) val old = cache.query { idEq(UserData::id, data.id) } @@ -33,7 +34,7 @@ internal class UserEventHandler( cache.put(data) val new = User(data, kord) - return UserUpdateEvent(old, new, shard) + return UserUpdateEvent(old, new, shard, context) } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/VoiceEventHandler.kt b/core/src/main/kotlin/gateway/handler/VoiceEventHandler.kt index 7c7f701be67c..c180e43169e6 100644 --- a/core/src/main/kotlin/gateway/handler/VoiceEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/VoiceEventHandler.kt @@ -14,6 +14,7 @@ import dev.kord.gateway.VoiceServerUpdate import dev.kord.gateway.VoiceStateUpdate import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.singleOrNull +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") @@ -21,13 +22,19 @@ internal class VoiceEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is VoiceStateUpdate -> handle(event, shard, kord) - is VoiceServerUpdate -> handle(event, shard, kord) - else -> null - } + override suspend fun handle(event: Event, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? = + when (event) { + is VoiceStateUpdate -> handle(event, shard, kord, context) + is VoiceServerUpdate -> handle(event, shard, kord, context) + else -> null + } - private suspend fun handle(event: VoiceStateUpdate, shard: Int, kord: Kord): VoiceStateUpdateEvent { + private suspend fun handle( + event: VoiceStateUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): VoiceStateUpdateEvent { val data = VoiceStateData.from(event.voiceState.guildId.value!!, event.voiceState) val old = cache.query { idEq(VoiceStateData::id, data.id) } @@ -36,12 +43,17 @@ internal class VoiceEventHandler( cache.put(data) val new = VoiceState(data, kord) - return VoiceStateUpdateEvent(old, new, shard) + return VoiceStateUpdateEvent(old, new, shard, context) } - private fun handle(event: VoiceServerUpdate, shard: Int, kord: Kord): VoiceServerUpdateEvent = + private fun handle( + event: VoiceServerUpdate, + shard: Int, + kord: Kord, + context: CoroutineContext + ): VoiceServerUpdateEvent = with(event.voiceServerUpdateData) { - return VoiceServerUpdateEvent(token, guildId, endpoint, kord, shard) + return VoiceServerUpdateEvent(token, guildId, endpoint, kord, shard, coroutineContext = context) } } \ No newline at end of file diff --git a/core/src/main/kotlin/gateway/handler/WebhookEventHandler.kt b/core/src/main/kotlin/gateway/handler/WebhookEventHandler.kt index 9c040dbdb623..c2b0e04b3980 100644 --- a/core/src/main/kotlin/gateway/handler/WebhookEventHandler.kt +++ b/core/src/main/kotlin/gateway/handler/WebhookEventHandler.kt @@ -5,6 +5,7 @@ import dev.kord.core.Kord import dev.kord.core.event.guild.WebhookUpdateEvent import dev.kord.gateway.Event import dev.kord.gateway.WebhooksUpdate +import kotlin.coroutines.CoroutineContext import dev.kord.core.event.Event as CoreEvent @Suppress("EXPERIMENTAL_API_USAGE") @@ -12,14 +13,15 @@ internal class WebhookEventHandler( cache: DataCache ) : BaseGatewayEventHandler(cache) { - override suspend fun handle(event: Event, shard: Int, kord: Kord): CoreEvent? = when (event) { - is WebhooksUpdate -> handle(event, shard, kord) - else -> null - } + override suspend fun handle(event: Event, shard: Int, kord: Kord, context: CoroutineContext): CoreEvent? = + when (event) { + is WebhooksUpdate -> handle(event, shard, kord, context) + else -> null + } - private fun handle(event: WebhooksUpdate, shard: Int, kord: Kord): WebhookUpdateEvent = + private fun handle(event: WebhooksUpdate, shard: Int, kord: Kord, context: CoroutineContext): WebhookUpdateEvent = with(event.webhooksUpdateData) { - return WebhookUpdateEvent(guildId, channelId, kord, shard) + return WebhookUpdateEvent(guildId, channelId, kord, shard, coroutineContext = context) } } \ No newline at end of file From a385f4556dcb42b926e7b1ea6b4885d0e7faa9eb Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Sat, 25 Sep 2021 02:11:09 +0200 Subject: [PATCH 12/13] Revert shard event to data class --- core/src/main/kotlin/gateway/MasterGateway.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/kotlin/gateway/MasterGateway.kt b/core/src/main/kotlin/gateway/MasterGateway.kt index 5c8b76d13dff..a20ca4e636de 100644 --- a/core/src/main/kotlin/gateway/MasterGateway.kt +++ b/core/src/main/kotlin/gateway/MasterGateway.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.launch import kotlin.time.Duration -open class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) +data class ShardEvent(val event: Event, val gateway: Gateway, val shard: Int) interface MasterGateway { val gateways: Map From 8f5211445fcb31b97d63049abb1a53a6bf15a6b9 Mon Sep 17 00:00:00 2001 From: ByteAlex Date: Sat, 25 Sep 2021 02:16:47 +0200 Subject: [PATCH 13/13] Move start method into Kord --- core/src/main/kotlin/Kord.kt | 8 +++++++- .../handler/DefaultGatewayEventInterceptor.kt | 2 +- .../gateway/handler/GatewayEventInterceptor.kt | 12 ++---------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/core/src/main/kotlin/Kord.kt b/core/src/main/kotlin/Kord.kt index 8e601fde3e86..2fe4a3872de1 100644 --- a/core/src/main/kotlin/Kord.kt +++ b/core/src/main/kotlin/Kord.kt @@ -109,7 +109,13 @@ class Kord( get() = defaultSupplier.guilds init { - launch { interceptor.start(gateway.events, eventFlow, this@Kord) } + gateway.events + .buffer(kotlinx.coroutines.channels.Channel.UNLIMITED) + .onEach { event -> + val coreEvent = interceptor.handle(event, this) + coreEvent?.let { eventFlow.emit(it) } + } + .launchIn(this) } /** diff --git a/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt b/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt index acb218087e24..09fa5a5d17b0 100644 --- a/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt +++ b/core/src/main/kotlin/gateway/handler/DefaultGatewayEventInterceptor.kt @@ -16,7 +16,7 @@ private val logger = KotlinLogging.logger { } class DefaultGatewayEventInterceptor( cache: DataCache, private val eventScope: ((ShardEvent, Kord) -> CoroutineContext)? = null -) : GatewayEventInterceptor() { +) : GatewayEventInterceptor { private val listeners = listOf( MessageEventHandler(cache), diff --git a/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt b/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt index cc1dcb71d89a..3840243ed0e4 100644 --- a/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt +++ b/core/src/main/kotlin/gateway/handler/GatewayEventInterceptor.kt @@ -7,15 +7,7 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.* import dev.kord.core.event.Event as CoreEvent -abstract class GatewayEventInterceptor { +interface GatewayEventInterceptor { - suspend fun start(events: Flow, coreEvents: MutableSharedFlow, kord: Kord): Job = events - .buffer(Channel.UNLIMITED) - .onEach { event -> - val coreEvent = handle(event, kord) - coreEvent?.let { coreEvents.emit(it) } - } - .launchIn(kord) - - abstract suspend fun handle(event: ShardEvent, kord: Kord): CoreEvent? + suspend fun handle(event: ShardEvent, kord: Kord): CoreEvent? } \ No newline at end of file