commonMain.live.LiveKordEntity.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kord-core Show documentation
Show all versions of kord-core Show documentation
Idiomatic Kotlin Wrapper for The Discord API
package dev.kord.core.live
import dev.kord.common.annotation.KordPreview
import dev.kord.core.Kord
import dev.kord.core.entity.KordEntity
import dev.kord.core.event.Event
import dev.kord.core.event.message.MessageUpdateEvent
import dev.kord.core.event.message.ReactionAddEvent
import dev.kord.core.logCaughtThrowable
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.*
import kotlin.coroutines.CoroutineContext
/**
* A Discord entity that only emits events *related* to this entity.
*
* For example, a [LiveMessage] will only emit [MessageUpdateEvents][MessageUpdateEvent] of that message, and only emit
* [reactions][ReactionAddEvent] to that message.
*/
@KordPreview
public interface LiveKordEntity : KordEntity, CoroutineScope {
public val events: Flow
public fun shutDown(cause: CancellationException = CancellationException("The live entity is shut down", null))
}
@KordPreview
public abstract class AbstractLiveKordEntity(
final override val kord: Kord,
private val coroutineScope: CoroutineScope = kord + SupervisorJob(kord.coroutineContext.job)
) : LiveKordEntity, CoroutineScope {
final override val coroutineContext: CoroutineContext
get() = coroutineScope.coroutineContext
@Suppress("LeakingThis") // only used as CoroutineScope; coroutineContext can not be overridden in subclasses
final override val events: SharedFlow =
kord.events.filter { filter(it) }.onEach { update(it) }.shareIn(this, SharingStarted.Eagerly)
protected abstract fun filter(event: Event): Boolean
protected abstract fun update(event: Event)
override fun shutDown(cause: CancellationException): Unit = cancel(cause)
}
/**
* Convenience method that will invoke the [consumer] on every event [T], the consumer is launched in the given [scope]
* or [Kord] by default and will not propagate any exceptions.
*/
@KordPreview
public inline fun LiveKordEntity.on(
scope: CoroutineScope = this,
noinline consumer: suspend (T) -> Unit
): Job =
events.buffer(Channel.UNLIMITED).filterIsInstance().onEach {
runCatching { consumer(it) }.onFailure(::logCaughtThrowable)
}.catch { logCaughtThrowable(it) }.launchIn(scope)