Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Lazy Intents #409

Merged
merged 7 commits into from
Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions core/src/main/kotlin/ClientResources.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package dev.kord.core

import dev.kord.common.entity.Snowflake
import dev.kord.core.builder.kord.Shards
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.gateway.Intents
import dev.kord.gateway.builder.Shards
import io.ktor.client.*

class ClientResources(
Expand All @@ -12,9 +12,8 @@ class ClientResources(
val shards: Shards,
val httpClient: HttpClient,
val defaultStrategy: EntitySupplyStrategy<*>,
val intents: Intents,
) {
override fun toString(): String {
return "ClientResources(shards=$shards, httpClient=$httpClient, defaultStrategy=$defaultStrategy, intents=$intents)"
return "ClientResources(shards=$shards, httpClient=$httpClient, defaultStrategy=$defaultStrategy)"
}
}
11 changes: 7 additions & 4 deletions core/src/main/kotlin/Kord.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ 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.LoginBuilder
import dev.kord.gateway.builder.PresenceBuilder
import dev.kord.gateway.builder.Shards
import dev.kord.rest.builder.guild.GuildCreateBuilder
import dev.kord.rest.builder.interaction.*
import dev.kord.rest.builder.user.CurrentUserModifyBuilder
Expand Down Expand Up @@ -122,15 +124,16 @@ class Kord(
* Logs in to the configured [Gateways][Gateway]. Suspends until [logout] or [shutdown] is called.
*/
@OptIn(ExperimentalContracts::class)
suspend inline fun login(builder: PresenceBuilder.() -> Unit = { status = PresenceStatus.Online }) {
suspend inline fun login(builder: LoginBuilder.() -> Unit = {}) {
contract {
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
}
val loginBuilder = LoginBuilder().apply(builder)
gateway.start(resources.token) {
shard = DiscordShard(0, resources.shards.totalShards)
presence(builder)
intents = resources.intents
name = "kord"
presence(loginBuilder.presence)
intents = loginBuilder.intents
name = loginBuilder.name
}
}

Expand Down
12 changes: 2 additions & 10 deletions core/src/main/kotlin/builder/kord/KordBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import dev.kord.core.gateway.DefaultMasterGateway
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.gateway.DefaultGateway
import dev.kord.gateway.Gateway
import dev.kord.gateway.Intents
import dev.kord.gateway.builder.Shards
import dev.kord.gateway.retry.LinearRetry
import dev.kord.gateway.retry.Retry
import dev.kord.rest.json.response.BotGatewayResponse
Expand All @@ -42,7 +42,6 @@ import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.time.Duration
import kotlin.time.seconds

operator fun DefaultGateway.Companion.invoke(
resources: ClientResources,
Expand All @@ -59,7 +58,6 @@ operator fun DefaultGateway.Companion.invoke(

private val logger = KotlinLogging.logger { }

data class Shards(val totalShards: Int, val indices: Iterable<Int> = 0 until totalShards)

class KordBuilder(val token: String) {
private var shardsBuilder: (recommended: Int) -> Shards = { Shards(it) }
Expand Down Expand Up @@ -111,12 +109,6 @@ class KordBuilder(val token: String) {

var applicationId: Snowflake? = null

/**
* The enabled gateway intents, setting intents to null will disable the feature.
*/
var intents: Intents = Intents.nonPrivileged


/**
* Configures the shards this client will connect to, by default `0 until recommended`.
* This can be used to break up to client into multiple processes.
Expand Down Expand Up @@ -231,7 +223,7 @@ class KordBuilder(val token: String) {
}
}

val resources = ClientResources(token,applicationId ?: getBotIdFromToken(token), shardsInfo, client, defaultStrategy, intents)
val resources = ClientResources(token,applicationId ?: getBotIdFromToken(token), shardsInfo, client, defaultStrategy)
val rest = RestClient(handlerBuilder(resources))
val cache = KordCacheBuilder().apply { cacheBuilder(resources) }.build()
cache.registerKordData()
Expand Down
8 changes: 2 additions & 6 deletions core/src/main/kotlin/builder/kord/KordRestOnlyBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,18 @@ import dev.kord.common.annotation.KordExperimental
import dev.kord.common.entity.Snowflake
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.DefaultMasterGateway
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.gateway.Gateway
import dev.kord.gateway.Intents
import dev.kord.gateway.builder.Shards
import dev.kord.rest.ratelimit.ExclusionRequestRateLimiter
import dev.kord.rest.request.KtorRequestHandler
import dev.kord.rest.request.RequestHandler
import dev.kord.rest.service.RestClient
import io.ktor.client.HttpClient
import io.ktor.client.*
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableSharedFlow

@KordExperimental
Expand Down Expand Up @@ -67,7 +64,6 @@ class KordRestOnlyBuilder(val token: String) {
Shards(0),
client,
EntitySupplyStrategy.rest,
Intents.none
)
val rest = RestClient(handlerBuilder(resources))
val selfId = getBotIdFromToken(token)
Expand Down
4 changes: 2 additions & 2 deletions core/src/test/kotlin/live/AbstractLiveEntityTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import dev.kord.common.annotation.KordPreview
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.DefaultMasterGateway
import dev.kord.core.live.AbstractLiveKordEntity
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.gateway.*
import dev.kord.gateway.builder.Shards
import dev.kord.rest.request.KtorRequestHandler
import dev.kord.rest.service.RestClient
import equality.randomId
Expand Down Expand Up @@ -103,7 +103,7 @@ abstract class AbstractLiveEntityTest<LIVE : AbstractLiveKordEntity> {
protected open fun createKord(): Kord {
gateway = GatewayMock()
return Kord(
resources = ClientResources("token", Snowflake(0u), Shards(1), HttpClient(), EntitySupplyStrategy.cache, Intents.none),
resources = ClientResources("token", Snowflake(0u), Shards(1), HttpClient(), EntitySupplyStrategy.cache),
cache = DataCache.none(),
DefaultMasterGateway(mapOf(0 to gateway)),
RestClient(KtorRequestHandler(token = "token")),
Expand Down
4 changes: 2 additions & 2 deletions core/src/test/kotlin/performance/KordEventDropTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import dev.kord.cache.api.DataCache
import dev.kord.common.entity.*
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.DefaultMasterGateway
import dev.kord.core.on
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.gateway.*
import dev.kord.gateway.builder.Shards
import dev.kord.rest.request.KtorRequestHandler
import dev.kord.rest.service.RestClient
import io.ktor.client.*
Expand Down Expand Up @@ -47,7 +47,7 @@ class KordEventDropTest {
}

val kord = Kord(
resources = ClientResources("token", Snowflake(0u), Shards(1), HttpClient(), EntitySupplyStrategy.cache, Intents.none),
resources = ClientResources("token", Snowflake(0u), Shards(1), HttpClient(), EntitySupplyStrategy.cache),
cache = DataCache.none(),
DefaultMasterGateway(mapOf(0 to SpammyGateway)),
RestClient(KtorRequestHandler("token", clock = Clock.System)),
Expand Down
13 changes: 9 additions & 4 deletions core/src/test/kotlin/regression/CacheMissRegression.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import dev.kord.common.entity.ChannelType
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.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.DefaultMasterGateway
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.gateway.*
import dev.kord.gateway.Command
import dev.kord.gateway.Event
import dev.kord.gateway.Gateway
import dev.kord.gateway.GatewayConfiguration
import dev.kord.gateway.builder.Shards
import dev.kord.rest.request.JsonRequest
import dev.kord.rest.request.MultipartRequest
import dev.kord.rest.request.Request
Expand All @@ -29,7 +32,10 @@ import io.ktor.http.*
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runBlockingTest
import kotlinx.serialization.SerializationStrategy
Expand Down Expand Up @@ -126,7 +132,6 @@ class CacheMissingRegressions {
Shards(1),
null.configure(token),
EntitySupplyStrategy.cacheWithRestFallback,
Intents.nonPrivileged
)
kord = Kord(
resources,
Expand Down
4 changes: 2 additions & 2 deletions core/src/test/kotlin/supplier/CacheEntitySupplierTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import dev.kord.common.annotation.KordUnsafe
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.cache.KordCacheBuilder
import dev.kord.core.gateway.DefaultMasterGateway
import dev.kord.gateway.Gateway
import dev.kord.gateway.Intents
import dev.kord.gateway.PrivilegedIntent
import dev.kord.gateway.builder.Shards
import dev.kord.rest.request.KtorRequestHandler
import dev.kord.rest.service.RestClient
import io.ktor.client.*
Expand All @@ -26,7 +26,7 @@ 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),
ClientResources("", Snowflake(0u), Shards(0), HttpClient(), EntitySupplyStrategy.cache),
KordCacheBuilder().build(),
DefaultMasterGateway(mapOf(0 to Gateway.none())),
RestClient(KtorRequestHandler("")),
Expand Down
21 changes: 21 additions & 0 deletions gateway/src/main/kotlin/builder/LoginBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dev.kord.gateway.builder

import dev.kord.common.entity.PresenceStatus
import dev.kord.gateway.Intents
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

data class Shards(val totalShards: Int, val indices: Iterable<Int> = 0 until totalShards)

class LoginBuilder {
var presence: PresenceBuilder.() -> Unit = { status = PresenceStatus.Online }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for this being a lambda? Why not keep a presence builder locally instead?

var intents: Intents = Intents.nonPrivileged
var name: String = "Kord"

@OptIn(ExperimentalContracts::class)
fun presence(builder: PresenceBuilder.() -> Unit) {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
this.presence = builder
}
}