From ab37ea3d78afd2c4b18ff148324adcea73fa6e74 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 17:44:21 +0200 Subject: [PATCH 01/83] Add native targets to KMP modules - Migrate test-kit to use kotlinx-resources --- build.gradle.kts | 7 ++- buildSrc/build.gradle.kts | 1 + .../kord-multiplatform-module.gradle.kts | 1 + .../main/kotlin/kord-native-module.gradle.kts | 29 +++++++++++ common/build.gradle.kts | 26 ++++++++++ common/src/appleMain/kotlin/HttpEngine.kt | 9 ++++ common/src/linuxMain/kotlin/HttpEngine.kt | 9 ++++ common/src/mingwMain/kotlin/HttpEngine.kt | 9 ++++ core/build.gradle.kts | 1 + core/src/nativeMain/kotlin/KordBuilder.kt | 3 ++ gateway/build.gradle.kts | 1 + .../src/nativeMain/kotlin/DefaultGateway.kt | 9 ++++ gateway/src/nativeMain/kotlin/Inflater.kt | 52 +++++++++++++++++++ gradle.properties | 4 ++ gradle/libs.versions.toml | 12 +++-- ksp-annotations/build.gradle.kts | 1 + rest/build.gradle.kts | 1 + .../nativeMain/kotlin/RecoveredStackTrace.kt | 4 ++ .../dev/kord/rest/request/StackTrace.kt | 23 ++++++++ test-kit/build.gradle.kts | 1 + test-kit/src/commonMain/kotlin/Annotations.kt | 5 ++ test-kit/src/commonMain/kotlin/Platform.kt | 11 +++- test-kit/src/jsMain/kotlin/Platform.kt | 14 ++--- .../src/nativeMain/kotlin/IgnoreOnNative.kt | 5 ++ test-kit/src/nativeMain/kotlin/Platform.kt | 23 ++++++++ 25 files changed, 247 insertions(+), 14 deletions(-) create mode 100644 buildSrc/src/main/kotlin/kord-native-module.gradle.kts create mode 100644 common/src/appleMain/kotlin/HttpEngine.kt create mode 100644 common/src/linuxMain/kotlin/HttpEngine.kt create mode 100644 common/src/mingwMain/kotlin/HttpEngine.kt create mode 100644 core/src/nativeMain/kotlin/KordBuilder.kt create mode 100644 gateway/src/nativeMain/kotlin/DefaultGateway.kt create mode 100644 gateway/src/nativeMain/kotlin/Inflater.kt create mode 100644 rest/src/nativeMain/kotlin/RecoveredStackTrace.kt create mode 100644 rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt create mode 100644 test-kit/src/nativeMain/kotlin/IgnoreOnNative.kt create mode 100644 test-kit/src/nativeMain/kotlin/Platform.kt diff --git a/build.gradle.kts b/build.gradle.kts index 0ad64bff26f..be333e43178 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,8 +2,11 @@ plugins { org.jetbrains.dokka // for dokkaHtmlMultiModule task } -repositories { - mavenCentral() +allprojects { + repositories { + mavenCentral() + maven("https://oss.sonatype.org/content/repositories/snapshots/") + } } group = Library.group diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 260920e5258..350ddece2c0 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -3,6 +3,7 @@ plugins { } repositories { + gradlePluginPortal() mavenCentral() } diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 8e9837e167c..48f03d119b4 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -8,6 +8,7 @@ plugins { `kotlinx-atomicfu` org.jetbrains.kotlinx.`binary-compatibility-validator` com.google.devtools.ksp + com.goncalossilva.resources } repositories { diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts new file mode 100644 index 00000000000..3aabb90a53d --- /dev/null +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -0,0 +1,29 @@ +plugins { + org.jetbrains.kotlin.multiplatform +} + +kotlin { + targetHierarchy.default() + + linuxX64() + // Waiting for Ktor + // https://youtrack.jetbrains.com/issue/KTOR-872 + //linuxArm64() + + mingwX64() + + macosArm64() + macosX64() + + iosArm64() + iosX64() +// iosSimulatorArm64() + + watchosX64() + watchosArm64() +// watchosSimulatorArm64() + + tvosX64() + tvosArm64() +// tvosSimulatorArm64() +} diff --git a/common/build.gradle.kts b/common/build.gradle.kts index fcc2c109d11..ed7e7dbbbc6 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-multiplatform-module` + `kord-native-module` `kord-publishing` alias(libs.plugins.buildconfig) } @@ -37,6 +38,31 @@ kotlin { implementation(projects.kspAnnotations) } } + + nativeMain { + dependencies { + // Native does not have compileOnly + implementation(projects.kspAnnotations) + } + } + + mingwMain { + dependencies { + api(libs.ktor.client.winhttp) + } + } + + appleMain { + dependencies { + api(libs.ktor.client.darwin) + } + } + + linuxMain { + dependencies { + api(libs.ktor.client.curl) + } + } } } diff --git a/common/src/appleMain/kotlin/HttpEngine.kt b/common/src/appleMain/kotlin/HttpEngine.kt new file mode 100644 index 00000000000..d43679d2357 --- /dev/null +++ b/common/src/appleMain/kotlin/HttpEngine.kt @@ -0,0 +1,9 @@ +package dev.kord.common.http + +import dev.kord.common.annotation.KordInternal +import io.ktor.client.engine.* +import io.ktor.client.engine.darwin.* + +/** @suppress */ +@KordInternal +public actual object HttpEngine: HttpClientEngineFactory by Darwin diff --git a/common/src/linuxMain/kotlin/HttpEngine.kt b/common/src/linuxMain/kotlin/HttpEngine.kt new file mode 100644 index 00000000000..f38a8a9aba8 --- /dev/null +++ b/common/src/linuxMain/kotlin/HttpEngine.kt @@ -0,0 +1,9 @@ +package dev.kord.common.http + +import dev.kord.common.annotation.KordInternal +import io.ktor.client.engine.* +import io.ktor.client.engine.curl.* + +/** @suppress */ +@KordInternal +public actual object HttpEngine : HttpClientEngineFactory by Curl diff --git a/common/src/mingwMain/kotlin/HttpEngine.kt b/common/src/mingwMain/kotlin/HttpEngine.kt new file mode 100644 index 00000000000..eb8489d3bed --- /dev/null +++ b/common/src/mingwMain/kotlin/HttpEngine.kt @@ -0,0 +1,9 @@ +package dev.kord.common.http + +import dev.kord.common.annotation.KordInternal +import io.ktor.client.engine.* +import io.ktor.client.engine.winhttp.* + +/** @suppress */ +@KordInternal +public actual object HttpEngine : HttpClientEngineFactory by WinHttp diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 8cbdb531e50..d7ad3517172 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 plugins { `kord-multiplatform-module` + `kord-native-module` `kord-publishing` } diff --git a/core/src/nativeMain/kotlin/KordBuilder.kt b/core/src/nativeMain/kotlin/KordBuilder.kt new file mode 100644 index 00000000000..a3d196befb4 --- /dev/null +++ b/core/src/nativeMain/kotlin/KordBuilder.kt @@ -0,0 +1,3 @@ +package dev.kord.core.builder.kord + +public actual class KordBuilder actual constructor(token: String) : BaseKordBuilder(token) diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index c1479ace37b..8732cf3f179 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-multiplatform-module` + `kord-native-module` `kord-publishing` } diff --git a/gateway/src/nativeMain/kotlin/DefaultGateway.kt b/gateway/src/nativeMain/kotlin/DefaultGateway.kt new file mode 100644 index 00000000000..9a563091de9 --- /dev/null +++ b/gateway/src/nativeMain/kotlin/DefaultGateway.kt @@ -0,0 +1,9 @@ +package dev.kord.gateway + +import kotlin.experimental.ExperimentalNativeApi + +// TODO: Timeout +internal actual fun Throwable.isTimeout() = false + +@OptIn(ExperimentalNativeApi::class) +internal actual val os: String get() = Platform.osFamily.name diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt new file mode 100644 index 00000000000..4fbca05c13c --- /dev/null +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -0,0 +1,52 @@ +package dev.kord.gateway + +import io.ktor.utils.io.core.* +import io.ktor.websocket.* +import kotlinx.cinterop.* +import platform.zlib.* + +private const val MAX_WBITS = 15 // Maximum window size in bits +private const val CHUNK_SIZE = 256 * 1000 + +@OptIn(ExperimentalForeignApi::class) +internal actual class Inflater : Closeable { + private val zStream = nativeHeap.alloc().apply { + val initResponse = inflateInit2(ptr, MAX_WBITS) + if (initResponse != Z_OK) { + nativeHeap.free(this) + throw IllegalStateException("Could not initialize zlib: $initResponse") + } + } + + actual fun Frame.inflateData(): String { + val compressedData = data + var out = ByteArray(0) + memScoped { + val uncompressedDataSize = CHUNK_SIZE // allocate enough space for the uncompressed data + val uncompressedData = allocArray(uncompressedDataSize) + zStream.apply { + next_in = compressedData.refTo(0).getPointer(memScope).reinterpret() + avail_in = compressedData.size.convert() + } + + do { + zStream.apply { + next_out = uncompressedData + avail_out = uncompressedDataSize.convert() + } + val resultCode = inflate(zStream.ptr, Z_NO_FLUSH) + if (resultCode != Z_OK && resultCode != Z_STREAM_END) { + throw IllegalStateException("An error occurred during decompression of frame: $resultCode") + } + out += uncompressedData.readBytes(uncompressedDataSize - zStream.avail_out.toInt()) + } while (zStream.avail_out == 0u) + } + + return out.decodeToString() + } + + override fun close() { + inflateEnd(zStream.ptr) + nativeHeap.free(zStream) + } +} diff --git a/gradle.properties b/gradle.properties index afdbf760d9d..171df0a30e0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,3 +11,7 @@ kotlin.code.style=official kotlinx.atomicfu.enableJvmIrTransformation=true kotlinx.atomicfu.enableJsIrTransformation=true kotlinx.atomicfu.enableNativeIrTransformations=true + +# We are aware of these issues and their symptoms don't affect us +kotlin.native.ignoreIncorrectDependencies=true +kotlin.native.ignoreDisabledTargets=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 17b77358e1c..53ae6a737aa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,8 @@ kotlinx-serialization = "1.6.2" # https://github.com/Kotlin/kotlinx.serializatio kotlinx-datetime = "0.5.0" # https://github.com/Kotlin/kotlinx-datetime kotlin-logging = "6.0.1" # https://github.com/oshai/kotlin-logging kotlin-logging-old = "3.0.5" # TODO remove after dependency is removed in rest, gateway, voice and core -kord-cache = "0.4.0" # https://github.com/kordlib/cache +# This is the specific release supporting native, until we setup CI +kord-cache = "0.5.x-20230411.160140-1" # https://github.com/kordlib/cache # implementation dependencies kotlin-node = "18.16.12-pre.619" # https://github.com/JetBrains/kotlin-wrappers @@ -43,6 +44,9 @@ ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negoti ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" } +ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor" } +ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" } +ktor-client-curl = { module = "io.ktor:ktor-client-curl", version.ref = "ktor" } ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" } ktor-client-websockets = { module = "io.ktor:ktor-client-websockets", version.ref = "ktor" } ktor-client-mock = { module = "io.ktor:ktor-client-mock", version.ref = "ktor" } @@ -78,6 +82,7 @@ kotlin-test-junit5 = { module = "org.jetbrains.kotlin:kotlin-test-junit5", versi junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit5" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" } +kotlinx-resources = { module = "com.goncalossilva:resources", version.ref = "kotlinx-resources" } # actually plugins, not libraries, but used is 'buildSrc/build.gradle.kts' as implementation dependencies: # https://docs.gradle.org/current/userguide/custom_plugins.html#applying_external_plugins_in_precompiled_script_plugins @@ -87,13 +92,13 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } - +kordx-resources-plugin = { module = "com.goncalossilva:resources-plugin", version.ref = "kotlinx-resources" } [bundles] ktor-client-serialization = ["ktor-client-content-negotiation", "ktor-serialization-kotlinx-json"] -test-common = ["kotlin-test-annotations-common", "kotlin-test", "kotlinx-coroutines-test"] +test-common = ["kotlin-test-annotations-common", "kotlin-test", "kotlinx-coroutines-test", "kotlinx-resources"] test-js = ["kotlin-test-js", "kotlin-node"] test-jvm = ["kotlin-test-junit5", "junit-jupiter-engine", "slf4j-simple"] @@ -104,6 +109,7 @@ pluginsForBuildSrc = [ "atomicfu-plugin", "binary-compatibility-validator-plugin", "ksp-plugin", + "kordx-resources-plugin" ] diff --git a/ksp-annotations/build.gradle.kts b/ksp-annotations/build.gradle.kts index 0c68a988730..e4fe6b72e20 100644 --- a/ksp-annotations/build.gradle.kts +++ b/ksp-annotations/build.gradle.kts @@ -2,6 +2,7 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask plugins { `kord-internal-multiplatform-module` + `kord-native-module` // workaround for https://youtrack.jetbrains.com/issue/KT-43500 (not intended to be published) org.jetbrains.dokka diff --git a/rest/build.gradle.kts b/rest/build.gradle.kts index 1e96bd4847c..af2d4e4c182 100644 --- a/rest/build.gradle.kts +++ b/rest/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-multiplatform-module` + `kord-native-module` `kord-publishing` } diff --git a/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt b/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt new file mode 100644 index 00000000000..091fca9aadd --- /dev/null +++ b/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt @@ -0,0 +1,4 @@ +package dev.kord.rest.request + +// You cannot really modify stack traces in Native :( +internal actual fun RecoveredStackTrace.sanitizeStackTrace() = Unit diff --git a/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt b/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt new file mode 100644 index 00000000000..41e0a08d13a --- /dev/null +++ b/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt @@ -0,0 +1,23 @@ +package dev.kord.rest.request + +import kotlin.test.assertEquals + +actual typealias StackTraceElement = String + +//kotlin.Exception +//at 0 ??? 7ff68473da75 kfun:kotlin.Throwable#(kotlin.String?){} + 117 +//at 1 ??? 7ff684f9ee89 kfun:dev.kord.rest.request.RecoveredStackTrace#(){} + 89 +//at 2 ??? 7ff684f9e939 kfun:dev.kord.rest.request.StackTraceRecoveringKtorRequestHandler.$handleCOROUTINE$23#invokeSuspend(kotlin.Result){}kotlin.Any? + 681 +//at 3 ??? 7ff684f9ed3c kfun:dev.kord.rest.request.StackTraceRecoveringKtorRequestHandler#handle(dev.kord.rest.request.Request<0:0,0:1>){0§;1§}0:1 + 300 +//at 4 ??? 7ff684fbd4c4 kfun:dev.kord.rest.request.StackTraceRecoveryTest.$test stack trace recovery$lambda$1COROUTINE$15.invokeSuspend#internal + 2740 +//-->at 5 ??? 7ff684fbdeca kfun:dev.kord.rest.request.StackTraceRecoveryTest.$test stack trace<-- +actual fun currentThreadStackTrace(): StackTraceElement = + Exception().stackTraceToString().lineSequence().filterNot(String::isBlank).drop(5).first().trim() + .substringAfter("???") + +internal actual fun RecoveredStackTrace.validate(expected: StackTraceElement) { + // The first few lines are artifacts from coroutines which are not present in expected + val actual = stackTraceToString().lineSequence().drop(6).first().trim() + .substringAfter("???") // index is off at call site + assertEquals(expected, actual) +} diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index 93ad034df43..511f9f57ed9 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -1,5 +1,6 @@ plugins { `kord-internal-multiplatform-module` + `kord-native-module` } kotlin { diff --git a/test-kit/src/commonMain/kotlin/Annotations.kt b/test-kit/src/commonMain/kotlin/Annotations.kt index bcc93e2653d..a2b8b3ae23d 100644 --- a/test-kit/src/commonMain/kotlin/Annotations.kt +++ b/test-kit/src/commonMain/kotlin/Annotations.kt @@ -14,3 +14,8 @@ expect annotation class IgnoreOnJs() @Target(CLASS, FUNCTION) @OptionalExpectation expect annotation class IgnoreOnJvm() + +/** Ignores this test on Native platforms. */ +@Target(CLASS, FUNCTION) +@OptionalExpectation +expect annotation class IgnoreOnNative() diff --git a/test-kit/src/commonMain/kotlin/Platform.kt b/test-kit/src/commonMain/kotlin/Platform.kt index fe9f5179e53..b3ea79f20fa 100644 --- a/test-kit/src/commonMain/kotlin/Platform.kt +++ b/test-kit/src/commonMain/kotlin/Platform.kt @@ -1,12 +1,19 @@ package dev.kord.test import io.ktor.utils.io.* +import com.goncalossilva.resources.Resource expect object Platform { val IS_JVM: Boolean val IS_NODE: Boolean + val IS_BROWSER: Boolean + val IS_MINGW: Boolean + val IS_LINUX: Boolean + val IS_DARWIN: Boolean } expect fun getEnv(name: String): String? -expect suspend fun file(project: String, path: String): String -expect suspend fun readFile(project: String, path: String): ByteReadChannel +fun file(path: String): String = resource(path).readText() +fun readFile(path: String): ByteReadChannel = ByteReadChannel(resource(path).readBytes()) + +private fun resource(path: String) = Resource("src/commonTest/resources/$path") diff --git a/test-kit/src/jsMain/kotlin/Platform.kt b/test-kit/src/jsMain/kotlin/Platform.kt index bf7bcae63bb..f646655df04 100644 --- a/test-kit/src/jsMain/kotlin/Platform.kt +++ b/test-kit/src/jsMain/kotlin/Platform.kt @@ -1,6 +1,5 @@ package dev.kord.test -import io.ktor.utils.io.* import node.process.process actual object Platform { @@ -9,12 +8,13 @@ actual object Platform { get() = js( "typeof process !== 'undefined' && process.versions != null && process.versions.node != null" ) as Boolean + actual val IS_BROWSER: Boolean + get() = js( + "typeof window !== 'undefined' && typeof window.document !== 'undefined' || typeof self !== 'undefined' && typeof self.location !== 'undefined'" + ) as Boolean + actual const val IS_MINGW: Boolean = false + actual const val IS_LINUX: Boolean = false + actual const val IS_DARWIN: Boolean = false } actual fun getEnv(name: String) = process.env[name] - -actual suspend fun file(project: String, path: String): String = - if (Platform.IS_NODE) nodeFile(project, path) else TODO("Browser JS is not supported yet") - -actual suspend fun readFile(project: String, path: String): ByteReadChannel = - if (Platform.IS_NODE) nodeReadFile(project, path) else TODO("Browser JS is not supported yet") diff --git a/test-kit/src/nativeMain/kotlin/IgnoreOnNative.kt b/test-kit/src/nativeMain/kotlin/IgnoreOnNative.kt new file mode 100644 index 00000000000..db53b213dce --- /dev/null +++ b/test-kit/src/nativeMain/kotlin/IgnoreOnNative.kt @@ -0,0 +1,5 @@ +package dev.kord.test + +import kotlin.test.Ignore + +actual typealias IgnoreOnNative = Ignore diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt new file mode 100644 index 00000000000..979518d356e --- /dev/null +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -0,0 +1,23 @@ +@file:OptIn(ExperimentalNativeApi::class) + +package dev.kord.test + +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.toKString +import platform.posix.getenv +import kotlin.experimental.ExperimentalNativeApi +import kotlin.native.Platform + +private val darwinFamilies = listOf(OsFamily.WATCHOS, OsFamily.TVOS, OsFamily.MACOSX) + +actual object Platform { + actual val IS_JVM: Boolean = false + actual val IS_NODE: Boolean = false + actual val IS_BROWSER: Boolean = false + actual val IS_MINGW: Boolean = Platform.osFamily == OsFamily.WINDOWS + actual val IS_LINUX: Boolean = Platform.osFamily == OsFamily.LINUX + actual val IS_DARWIN: Boolean = Platform.osFamily in darwinFamilies +} + +@OptIn(ExperimentalForeignApi::class) +actual fun getEnv(name: String) = getenv(name)?.toKString() From 537a01bbe4b38e5c007cd583b9ad99b2b6b03c22 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 17:48:47 +0200 Subject: [PATCH 02/83] Disable CI for now --- .github/workflows/deployment-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/deployment-ci.yml b/.github/workflows/deployment-ci.yml index a0a01ee1e7f..380dd25838f 100644 --- a/.github/workflows/deployment-ci.yml +++ b/.github/workflows/deployment-ci.yml @@ -8,6 +8,9 @@ on: - '**' # We want to run this on all branch pushes tags-ignore: - '**' # We don't want this to run on tags pushes + branches-ignore: + # CI is not setup for Native + - 'feature/native' pull_request: release: types: [ published ] From 540aee283bcc10b62e1110b62756bccf5ae32a97 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 17:49:11 +0200 Subject: [PATCH 03/83] Use hierarchies for all KMP targets --- .../main/kotlin/kord-multiplatform-module.gradle.kts | 11 +++++++++-- .../src/main/kotlin/kord-native-module.gradle.kts | 2 -- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 48f03d119b4..3f0c3906247 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -24,6 +24,15 @@ apiValidation { } kotlin { + applyDefaultHierarchyTemplate { + common { + group("nonJvm") { + withNative() + withJs() + } + } + } + explicitApi() jvm() @@ -38,8 +47,6 @@ kotlin { } } - applyDefaultHierarchyTemplate() - sourceSets { all { applyKordOptIns() diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index 3aabb90a53d..1198e9e6bbe 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -3,8 +3,6 @@ plugins { } kotlin { - targetHierarchy.default() - linuxX64() // Waiting for Ktor // https://youtrack.jetbrains.com/issue/KTOR-872 From e01927280eceac9a985b1263e47dd3aecb76732e Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 17:49:31 +0200 Subject: [PATCH 04/83] Add missing generated files --- ...icationRoleConnectionMetadataRecordType.kt | 137 ++++++++++++++++++ .../entity/DiscordRoleConnectionMetadata.kt | 75 ++++++++++ .../ApplicationRoleConnectionMetadataData.kt | 39 +++++ .../RoleConnectionMetadataRecord.kt | 26 ++++ 4 files changed, 277 insertions(+) create mode 100644 common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt create mode 100644 common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt create mode 100644 core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt create mode 100644 core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt diff --git a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt new file mode 100644 index 00000000000..a758497efeb --- /dev/null +++ b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt @@ -0,0 +1,137 @@ +// THIS FILE IS AUTO-GENERATED BY KordEnumProcessor.kt, DO NOT EDIT! +@file:Suppress(names = arrayOf("RedundantVisibilityModifier", "IncorrectFormatting", + "ReplaceArrayOfWithLiteral", "SpellCheckingInspection", "GrazieInspection")) + +package dev.kord.common.entity + +import kotlin.Any +import kotlin.Boolean +import kotlin.Int +import kotlin.LazyThreadSafetyMode.PUBLICATION +import kotlin.String +import kotlin.Suppress +import kotlin.collections.List +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +/** + * Type of [DiscordRoleConnectionMetadata] values + * + * See [DiscordApplicationRoleConnectionMetadataRecordType]s in the + * [Discord Developer Documentation](https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type). + */ +@Serializable(with = DiscordApplicationRoleConnectionMetadataRecordType.Serializer::class) +public sealed class DiscordApplicationRoleConnectionMetadataRecordType( + /** + * The raw value used by Discord. + */ + public val `value`: Int, +) { + public final override fun equals(other: Any?): Boolean = this === other || + (other is DiscordApplicationRoleConnectionMetadataRecordType && this.value == other.value) + + public final override fun hashCode(): Int = value.hashCode() + + public final override fun toString(): String = + "DiscordApplicationRoleConnectionMetadataRecordType.${this::class.simpleName}(value=$value)" + + /** + * An unknown [DiscordApplicationRoleConnectionMetadataRecordType]. + * + * This is used as a fallback for [DiscordApplicationRoleConnectionMetadataRecordType]s that + * haven't been added to Kord yet. + */ + public class Unknown( + `value`: Int, + ) : DiscordApplicationRoleConnectionMetadataRecordType(value) + + /** + * The metadata value (integer) is less than or equal to the guild's configured value (integer) + */ + public object IntegerLessThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(1) + + /** + * The metadata value (integer) is greater than or equal to the guild's configured value + * (integer) + */ + public object IntegerGreaterThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(2) + + /** + * The metadata value (integer) is equal to the guild's configured value (integer) + */ + public object IntegerEqual : DiscordApplicationRoleConnectionMetadataRecordType(3) + + /** + * The metadata value (integer) is not equal to the guild's configured value (integer) + */ + public object IntegerNotEqual : DiscordApplicationRoleConnectionMetadataRecordType(4) + + /** + * The metadata value (ISO8601 string) is less than or equal to the guild's configured value + * (integer; days before current date) + */ + public object DateTimeLessThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(5) + + /** + * The metadata value (ISO8601 string) is greater than or equal to the guild's configured value + * (integer; days before current date) + */ + public object DateTimeGreaterThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(6) + + /** + * The metadata value (integer) is equal to the guild's configured value (integer; 1) + */ + public object BooleanEqual : DiscordApplicationRoleConnectionMetadataRecordType(7) + + /** + * The metadata value (integer) is not equal to the guild's configured value (integer; 1) + */ + public object BooleanNotEqual : DiscordApplicationRoleConnectionMetadataRecordType(8) + + internal object Serializer : KSerializer { + public override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType", + PrimitiveKind.INT) + + public override fun serialize(encoder: Encoder, + `value`: DiscordApplicationRoleConnectionMetadataRecordType) = + encoder.encodeInt(value.value) + + public override fun deserialize(decoder: Decoder) = when (val value = decoder.decodeInt()) { + 1 -> IntegerLessThanOrEqual + 2 -> IntegerGreaterThanOrEqual + 3 -> IntegerEqual + 4 -> IntegerNotEqual + 5 -> DateTimeLessThanOrEqual + 6 -> DateTimeGreaterThanOrEqual + 7 -> BooleanEqual + 8 -> BooleanNotEqual + else -> Unknown(value) + } + } + + public companion object { + /** + * A [List] of all known [DiscordApplicationRoleConnectionMetadataRecordType]s. + */ + public val entries: List by + lazy(mode = PUBLICATION) { + listOf( + IntegerLessThanOrEqual, + IntegerGreaterThanOrEqual, + IntegerEqual, + IntegerNotEqual, + DateTimeLessThanOrEqual, + DateTimeGreaterThanOrEqual, + BooleanEqual, + BooleanNotEqual, + ) + } + + } +} diff --git a/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt b/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt new file mode 100644 index 00000000000..c1150a053e7 --- /dev/null +++ b/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt @@ -0,0 +1,75 @@ +@file:GenerateKordEnum( + name = "DiscordApplicationRoleConnectionMetadataRecordType", + valueType = GenerateKordEnum.ValueType.INT, + docUrl = "https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type", + kDoc = "Type of [DiscordRoleConnectionMetadata] values", + entries = [ + GenerateKordEnum.Entry( + name = "IntegerLessThanOrEqual", + intValue = 1, + kDoc = "The metadata value (integer) is less than or equal to the guild's configured value (integer)" + ), + GenerateKordEnum.Entry( + name = "IntegerGreaterThanOrEqual", + intValue = 2, + kDoc = "The metadata value (integer) is greater than or equal to the guild's configured value (integer)" + ), + GenerateKordEnum.Entry( + name = "IntegerEqual", + intValue = 3, + kDoc = "The metadata value (integer) is equal to the guild's configured value (integer)" + ), + GenerateKordEnum.Entry( + name = "IntegerNotEqual", + intValue = 4, + kDoc = "The metadata value (integer) is not equal to the guild's configured value (integer)" + ), + GenerateKordEnum.Entry( + name = "DateTimeLessThanOrEqual", + intValue = 5, + kDoc = "The metadata value (ISO8601 string) is less than or equal to the guild's configured value (integer; days before current date)" + ), + GenerateKordEnum.Entry( + name = "DateTimeGreaterThanOrEqual", + intValue = 6, + kDoc = "The metadata value (ISO8601 string) is greater than or equal to the guild's configured value (integer; days before current date)" + ), + GenerateKordEnum.Entry( + name = "BooleanEqual", + intValue = 7, + kDoc = "The metadata value (integer) is equal to the guild's configured value (integer; 1)" + ), + GenerateKordEnum.Entry( + name = "BooleanNotEqual", + intValue = 8, + kDoc = "The metadata value (integer) is not equal to the guild's configured value (integer; 1)" + ) + ] +) + +package dev.kord.common.entity + +import dev.kord.common.Locale +import dev.kord.common.entity.optional.Optional +import dev.kord.ksp.GenerateKordEnum +import kotlinx.serialization.Serializable + +/** + * A representation of role connection metadata for an [application][DiscordApplication]. + * + * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value + * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) + * @property name name of the metadata field (1-100 characters) + * @property nameLocalizations with keys in available locales translations of the name + * @property description description of the metadata field (1-200 characters) + * @property descriptionLocalizations with keys in available locales translations of the description + */ +@Serializable +public data class DiscordApplicationRoleConnectionMetadataRecord( + val type: DiscordApplicationRoleConnectionMetadataRecordType, + val key: String, + val name: String, + val nameLocalizations: Optional> = Optional.Missing(), + val description: String, + val descriptionLocalizations: Optional> = Optional.Missing() +) diff --git a/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt b/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt new file mode 100644 index 00000000000..fd3faf8a2c5 --- /dev/null +++ b/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt @@ -0,0 +1,39 @@ +package dev.kord.core.cache.data + +import dev.kord.common.Locale +import dev.kord.common.entity.DiscordApplication +import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecord +import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType +import dev.kord.common.entity.optional.Optional + +/** + * A representation of role connection metadata for an [application][DiscordApplication]. + * + * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value + * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) + * @property name name of the metadata field (1-100 characters) + * @property nameLocalizations with keys in available locales translations of the name + * @property description description of the metadata field (1-200 characters) + * @property descriptionLocalizations with keys in available locales translations of the description + */ + +public data class ApplicationRoleConnectionMetadataData( + val type: DiscordApplicationRoleConnectionMetadataRecordType, + val key: String, + val name: String, + val nameLocalizations: Optional> = Optional.Missing(), + val description: String, + val descriptionLocalizations: Optional> = Optional.Missing() +) { + public companion object { + public fun from(record: DiscordApplicationRoleConnectionMetadataRecord): ApplicationRoleConnectionMetadataData = + ApplicationRoleConnectionMetadataData( + record.type, + record.key, + record.name, + record.nameLocalizations, + record.description, + record.descriptionLocalizations + ) + } +} diff --git a/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt b/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt new file mode 100644 index 00000000000..d3d9c77d673 --- /dev/null +++ b/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt @@ -0,0 +1,26 @@ +package dev.kord.core.entity.application + +import dev.kord.common.Locale +import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType +import dev.kord.core.cache.data.ApplicationRoleConnectionMetadataData + +/** + * A representation of role connection metadata for an [application][Application]. + * + * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value + * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) + * @property name name of the metadata field (1-100 characters) + * @property nameLocalizations with keys in available locales translations of the name + * @property description description of the metadata field (1-200 characters) + * @property descriptionLocalizations with keys in available locales translations of the description + */ +public class RoleConnectionMetadataRecord(public val data: ApplicationRoleConnectionMetadataData) { + public val type: DiscordApplicationRoleConnectionMetadataRecordType get() = data.type + public val key: String get() = data.key + public val name: String get() = data.name + public val nameLocalizations: Map + get() = data.nameLocalizations.value ?: emptyMap() + public val description: String get() = data.description + public val descriptionLocalizations: Map + get() = data.nameLocalizations.value ?: emptyMap() +} From 6d91b32364f4896d08c0e4d0ad0bfbe733395da0 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 21:20:34 +0200 Subject: [PATCH 05/83] Add missing generated types --- common/api/common.api | 90 +++++++++++++++++++ ...icationRoleConnectionMetadataRecordType.kt | 27 +++--- core/api/core.api | 38 ++++++++ 3 files changed, 140 insertions(+), 15 deletions(-) diff --git a/common/api/common.api b/common/api/common.api index 324cfa62fd2..18ae0b41cc7 100644 --- a/common/api/common.api +++ b/common/api/common.api @@ -2624,6 +2624,96 @@ public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetada public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord { + public static final field Companion Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$Companion; + public synthetic fun (ILdev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)V + public synthetic fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Ldev/kord/common/entity/optional/Optional; + public final fun component5 ()Ljava/lang/String; + public final fun component6 ()Ldev/kord/common/entity/optional/Optional; + public final fun copy (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; + public static synthetic fun copy$default (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILjava/lang/Object;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; + public fun equals (Ljava/lang/Object;)Z + public final fun getDescription ()Ljava/lang/String; + public final fun getDescriptionLocalizations ()Ldev/kord/common/entity/optional/Optional; + public final fun getKey ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getNameLocalizations ()Ldev/kord/common/entity/optional/Optional; + public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public static final synthetic fun write$Self (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$$serializer; + public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public abstract class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field Companion Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Companion; + public synthetic fun (ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun equals (Ljava/lang/Object;)Z + public final fun getValue ()I + public final fun hashCode ()I + public final fun toString ()Ljava/lang/String; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanNotEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanNotEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Companion { + public final fun getEntries ()Ljava/util/List; + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeGreaterThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeGreaterThanOrEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeLessThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeLessThanOrEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerGreaterThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerGreaterThanOrEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerLessThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerLessThanOrEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerNotEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerNotEqual; +} + +public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Unknown : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { + public fun (I)V +} + public final class dev/kord/common/entity/DiscordAttachment { public static final field Companion Ldev/kord/common/entity/DiscordAttachment$Companion; public fun (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;ILjava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalBoolean;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;)V diff --git a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt index a758497efeb..df3e645a038 100644 --- a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt +++ b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt @@ -1,16 +1,10 @@ -// THIS FILE IS AUTO-GENERATED BY KordEnumProcessor.kt, DO NOT EDIT! +// THIS FILE IS AUTO-GENERATED, DO NOT EDIT! @file:Suppress(names = arrayOf("RedundantVisibilityModifier", "IncorrectFormatting", "ReplaceArrayOfWithLiteral", "SpellCheckingInspection", "GrazieInspection")) package dev.kord.common.entity -import kotlin.Any -import kotlin.Boolean -import kotlin.Int import kotlin.LazyThreadSafetyMode.PUBLICATION -import kotlin.String -import kotlin.Suppress -import kotlin.collections.List import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.descriptors.PrimitiveKind @@ -32,12 +26,12 @@ public sealed class DiscordApplicationRoleConnectionMetadataRecordType( */ public val `value`: Int, ) { - public final override fun equals(other: Any?): Boolean = this === other || + final override fun equals(other: Any?): Boolean = this === other || (other is DiscordApplicationRoleConnectionMetadataRecordType && this.value == other.value) - public final override fun hashCode(): Int = value.hashCode() + final override fun hashCode(): Int = value.hashCode() - public final override fun toString(): String = + final override fun toString(): String = "DiscordApplicationRoleConnectionMetadataRecordType.${this::class.simpleName}(value=$value)" /** @@ -94,15 +88,18 @@ public sealed class DiscordApplicationRoleConnectionMetadataRecordType( public object BooleanNotEqual : DiscordApplicationRoleConnectionMetadataRecordType(8) internal object Serializer : KSerializer { - public override val descriptor: SerialDescriptor = + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType", PrimitiveKind.INT) - public override fun serialize(encoder: Encoder, - `value`: DiscordApplicationRoleConnectionMetadataRecordType) = - encoder.encodeInt(value.value) + override fun serialize(encoder: Encoder, + `value`: DiscordApplicationRoleConnectionMetadataRecordType) { + encoder.encodeInt(value.value) + } - public override fun deserialize(decoder: Decoder) = when (val value = decoder.decodeInt()) { + override fun deserialize(decoder: Decoder): + DiscordApplicationRoleConnectionMetadataRecordType = + when (val value = decoder.decodeInt()) { 1 -> IntegerLessThanOrEqual 2 -> IntegerGreaterThanOrEqual 3 -> IntegerEqual diff --git a/core/api/core.api b/core/api/core.api index a535d1f6dd6..96a0de18cf6 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -2680,6 +2680,33 @@ public final class dev/kord/core/cache/data/ApplicationInteractionData$Companion public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class dev/kord/core/cache/data/ApplicationRoleConnectionMetadataData { + public static final field Companion Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData$Companion; + public fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)V + public synthetic fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Ldev/kord/common/entity/optional/Optional; + public final fun component5 ()Ljava/lang/String; + public final fun component6 ()Ldev/kord/common/entity/optional/Optional; + public final fun copy (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; + public static synthetic fun copy$default (Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILjava/lang/Object;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; + public fun equals (Ljava/lang/Object;)Z + public final fun getDescription ()Ljava/lang/String; + public final fun getDescriptionLocalizations ()Ldev/kord/common/entity/optional/Optional; + public final fun getKey ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getNameLocalizations ()Ldev/kord/common/entity/optional/Optional; + public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class dev/kord/core/cache/data/ApplicationRoleConnectionMetadataData$Companion { + public final fun from (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; +} + public final class dev/kord/core/cache/data/AttachmentData { public static final field Companion Ldev/kord/core/cache/data/AttachmentData$Companion; public fun (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;ILjava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalBoolean;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;)V @@ -7491,6 +7518,17 @@ public final class dev/kord/core/entity/application/MessageCommand$DefaultImpls public static fun isNsfw (Ldev/kord/core/entity/application/MessageCommand;)Z } +public final class dev/kord/core/entity/application/RoleConnectionMetadataRecord { + public fun (Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData;)V + public final fun getData ()Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; + public final fun getDescription ()Ljava/lang/String; + public final fun getDescriptionLocalizations ()Ljava/util/Map; + public final fun getKey ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getNameLocalizations ()Ljava/util/Map; + public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; +} + public final class dev/kord/core/entity/application/UnknownGlobalApplicationCommand : dev/kord/core/entity/application/GlobalApplicationCommand { public fun (Ldev/kord/core/cache/data/ApplicationCommandData;Ldev/kord/rest/service/InteractionService;)V public fun compareTo (Ldev/kord/core/entity/Entity;)I From 1ed902eb16bdf92983ad2f5e6c242536662fd2e9 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 21:44:12 +0200 Subject: [PATCH 06/83] Fix tests - revert back to own test file handler - update yarn lock - Fix task dependencies --- ...d-internal-multiplatform-module.gradle.kts | 4 +++ .../kord-multiplatform-module.gradle.kts | 16 +++++++++--- .../main/kotlin/kord-native-module.gradle.kts | 13 +++++++--- common/build.gradle.kts | 4 +-- core/build.gradle.kts | 2 +- gateway/build.gradle.kts | 2 +- gradle/libs.versions.toml | 2 ++ kotlin-js-store/yarn.lock | 18 +++++++++++++ ksp-annotations/build.gradle.kts | 2 +- rest/build.gradle.kts | 2 +- test-kit/build.gradle.kts | 7 ++++- test-kit/src/commonMain/kotlin/Platform.kt | 6 ++--- test-kit/src/jsMain/kotlin/Platform.kt | 7 +++++ test-kit/src/jsMain/kotlin/Platform.node.kt | 2 +- test-kit/src/jvmMain/kotlin/Platform.kt | 4 +++ test-kit/src/nativeMain/kotlin/Platform.kt | 26 +++++++++++++++++++ 16 files changed, 98 insertions(+), 19 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts index bf1d80fd0b6..3c041c6e387 100644 --- a/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi + plugins { org.jetbrains.kotlin.multiplatform } @@ -6,7 +8,9 @@ repositories { mavenCentral() } +@OptIn(ExperimentalKotlinGradlePluginApi::class) kotlin { + targetHierarchy.default() jvm() js { nodejs() diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 3f0c3906247..01a974c37be 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -1,4 +1,7 @@ +import org.gradle.configurationcache.extensions.capitalized import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest plugins { @@ -8,7 +11,6 @@ plugins { `kotlinx-atomicfu` org.jetbrains.kotlinx.`binary-compatibility-validator` com.google.devtools.ksp - com.goncalossilva.resources } repositories { @@ -24,7 +26,7 @@ apiValidation { } kotlin { - applyDefaultHierarchyTemplate { + targetHierarchy.default { common { group("nonJvm") { withNative() @@ -80,7 +82,15 @@ tasks { environment("PROJECT_ROOT", rootProject.projectDir.absolutePath) } - for (task in listOf("compileKotlinJvm", "compileKotlinJs", "jvmSourcesJar", "jsSourcesJar")) { + val compilationTasks = kotlin.targets.flatMap { + buildList { + add("compileKotlin${it.name.capitalized()}") + if (it !is KotlinNativeTarget) { + add("${it.name}SourcesJar") + } + } + } + for (task in compilationTasks) { named(task) { dependsOn("kspCommonMainKotlinMetadata") } diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index 1198e9e6bbe..548c59f8950 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -1,12 +1,17 @@ +import org.apache.tools.ant.taskdefs.condition.Os + plugins { org.jetbrains.kotlin.multiplatform } kotlin { - linuxX64() - // Waiting for Ktor - // https://youtrack.jetbrains.com/issue/KTOR-872 - //linuxArm64() + if(!Os.isFamily(Os.FAMILY_WINDOWS)) { + linuxX64() + // Waiting for Ktor + // https://youtrack.jetbrains.com/issue/KTOR-872 + //linuxArm64() + } + mingwX64() diff --git a/common/build.gradle.kts b/common/build.gradle.kts index ed7e7dbbbc6..910c9993806 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-multiplatform-module` `kord-native-module` + `kord-multiplatform-module` `kord-publishing` alias(libs.plugins.buildconfig) } @@ -58,7 +58,7 @@ kotlin { } } - linuxMain { + findByName("linuxMain")?.apply { dependencies { api(libs.ktor.client.curl) } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index d7ad3517172..1351ed54cd1 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,8 +1,8 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 plugins { - `kord-multiplatform-module` `kord-native-module` + `kord-multiplatform-module` `kord-publishing` } diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index 8732cf3f179..1a0f0c1d718 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-multiplatform-module` `kord-native-module` + `kord-multiplatform-module` `kord-publishing` } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 53ae6a737aa..9ed66818ff1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,6 +25,7 @@ kotlinpoet = "1.15.3" # https://github.com/square/kotlinpoet junit5 = "5.10.1" # https://github.com/junit-team/junit5 mockk = "1.13.8" # https://github.com/mockk/mockk slf4j = "2.0.9" # https://www.slf4j.org +okio = "3.5.0" # plugins dokka = "1.9.10" # https://github.com/Kotlin/dokka @@ -83,6 +84,7 @@ junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", vers mockk = { module = "io.mockk:mockk", version.ref = "mockk" } slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" } kotlinx-resources = { module = "com.goncalossilva:resources", version.ref = "kotlinx-resources" } +okio = { module = "com.squareup.okio:okio", version.ref = "okio" } # actually plugins, not libraries, but used is 'buildSrc/build.gradle.kts' as implementation dependencies: # https://docs.gradle.org/current/userguide/custom_plugins.html#applying_external_plugins_in_precompiled_script_plugins diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 28defc34c42..3ad6f3f7202 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -157,6 +157,14 @@ diff@5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== +dukat@0.5.8-rc.4: + version "0.5.8-rc.4" + resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.8-rc.4.tgz#90384dcb50b14c26f0e99dae92b2dea44f5fce21" + integrity sha512-ZnMt6DGBjlVgK2uQamXfd7uP/AxH7RqI0BL9GLrrJb2gKdDxvJChWy+M9AQEaL+7/6TmxzJxFOsRiInY9oGWTA== + dependencies: + google-protobuf "3.12.2" + typescript "3.9.5" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -241,6 +249,11 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +google-protobuf@3.12.2: + version "3.12.2" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53" + integrity sha512-4CZhpuRr1d6HjlyrxoXoocoGFnRYgKULgMtikMddA9ztRyYR59Aondv2FioyxWVamRo0rF2XpYawkTCBEQOSkA== + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -520,6 +533,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +typescript@3.9.5: + version "3.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" + integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== + typescript@5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" diff --git a/ksp-annotations/build.gradle.kts b/ksp-annotations/build.gradle.kts index e4fe6b72e20..74548672acb 100644 --- a/ksp-annotations/build.gradle.kts +++ b/ksp-annotations/build.gradle.kts @@ -1,8 +1,8 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask plugins { - `kord-internal-multiplatform-module` `kord-native-module` + `kord-internal-multiplatform-module` // workaround for https://youtrack.jetbrains.com/issue/KT-43500 (not intended to be published) org.jetbrains.dokka diff --git a/rest/build.gradle.kts b/rest/build.gradle.kts index af2d4e4c182..6ccbec4d98a 100644 --- a/rest/build.gradle.kts +++ b/rest/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-multiplatform-module` `kord-native-module` + `kord-multiplatform-module` `kord-publishing` } diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index 511f9f57ed9..40f52c38294 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - `kord-internal-multiplatform-module` `kord-native-module` + `kord-internal-multiplatform-module` } kotlin { @@ -21,5 +21,10 @@ kotlin { api(libs.bundles.test.jvm) } } + nativeMain { + dependencies { + api(libs.okio) + } + } } } diff --git a/test-kit/src/commonMain/kotlin/Platform.kt b/test-kit/src/commonMain/kotlin/Platform.kt index b3ea79f20fa..6b22bfdf063 100644 --- a/test-kit/src/commonMain/kotlin/Platform.kt +++ b/test-kit/src/commonMain/kotlin/Platform.kt @@ -13,7 +13,5 @@ expect object Platform { } expect fun getEnv(name: String): String? -fun file(path: String): String = resource(path).readText() -fun readFile(path: String): ByteReadChannel = ByteReadChannel(resource(path).readBytes()) - -private fun resource(path: String) = Resource("src/commonTest/resources/$path") +expect suspend fun file(project: String, path: String): String +expect suspend fun readFile(project: String, path: String): ByteReadChannel diff --git a/test-kit/src/jsMain/kotlin/Platform.kt b/test-kit/src/jsMain/kotlin/Platform.kt index f646655df04..c9cc7a4220a 100644 --- a/test-kit/src/jsMain/kotlin/Platform.kt +++ b/test-kit/src/jsMain/kotlin/Platform.kt @@ -1,5 +1,6 @@ package dev.kord.test +import io.ktor.utils.io.* import node.process.process actual object Platform { @@ -18,3 +19,9 @@ actual object Platform { } actual fun getEnv(name: String) = process.env[name] + +actual suspend fun file(project: String, path: String): String = + if (Platform.IS_NODE) nodeFile(project, path) else TODO("Browser JS is not supported yet") + +actual suspend fun readFile(project: String, path: String): ByteReadChannel = + if (Platform.IS_NODE) nodeReadFile(project, path) else TODO("Browser JS is not supported yet") diff --git a/test-kit/src/jsMain/kotlin/Platform.node.kt b/test-kit/src/jsMain/kotlin/Platform.node.kt index 0ed68d8e976..2949105f551 100644 --- a/test-kit/src/jsMain/kotlin/Platform.node.kt +++ b/test-kit/src/jsMain/kotlin/Platform.node.kt @@ -1,7 +1,7 @@ package dev.kord.test import io.ktor.utils.io.* -import js.iterable.toList +import js.core.toList import node.buffer.Buffer import node.buffer.BufferEncoding import node.process.process diff --git a/test-kit/src/jvmMain/kotlin/Platform.kt b/test-kit/src/jvmMain/kotlin/Platform.kt index 85e5784737c..d70783d045a 100644 --- a/test-kit/src/jvmMain/kotlin/Platform.kt +++ b/test-kit/src/jvmMain/kotlin/Platform.kt @@ -6,6 +6,10 @@ import io.ktor.utils.io.jvm.javaio.* actual object Platform { actual const val IS_JVM: Boolean = true actual const val IS_NODE: Boolean = false + actual val IS_BROWSER: Boolean = false + actual val IS_MINGW: Boolean = false + actual val IS_LINUX: Boolean = false + actual val IS_DARWIN: Boolean = false } actual fun getEnv(name: String): String? = System.getenv(name) diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt index 979518d356e..82e6e61381b 100644 --- a/test-kit/src/nativeMain/kotlin/Platform.kt +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -2,8 +2,13 @@ package dev.kord.test +import io.ktor.utils.io.* import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.toKString +import okio.BufferedSource +import okio.FileSystem +import okio.IOException +import okio.Path.Companion.toPath import platform.posix.getenv import kotlin.experimental.ExperimentalNativeApi import kotlin.native.Platform @@ -21,3 +26,24 @@ actual object Platform { @OptIn(ExperimentalForeignApi::class) actual fun getEnv(name: String) = getenv(name)?.toKString() + +private fun actutalPath(path: String) = + "src/commonTest/resources/$path".toPath() + +actual suspend fun file(project: String, path: String): String = read(path, BufferedSource::readUtf8) + +actual suspend fun readFile(project: String, path: String): ByteReadChannel = + read(path) { ByteReadChannel(readByteArray()) } + +private inline fun read(path: String, readerAction: BufferedSource.() -> T): T { + val actualPath = actutalPath(path) + return try { + FileSystem.SYSTEM.read(actualPath, readerAction) + } catch (e: Throwable) { + val pwd = FileSystem.SYSTEM.canonicalize(".".toPath()) + val absolutePath = pwd / actualPath + throw FileNotFoundException(absolutePath.toString(), e) + } +} + +class FileNotFoundException(absolutePath: String, cause: Throwable) : IOException("Absolute Path: $absolutePath", cause) From 92ab453097f0a2eae071565b11966a61d3c723f4 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 22:11:58 +0200 Subject: [PATCH 07/83] Fix weird atomic issues on native --- .../src/main/kotlin/kord-multiplatform-module.gradle.kts | 5 +++++ rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt | 4 ++++ .../nativeMain/kotlin/{ => request}/RecoveredStackTrace.kt | 0 rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt | 3 +++ 4 files changed, 12 insertions(+) create mode 100644 rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt rename rest/src/nativeMain/kotlin/{ => request}/RecoveredStackTrace.kt (100%) create mode 100644 rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 01a974c37be..9efa8b58537 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -32,6 +32,11 @@ kotlin { withNative() withJs() } + + group("nonNative") { + withJs() + withJvm() + } } } diff --git a/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt b/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt new file mode 100644 index 00000000000..fcb7c50f4b1 --- /dev/null +++ b/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt @@ -0,0 +1,4 @@ +package dev.kord.rest.ratelimit + +// https://github.com/Kotlin/kotlinx-atomicfu/issues/291 +internal actual val useUpdate: Boolean = false diff --git a/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt b/rest/src/nativeMain/kotlin/request/RecoveredStackTrace.kt similarity index 100% rename from rest/src/nativeMain/kotlin/RecoveredStackTrace.kt rename to rest/src/nativeMain/kotlin/request/RecoveredStackTrace.kt diff --git a/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt b/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt new file mode 100644 index 00000000000..f48a77ecc64 --- /dev/null +++ b/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt @@ -0,0 +1,3 @@ +package dev.kord.rest.ratelimit + +internal actual val useUpdate: Boolean = true From e8007c1c91193c1a3e2278c0efc7f2a2608f74f5 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 15 Apr 2023 19:02:53 +0200 Subject: [PATCH 08/83] Implement Throwable.isTimeout() on native --- gateway/src/nativeMain/kotlin/DefaultGateway.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/DefaultGateway.kt b/gateway/src/nativeMain/kotlin/DefaultGateway.kt index 9a563091de9..2224a4ebe0c 100644 --- a/gateway/src/nativeMain/kotlin/DefaultGateway.kt +++ b/gateway/src/nativeMain/kotlin/DefaultGateway.kt @@ -1,9 +1,11 @@ package dev.kord.gateway +import dev.kord.common.annotation.KordInternal +import io.ktor.util.network.* import kotlin.experimental.ExperimentalNativeApi -// TODO: Timeout -internal actual fun Throwable.isTimeout() = false +@KordInternal +public actual fun Throwable.isTimeout(): Boolean = this is UnresolvedAddressException @OptIn(ExperimentalNativeApi::class) internal actual val os: String get() = Platform.osFamily.name From 850b2d8a1d24c3b97b597d8afc563ec3241e65f5 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 22:41:53 +0200 Subject: [PATCH 09/83] Add publishing utility functions --- .../kord-multiplatform-module.gradle.kts | 31 ++++++++++++++++++- .../main/kotlin/kord-publishing.gradle.kts | 2 +- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 9efa8b58537..7927f348706 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -34,7 +34,7 @@ kotlin { } group("nonNative") { - withJs() + withJs() withJvm() } } @@ -101,6 +101,35 @@ tasks { } } + register("publishNonNative") { + dependsOn( + "publishKotlinMultiplatformPublicationToMavenRepository", + "publishJsPublicationToMavenRepository", + "publishJvmPublicationToMavenRepository" + ) + } + + register("publishLinux") { + dependsOn("publishLinuxX64PublicationToMavenRepository") + } + + register("publishMingw") { + dependsOn("publishMingwX64PublicationToMavenRepository") + } + + register("publishDarwin") { + dependsOn( + "publishMacosArm64PublicationToMavenRepository", + "publishMacosX64PublicationToMavenRepository", + "publishIosArm64PublicationToMavenRepository", + "publishIosX64PublicationToMavenRepository", + "publishWatchosX64PublicationToMavenRepository", + "publishWatchosArm64PublicationToMavenRepository", + "publishTvosX64PublicationToMavenRepository", + "publishTvosArm64PublicationToMavenRepository" + ) + } + afterEvaluate { named("sourcesJar") { dependsOn("kspCommonMainKotlinMetadata") diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index a001f7113cc..4f7222f05ef 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -75,5 +75,5 @@ signing { val secretKey = getenv("SIGNING_KEY")?.let { String(Base64.getDecoder().decode(it)) } val password = getenv("SIGNING_PASSWORD") useInMemoryPgpKeys(secretKey, password) - sign(publishing.publications) + //sign(publishing.publications) } From cc1eca9f4213040820ce39fbd05b214643b6d91f Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 22:50:33 +0200 Subject: [PATCH 10/83] Fix darwin compilation --- .../src/main/kotlin/kord-multiplatform-module.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 7927f348706..9587fe91ea9 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -1,7 +1,6 @@ import org.gradle.configurationcache.extensions.capitalized import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest plugins { @@ -90,8 +89,9 @@ tasks { val compilationTasks = kotlin.targets.flatMap { buildList { add("compileKotlin${it.name.capitalized()}") - if (it !is KotlinNativeTarget) { - add("${it.name}SourcesJar") + val sourcesJarName = "${it.name}SourcesJar" + if (tasks.findByName(sourcesJarName) != null) { + add(sourcesJarName) } } } From 4c4d38ab66018d2741fefce0a43dfd7aabf24356 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 5 Aug 2023 22:53:14 +0200 Subject: [PATCH 11/83] Fix darwin compilation v2 --- .../kord-multiplatform-module.gradle.kts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 9587fe91ea9..52c7a1a6f05 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -86,21 +86,22 @@ tasks { environment("PROJECT_ROOT", rootProject.projectDir.absolutePath) } - val compilationTasks = kotlin.targets.flatMap { - buildList { - add("compileKotlin${it.name.capitalized()}") - val sourcesJarName = "${it.name}SourcesJar" - if (tasks.findByName(sourcesJarName) != null) { + afterEvaluate { + val compilationTasks = kotlin.targets.flatMap { + buildList { + add("compileKotlin${it.name.capitalized()}") + val sourcesJarName = "${it.name}SourcesJar" add(sourcesJarName) } } - } - for (task in compilationTasks) { - named(task) { - dependsOn("kspCommonMainKotlinMetadata") + for (task in compilationTasks) { + named(task) { + dependsOn("kspCommonMainKotlinMetadata") + } } } + register("publishNonNative") { dependsOn( "publishKotlinMultiplatformPublicationToMavenRepository", From 7bca8ba2d054190f9255ed387fd71383c6b74892 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sun, 6 Aug 2023 01:32:50 +0200 Subject: [PATCH 12/83] Enable signing if possible --- buildSrc/src/main/kotlin/kord-publishing.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index 4f7222f05ef..6c01f603544 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -75,5 +75,7 @@ signing { val secretKey = getenv("SIGNING_KEY")?.let { String(Base64.getDecoder().decode(it)) } val password = getenv("SIGNING_PASSWORD") useInMemoryPgpKeys(secretKey, password) - //sign(publishing.publications) + if (secretKey != null && password != null) { + sign(publishing.publications) + } } From bc672add43e0f9d5363eedb388f3f03c1d58385f Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sun, 6 Aug 2023 16:53:32 +0200 Subject: [PATCH 13/83] Add simulator targets --- buildSrc/src/main/kotlin/kord-native-module.gradle.kts | 6 +++--- gradle/libs.versions.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index 548c59f8950..3283be52e6e 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -20,13 +20,13 @@ kotlin { iosArm64() iosX64() -// iosSimulatorArm64() + iosSimulatorArm64() watchosX64() watchosArm64() -// watchosSimulatorArm64() + watchosSimulatorArm64() tvosX64() tvosArm64() -// tvosSimulatorArm64() + tvosSimulatorArm64() } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9ed66818ff1..d40b0da24a1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kotlinx-datetime = "0.5.0" # https://github.com/Kotlin/kotlinx-datetime kotlin-logging = "6.0.1" # https://github.com/oshai/kotlin-logging kotlin-logging-old = "3.0.5" # TODO remove after dependency is removed in rest, gateway, voice and core # This is the specific release supporting native, until we setup CI -kord-cache = "0.5.x-20230411.160140-1" # https://github.com/kordlib/cache +kord-cache = "0.5.x-20230806.144015-3" # https://github.com/kordlib/cache # implementation dependencies kotlin-node = "18.16.12-pre.619" # https://github.com/JetBrains/kotlin-wrappers From 1599a8e02503c1c21164e9c94474a6fd60c7fde0 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sun, 6 Aug 2023 17:09:31 +0200 Subject: [PATCH 14/83] Replace toInt() with convert() --- gateway/src/nativeMain/kotlin/Inflater.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index 4fbca05c13c..63bfa922edc 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -38,7 +38,7 @@ internal actual class Inflater : Closeable { if (resultCode != Z_OK && resultCode != Z_STREAM_END) { throw IllegalStateException("An error occurred during decompression of frame: $resultCode") } - out += uncompressedData.readBytes(uncompressedDataSize - zStream.avail_out.toInt()) + out += uncompressedData.readBytes(uncompressedDataSize - zStream.avail_out.convert()) } while (zStream.avail_out == 0u) } From 996bd00864f34f6ecff51e113868513f7dff52ba Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Wed, 24 Jan 2024 18:49:54 +0100 Subject: [PATCH 15/83] Rebase on main - Upgrade kotlin-js-store/yarn.lock - Remove deprecated KLogger.error - test-kit - Update native inflater and HttpClient definitions - Remove deprecated gatewayOnLogger - Upgrade api dump - Replace deprecated java.net.URL --- buildSrc/src/main/kotlin/Documentation.kt | 4 +- ...d-internal-multiplatform-module.gradle.kts | 2 +- .../kord-multiplatform-module.gradle.kts | 9 +---- common/api/common.api | 4 +- ...icationRoleConnectionMetadataRecordType.kt | 39 +++++++++++-------- common/src/appleMain/kotlin/HttpEngine.kt | 2 +- .../entity/DiscordRoleConnectionMetadata.kt | 22 +++++------ common/src/mingwMain/kotlin/HttpEngine.kt | 2 +- core/build.gradle.kts | 5 +++ gateway/api/gateway.api | 5 --- gateway/build.gradle.kts | 3 -- gateway/src/commonMain/kotlin/Gateway.kt | 5 --- gateway/src/commonMain/kotlin/Utils.kt | 8 ---- gateway/src/nativeMain/kotlin/Inflater.kt | 7 ++-- gradle/libs.versions.toml | 5 +-- kotlin-js-store/yarn.lock | 18 --------- .../kotlin/ratelimit/AbstractRateLimiter.kt | 4 -- .../kotlin/AbstractRateLimiter.kt | 3 -- test-kit/src/commonMain/kotlin/Platform.kt | 1 - test-kit/src/jsMain/kotlin/Platform.node.kt | 2 +- 20 files changed, 53 insertions(+), 97 deletions(-) delete mode 100644 gateway/src/commonMain/kotlin/Utils.kt delete mode 100644 rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt delete mode 100644 rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt diff --git a/buildSrc/src/main/kotlin/Documentation.kt b/buildSrc/src/main/kotlin/Documentation.kt index 090ed8310b6..92eb73e751c 100644 --- a/buildSrc/src/main/kotlin/Documentation.kt +++ b/buildSrc/src/main/kotlin/Documentation.kt @@ -1,6 +1,6 @@ import org.gradle.kotlin.dsl.assign import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask -import java.net.URL +import java.net.URI fun AbstractDokkaLeafTask.applyKordDokkaOptions() { @@ -16,7 +16,7 @@ fun AbstractDokkaLeafTask.applyKordDokkaOptions() { sourceLink { localDirectory = project.projectDir - remoteUrl = URL("https://github.com/kordlib/kord/blob/${project.commitHash}/${project.name}") + remoteUrl = URI("https://github.com/kordlib/kord/blob/${project.commitHash}/${project.name}").toURL() remoteLineSuffix = "#L" } diff --git a/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts index 3c041c6e387..3ec4029669e 100644 --- a/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts @@ -10,7 +10,7 @@ repositories { @OptIn(ExperimentalKotlinGradlePluginApi::class) kotlin { - targetHierarchy.default() + applyDefaultHierarchyTemplate() jvm() js { nodejs() diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 52c7a1a6f05..a876163a4e6 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -24,8 +24,9 @@ apiValidation { applyKordBCVOptions() } +@OptIn(ExperimentalKotlinGradlePluginApi::class) kotlin { - targetHierarchy.default { + applyDefaultHierarchyTemplate { common { group("nonJvm") { withNative() @@ -66,12 +67,6 @@ kotlin { implementation(project(":test-kit")) } } - val nonJvmMain by creating { - dependsOn(commonMain.get()) - } - jsMain { - dependsOn(nonJvmMain) - } } } diff --git a/common/api/common.api b/common/api/common.api index 18ae0b41cc7..cd62379b349 100644 --- a/common/api/common.api +++ b/common/api/common.api @@ -2626,7 +2626,6 @@ public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetada public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord { public static final field Companion Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$Companion; - public synthetic fun (ILdev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V public fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)V public synthetic fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; @@ -2646,7 +2645,6 @@ public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetada public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; public fun hashCode ()I public fun toString ()Ljava/lang/String; - public static final synthetic fun write$Self (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$$serializer : kotlinx/serialization/internal/GeneratedSerializer { @@ -2682,6 +2680,7 @@ public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetada } public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Companion { + public final fun from (I)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; public final fun getEntries ()Ljava/util/List; public final fun serializer ()Lkotlinx/serialization/KSerializer; } @@ -2711,7 +2710,6 @@ public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetada } public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Unknown : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public fun (I)V } public final class dev/kord/common/entity/DiscordAttachment { diff --git a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt index df3e645a038..93375a7942f 100644 --- a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt +++ b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt @@ -1,6 +1,6 @@ // THIS FILE IS AUTO-GENERATED, DO NOT EDIT! -@file:Suppress(names = arrayOf("RedundantVisibilityModifier", "IncorrectFormatting", - "ReplaceArrayOfWithLiteral", "SpellCheckingInspection", "GrazieInspection")) +@file:Suppress(names = arrayOf("IncorrectFormatting", "ReplaceArrayOfWithLiteral", + "SpellCheckingInspection", "GrazieInspection")) package dev.kord.common.entity @@ -32,7 +32,8 @@ public sealed class DiscordApplicationRoleConnectionMetadataRecordType( final override fun hashCode(): Int = value.hashCode() final override fun toString(): String = - "DiscordApplicationRoleConnectionMetadataRecordType.${this::class.simpleName}(value=$value)" + if (this is Unknown) "DiscordApplicationRoleConnectionMetadataRecordType.Unknown(value=$value)" + else "DiscordApplicationRoleConnectionMetadataRecordType.${this::class.simpleName}" /** * An unknown [DiscordApplicationRoleConnectionMetadataRecordType]. @@ -40,7 +41,7 @@ public sealed class DiscordApplicationRoleConnectionMetadataRecordType( * This is used as a fallback for [DiscordApplicationRoleConnectionMetadataRecordType]s that * haven't been added to Kord yet. */ - public class Unknown( + public class Unknown internal constructor( `value`: Int, ) : DiscordApplicationRoleConnectionMetadataRecordType(value) @@ -98,18 +99,7 @@ public sealed class DiscordApplicationRoleConnectionMetadataRecordType( } override fun deserialize(decoder: Decoder): - DiscordApplicationRoleConnectionMetadataRecordType = - when (val value = decoder.decodeInt()) { - 1 -> IntegerLessThanOrEqual - 2 -> IntegerGreaterThanOrEqual - 3 -> IntegerEqual - 4 -> IntegerNotEqual - 5 -> DateTimeLessThanOrEqual - 6 -> DateTimeGreaterThanOrEqual - 7 -> BooleanEqual - 8 -> BooleanNotEqual - else -> Unknown(value) - } + DiscordApplicationRoleConnectionMetadataRecordType = from(decoder.decodeInt()) } public companion object { @@ -130,5 +120,22 @@ public sealed class DiscordApplicationRoleConnectionMetadataRecordType( ) } + + /** + * Returns an instance of [DiscordApplicationRoleConnectionMetadataRecordType] with + * [DiscordApplicationRoleConnectionMetadataRecordType.value] equal to the specified [value]. + */ + public fun from(`value`: Int): DiscordApplicationRoleConnectionMetadataRecordType = + when (value) { + 1 -> IntegerLessThanOrEqual + 2 -> IntegerGreaterThanOrEqual + 3 -> IntegerEqual + 4 -> IntegerNotEqual + 5 -> DateTimeLessThanOrEqual + 6 -> DateTimeGreaterThanOrEqual + 7 -> BooleanEqual + 8 -> BooleanNotEqual + else -> Unknown(value) + } } } diff --git a/common/src/appleMain/kotlin/HttpEngine.kt b/common/src/appleMain/kotlin/HttpEngine.kt index d43679d2357..945d0d5fb1c 100644 --- a/common/src/appleMain/kotlin/HttpEngine.kt +++ b/common/src/appleMain/kotlin/HttpEngine.kt @@ -6,4 +6,4 @@ import io.ktor.client.engine.darwin.* /** @suppress */ @KordInternal -public actual object HttpEngine: HttpClientEngineFactory by Darwin +public actual fun httpEngine(): HttpClientEngineFactory = Darwin diff --git a/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt b/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt index c1150a053e7..5d9f508b8ec 100644 --- a/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt +++ b/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt @@ -1,45 +1,45 @@ -@file:GenerateKordEnum( +@file:Generate( name = "DiscordApplicationRoleConnectionMetadataRecordType", - valueType = GenerateKordEnum.ValueType.INT, docUrl = "https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type", kDoc = "Type of [DiscordRoleConnectionMetadata] values", + entityType = Generate.EntityType.INT_KORD_ENUM, entries = [ - GenerateKordEnum.Entry( + Generate.Entry( name = "IntegerLessThanOrEqual", intValue = 1, kDoc = "The metadata value (integer) is less than or equal to the guild's configured value (integer)" ), - GenerateKordEnum.Entry( + Generate.Entry( name = "IntegerGreaterThanOrEqual", intValue = 2, kDoc = "The metadata value (integer) is greater than or equal to the guild's configured value (integer)" ), - GenerateKordEnum.Entry( + Generate.Entry( name = "IntegerEqual", intValue = 3, kDoc = "The metadata value (integer) is equal to the guild's configured value (integer)" ), - GenerateKordEnum.Entry( + Generate.Entry( name = "IntegerNotEqual", intValue = 4, kDoc = "The metadata value (integer) is not equal to the guild's configured value (integer)" ), - GenerateKordEnum.Entry( + Generate.Entry( name = "DateTimeLessThanOrEqual", intValue = 5, kDoc = "The metadata value (ISO8601 string) is less than or equal to the guild's configured value (integer; days before current date)" ), - GenerateKordEnum.Entry( + Generate.Entry( name = "DateTimeGreaterThanOrEqual", intValue = 6, kDoc = "The metadata value (ISO8601 string) is greater than or equal to the guild's configured value (integer; days before current date)" ), - GenerateKordEnum.Entry( + Generate.Entry( name = "BooleanEqual", intValue = 7, kDoc = "The metadata value (integer) is equal to the guild's configured value (integer; 1)" ), - GenerateKordEnum.Entry( + Generate.Entry( name = "BooleanNotEqual", intValue = 8, kDoc = "The metadata value (integer) is not equal to the guild's configured value (integer; 1)" @@ -51,7 +51,7 @@ package dev.kord.common.entity import dev.kord.common.Locale import dev.kord.common.entity.optional.Optional -import dev.kord.ksp.GenerateKordEnum +import dev.kord.ksp.Generate import kotlinx.serialization.Serializable /** diff --git a/common/src/mingwMain/kotlin/HttpEngine.kt b/common/src/mingwMain/kotlin/HttpEngine.kt index eb8489d3bed..9c3eb3dc13c 100644 --- a/common/src/mingwMain/kotlin/HttpEngine.kt +++ b/common/src/mingwMain/kotlin/HttpEngine.kt @@ -6,4 +6,4 @@ import io.ktor.client.engine.winhttp.* /** @suppress */ @KordInternal -public actual object HttpEngine : HttpClientEngineFactory by WinHttp +public actual fun httpEngine(): HttpClientEngineFactory = WinHttp diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 1351ed54cd1..aef1219e128 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -33,6 +33,11 @@ kotlin { implementation(libs.kotlin.logging.old) } } + nonJvmMain { + dependencies { + implementation(libs.stately.collections) + } + } jvmMain { dependencies { implementation(libs.slf4j.api) diff --git a/gateway/api/gateway.api b/gateway/api/gateway.api index c16823edfd4..e5cf9c435d2 100644 --- a/gateway/api/gateway.api +++ b/gateway/api/gateway.api @@ -668,7 +668,6 @@ public final class dev/kord/gateway/GatewayConfigurationBuilder { public final class dev/kord/gateway/GatewayKt { public static final fun editPresence (Ldev/kord/gateway/Gateway;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun getGatewayOnLogger ()Lmu/KLogger; public static final fun logCaughtThrowable (Ljava/lang/Throwable;)V public static final fun requestGuildMembers (Ldev/kord/gateway/Gateway;Ldev/kord/common/entity/Snowflake;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow; public static final fun requestGuildMembers (Ldev/kord/gateway/Gateway;Ldev/kord/gateway/RequestGuildMembers;)Lkotlinx/coroutines/flow/Flow; @@ -1875,10 +1874,6 @@ public final class dev/kord/gateway/UserUpdate : dev/kord/gateway/DispatchEvent public fun toString ()Ljava/lang/String; } -public final class dev/kord/gateway/UtilsKt { - public static final fun error (Lmu/KLogger;Ljava/lang/Throwable;)V -} - public final class dev/kord/gateway/VoiceServerUpdate : dev/kord/gateway/DispatchEvent { public fun (Ldev/kord/common/entity/DiscordVoiceServerUpdateData;Ljava/lang/Integer;)V public final fun component1 ()Ldev/kord/common/entity/DiscordVoiceServerUpdateData; diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index 1a0f0c1d718..4d910dce089 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -15,9 +15,6 @@ kotlin { implementation(libs.kotlin.logging) - // TODO remove when gatewayOnLogger and mu.KLogger.error() are removed - implementation(libs.kotlin.logging.old) - compileOnly(projects.kspAnnotations) } } diff --git a/gateway/src/commonMain/kotlin/Gateway.kt b/gateway/src/commonMain/kotlin/Gateway.kt index 577e260e31e..2948b89b5c9 100644 --- a/gateway/src/commonMain/kotlin/Gateway.kt +++ b/gateway/src/commonMain/kotlin/Gateway.kt @@ -139,11 +139,6 @@ public suspend inline fun Gateway.start(token: String, config: GatewayConfigurat start(builder.build()) } -@Suppress("unused") -@Deprecated("Binary compatibility, remove after deprecation cycle.", level = DeprecationLevel.ERROR) -@PublishedApi -internal val gatewayOnLogger: mu.KLogger = mu.KotlinLogging.logger("Gateway.on") - /** * Logger used to report [Throwable]s caught in [Gateway.on]. */ diff --git a/gateway/src/commonMain/kotlin/Utils.kt b/gateway/src/commonMain/kotlin/Utils.kt deleted file mode 100644 index 18cca4075a0..00000000000 --- a/gateway/src/commonMain/kotlin/Utils.kt +++ /dev/null @@ -1,8 +0,0 @@ -package dev.kord.gateway - -import mu.KLogger - -@Suppress("DeprecatedCallableAddReplaceWith") -@Deprecated("Binary compatibility, remove after deprecation cycle.", level = DeprecationLevel.ERROR) -@PublishedApi -internal fun KLogger.error(throwable: Throwable): Unit = error(throwable) { "" } diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index 63bfa922edc..80b4a9abe6c 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -1,6 +1,5 @@ package dev.kord.gateway -import io.ktor.utils.io.core.* import io.ktor.websocket.* import kotlinx.cinterop.* import platform.zlib.* @@ -8,8 +7,10 @@ import platform.zlib.* private const val MAX_WBITS = 15 // Maximum window size in bits private const val CHUNK_SIZE = 256 * 1000 +internal actual fun Inflater(): Inflater = NativeInflater() + @OptIn(ExperimentalForeignApi::class) -internal actual class Inflater : Closeable { +private class NativeInflater : Inflater { private val zStream = nativeHeap.alloc().apply { val initResponse = inflateInit2(ptr, MAX_WBITS) if (initResponse != Z_OK) { @@ -18,7 +19,7 @@ internal actual class Inflater : Closeable { } } - actual fun Frame.inflateData(): String { + override fun Frame.inflateData(): String { val compressedData = data var out = ByteArray(0) memScoped { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d40b0da24a1..916aac36392 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -83,7 +83,6 @@ kotlin-test-junit5 = { module = "org.jetbrains.kotlin:kotlin-test-junit5", versi junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit5" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" } -kotlinx-resources = { module = "com.goncalossilva:resources", version.ref = "kotlinx-resources" } okio = { module = "com.squareup.okio:okio", version.ref = "okio" } # actually plugins, not libraries, but used is 'buildSrc/build.gradle.kts' as implementation dependencies: @@ -94,13 +93,12 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } -kordx-resources-plugin = { module = "com.goncalossilva:resources-plugin", version.ref = "kotlinx-resources" } [bundles] ktor-client-serialization = ["ktor-client-content-negotiation", "ktor-serialization-kotlinx-json"] -test-common = ["kotlin-test-annotations-common", "kotlin-test", "kotlinx-coroutines-test", "kotlinx-resources"] +test-common = ["kotlin-test-annotations-common", "kotlin-test", "kotlinx-coroutines-test"] test-js = ["kotlin-test-js", "kotlin-node"] test-jvm = ["kotlin-test-junit5", "junit-jupiter-engine", "slf4j-simple"] @@ -111,7 +109,6 @@ pluginsForBuildSrc = [ "atomicfu-plugin", "binary-compatibility-validator-plugin", "ksp-plugin", - "kordx-resources-plugin" ] diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 3ad6f3f7202..28defc34c42 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -157,14 +157,6 @@ diff@5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -dukat@0.5.8-rc.4: - version "0.5.8-rc.4" - resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.8-rc.4.tgz#90384dcb50b14c26f0e99dae92b2dea44f5fce21" - integrity sha512-ZnMt6DGBjlVgK2uQamXfd7uP/AxH7RqI0BL9GLrrJb2gKdDxvJChWy+M9AQEaL+7/6TmxzJxFOsRiInY9oGWTA== - dependencies: - google-protobuf "3.12.2" - typescript "3.9.5" - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -249,11 +241,6 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -google-protobuf@3.12.2: - version "3.12.2" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53" - integrity sha512-4CZhpuRr1d6HjlyrxoXoocoGFnRYgKULgMtikMddA9ztRyYR59Aondv2FioyxWVamRo0rF2XpYawkTCBEQOSkA== - has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -533,11 +520,6 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -typescript@3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== - typescript@5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" diff --git a/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt b/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt deleted file mode 100644 index fcb7c50f4b1..00000000000 --- a/rest/src/nativeMain/kotlin/ratelimit/AbstractRateLimiter.kt +++ /dev/null @@ -1,4 +0,0 @@ -package dev.kord.rest.ratelimit - -// https://github.com/Kotlin/kotlinx-atomicfu/issues/291 -internal actual val useUpdate: Boolean = false diff --git a/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt b/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt deleted file mode 100644 index f48a77ecc64..00000000000 --- a/rest/src/nonNativeMain/kotlin/AbstractRateLimiter.kt +++ /dev/null @@ -1,3 +0,0 @@ -package dev.kord.rest.ratelimit - -internal actual val useUpdate: Boolean = true diff --git a/test-kit/src/commonMain/kotlin/Platform.kt b/test-kit/src/commonMain/kotlin/Platform.kt index 6b22bfdf063..9c3e732f129 100644 --- a/test-kit/src/commonMain/kotlin/Platform.kt +++ b/test-kit/src/commonMain/kotlin/Platform.kt @@ -1,7 +1,6 @@ package dev.kord.test import io.ktor.utils.io.* -import com.goncalossilva.resources.Resource expect object Platform { val IS_JVM: Boolean diff --git a/test-kit/src/jsMain/kotlin/Platform.node.kt b/test-kit/src/jsMain/kotlin/Platform.node.kt index 2949105f551..0ed68d8e976 100644 --- a/test-kit/src/jsMain/kotlin/Platform.node.kt +++ b/test-kit/src/jsMain/kotlin/Platform.node.kt @@ -1,7 +1,7 @@ package dev.kord.test import io.ktor.utils.io.* -import js.core.toList +import js.iterable.toList import node.buffer.Buffer import node.buffer.BufferEncoding import node.process.process From e42dbeac03f5810e8cc0951c602428166ecb9687 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Wed, 24 Jan 2024 18:53:03 +0100 Subject: [PATCH 16/83] Remove wrongly added classes --- common/api/common.api | 88 ----------- ...icationRoleConnectionMetadataRecordType.kt | 141 ------------------ .../entity/DiscordRoleConnectionMetadata.kt | 75 ---------- core/api/core.api | 38 ----- .../ApplicationRoleConnectionMetadataData.kt | 39 ----- .../RoleConnectionMetadataRecord.kt | 26 ---- 6 files changed, 407 deletions(-) delete mode 100644 common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt delete mode 100644 common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt delete mode 100644 core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt delete mode 100644 core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt diff --git a/common/api/common.api b/common/api/common.api index cd62379b349..324cfa62fd2 100644 --- a/common/api/common.api +++ b/common/api/common.api @@ -2624,94 +2624,6 @@ public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetada public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord { - public static final field Companion Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$Companion; - public fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)V - public synthetic fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; - public final fun component2 ()Ljava/lang/String; - public final fun component3 ()Ljava/lang/String; - public final fun component4 ()Ldev/kord/common/entity/optional/Optional; - public final fun component5 ()Ljava/lang/String; - public final fun component6 ()Ldev/kord/common/entity/optional/Optional; - public final fun copy (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; - public static synthetic fun copy$default (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILjava/lang/Object;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; - public fun equals (Ljava/lang/Object;)Z - public final fun getDescription ()Ljava/lang/String; - public final fun getDescriptionLocalizations ()Ldev/kord/common/entity/optional/Optional; - public final fun getKey ()Ljava/lang/String; - public final fun getName ()Ljava/lang/String; - public final fun getNameLocalizations ()Ldev/kord/common/entity/optional/Optional; - public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$$serializer : kotlinx/serialization/internal/GeneratedSerializer { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$$serializer; - public fun childSerializers ()[Lkotlinx/serialization/KSerializer; - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord; - public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;)V - public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V - public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord$Companion { - public final fun serializer ()Lkotlinx/serialization/KSerializer; -} - -public abstract class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field Companion Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Companion; - public synthetic fun (ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun equals (Ljava/lang/Object;)Z - public final fun getValue ()I - public final fun hashCode ()I - public final fun toString ()Ljava/lang/String; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanEqual; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanNotEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$BooleanNotEqual; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Companion { - public final fun from (I)Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; - public final fun getEntries ()Ljava/util/List; - public final fun serializer ()Lkotlinx/serialization/KSerializer; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeGreaterThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeGreaterThanOrEqual; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeLessThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$DateTimeLessThanOrEqual; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerEqual; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerGreaterThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerGreaterThanOrEqual; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerLessThanOrEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerLessThanOrEqual; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerNotEqual : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { - public static final field INSTANCE Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$IntegerNotEqual; -} - -public final class dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType$Unknown : dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType { -} - public final class dev/kord/common/entity/DiscordAttachment { public static final field Companion Ldev/kord/common/entity/DiscordAttachment$Companion; public fun (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;ILjava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalBoolean;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;)V diff --git a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt b/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt deleted file mode 100644 index 93375a7942f..00000000000 --- a/common/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType.kt +++ /dev/null @@ -1,141 +0,0 @@ -// THIS FILE IS AUTO-GENERATED, DO NOT EDIT! -@file:Suppress(names = arrayOf("IncorrectFormatting", "ReplaceArrayOfWithLiteral", - "SpellCheckingInspection", "GrazieInspection")) - -package dev.kord.common.entity - -import kotlin.LazyThreadSafetyMode.PUBLICATION -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.descriptors.PrimitiveKind -import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder - -/** - * Type of [DiscordRoleConnectionMetadata] values - * - * See [DiscordApplicationRoleConnectionMetadataRecordType]s in the - * [Discord Developer Documentation](https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type). - */ -@Serializable(with = DiscordApplicationRoleConnectionMetadataRecordType.Serializer::class) -public sealed class DiscordApplicationRoleConnectionMetadataRecordType( - /** - * The raw value used by Discord. - */ - public val `value`: Int, -) { - final override fun equals(other: Any?): Boolean = this === other || - (other is DiscordApplicationRoleConnectionMetadataRecordType && this.value == other.value) - - final override fun hashCode(): Int = value.hashCode() - - final override fun toString(): String = - if (this is Unknown) "DiscordApplicationRoleConnectionMetadataRecordType.Unknown(value=$value)" - else "DiscordApplicationRoleConnectionMetadataRecordType.${this::class.simpleName}" - - /** - * An unknown [DiscordApplicationRoleConnectionMetadataRecordType]. - * - * This is used as a fallback for [DiscordApplicationRoleConnectionMetadataRecordType]s that - * haven't been added to Kord yet. - */ - public class Unknown internal constructor( - `value`: Int, - ) : DiscordApplicationRoleConnectionMetadataRecordType(value) - - /** - * The metadata value (integer) is less than or equal to the guild's configured value (integer) - */ - public object IntegerLessThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(1) - - /** - * The metadata value (integer) is greater than or equal to the guild's configured value - * (integer) - */ - public object IntegerGreaterThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(2) - - /** - * The metadata value (integer) is equal to the guild's configured value (integer) - */ - public object IntegerEqual : DiscordApplicationRoleConnectionMetadataRecordType(3) - - /** - * The metadata value (integer) is not equal to the guild's configured value (integer) - */ - public object IntegerNotEqual : DiscordApplicationRoleConnectionMetadataRecordType(4) - - /** - * The metadata value (ISO8601 string) is less than or equal to the guild's configured value - * (integer; days before current date) - */ - public object DateTimeLessThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(5) - - /** - * The metadata value (ISO8601 string) is greater than or equal to the guild's configured value - * (integer; days before current date) - */ - public object DateTimeGreaterThanOrEqual : DiscordApplicationRoleConnectionMetadataRecordType(6) - - /** - * The metadata value (integer) is equal to the guild's configured value (integer; 1) - */ - public object BooleanEqual : DiscordApplicationRoleConnectionMetadataRecordType(7) - - /** - * The metadata value (integer) is not equal to the guild's configured value (integer; 1) - */ - public object BooleanNotEqual : DiscordApplicationRoleConnectionMetadataRecordType(8) - - internal object Serializer : KSerializer { - override val descriptor: SerialDescriptor = - PrimitiveSerialDescriptor("dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType", - PrimitiveKind.INT) - - override fun serialize(encoder: Encoder, - `value`: DiscordApplicationRoleConnectionMetadataRecordType) { - encoder.encodeInt(value.value) - } - - override fun deserialize(decoder: Decoder): - DiscordApplicationRoleConnectionMetadataRecordType = from(decoder.decodeInt()) - } - - public companion object { - /** - * A [List] of all known [DiscordApplicationRoleConnectionMetadataRecordType]s. - */ - public val entries: List by - lazy(mode = PUBLICATION) { - listOf( - IntegerLessThanOrEqual, - IntegerGreaterThanOrEqual, - IntegerEqual, - IntegerNotEqual, - DateTimeLessThanOrEqual, - DateTimeGreaterThanOrEqual, - BooleanEqual, - BooleanNotEqual, - ) - } - - - /** - * Returns an instance of [DiscordApplicationRoleConnectionMetadataRecordType] with - * [DiscordApplicationRoleConnectionMetadataRecordType.value] equal to the specified [value]. - */ - public fun from(`value`: Int): DiscordApplicationRoleConnectionMetadataRecordType = - when (value) { - 1 -> IntegerLessThanOrEqual - 2 -> IntegerGreaterThanOrEqual - 3 -> IntegerEqual - 4 -> IntegerNotEqual - 5 -> DateTimeLessThanOrEqual - 6 -> DateTimeGreaterThanOrEqual - 7 -> BooleanEqual - 8 -> BooleanNotEqual - else -> Unknown(value) - } - } -} diff --git a/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt b/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt deleted file mode 100644 index 5d9f508b8ec..00000000000 --- a/common/src/commonMain/kotlin/entity/DiscordRoleConnectionMetadata.kt +++ /dev/null @@ -1,75 +0,0 @@ -@file:Generate( - name = "DiscordApplicationRoleConnectionMetadataRecordType", - docUrl = "https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type", - kDoc = "Type of [DiscordRoleConnectionMetadata] values", - entityType = Generate.EntityType.INT_KORD_ENUM, - entries = [ - Generate.Entry( - name = "IntegerLessThanOrEqual", - intValue = 1, - kDoc = "The metadata value (integer) is less than or equal to the guild's configured value (integer)" - ), - Generate.Entry( - name = "IntegerGreaterThanOrEqual", - intValue = 2, - kDoc = "The metadata value (integer) is greater than or equal to the guild's configured value (integer)" - ), - Generate.Entry( - name = "IntegerEqual", - intValue = 3, - kDoc = "The metadata value (integer) is equal to the guild's configured value (integer)" - ), - Generate.Entry( - name = "IntegerNotEqual", - intValue = 4, - kDoc = "The metadata value (integer) is not equal to the guild's configured value (integer)" - ), - Generate.Entry( - name = "DateTimeLessThanOrEqual", - intValue = 5, - kDoc = "The metadata value (ISO8601 string) is less than or equal to the guild's configured value (integer; days before current date)" - ), - Generate.Entry( - name = "DateTimeGreaterThanOrEqual", - intValue = 6, - kDoc = "The metadata value (ISO8601 string) is greater than or equal to the guild's configured value (integer; days before current date)" - ), - Generate.Entry( - name = "BooleanEqual", - intValue = 7, - kDoc = "The metadata value (integer) is equal to the guild's configured value (integer; 1)" - ), - Generate.Entry( - name = "BooleanNotEqual", - intValue = 8, - kDoc = "The metadata value (integer) is not equal to the guild's configured value (integer; 1)" - ) - ] -) - -package dev.kord.common.entity - -import dev.kord.common.Locale -import dev.kord.common.entity.optional.Optional -import dev.kord.ksp.Generate -import kotlinx.serialization.Serializable - -/** - * A representation of role connection metadata for an [application][DiscordApplication]. - * - * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value - * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) - * @property name name of the metadata field (1-100 characters) - * @property nameLocalizations with keys in available locales translations of the name - * @property description description of the metadata field (1-200 characters) - * @property descriptionLocalizations with keys in available locales translations of the description - */ -@Serializable -public data class DiscordApplicationRoleConnectionMetadataRecord( - val type: DiscordApplicationRoleConnectionMetadataRecordType, - val key: String, - val name: String, - val nameLocalizations: Optional> = Optional.Missing(), - val description: String, - val descriptionLocalizations: Optional> = Optional.Missing() -) diff --git a/core/api/core.api b/core/api/core.api index 96a0de18cf6..a535d1f6dd6 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -2680,33 +2680,6 @@ public final class dev/kord/core/cache/data/ApplicationInteractionData$Companion public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class dev/kord/core/cache/data/ApplicationRoleConnectionMetadataData { - public static final field Companion Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData$Companion; - public fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)V - public synthetic fun (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; - public final fun component2 ()Ljava/lang/String; - public final fun component3 ()Ljava/lang/String; - public final fun component4 ()Ldev/kord/common/entity/optional/Optional; - public final fun component5 ()Ljava/lang/String; - public final fun component6 ()Ldev/kord/common/entity/optional/Optional; - public final fun copy (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; - public static synthetic fun copy$default (Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData;Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType;Ljava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;ILjava/lang/Object;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; - public fun equals (Ljava/lang/Object;)Z - public final fun getDescription ()Ljava/lang/String; - public final fun getDescriptionLocalizations ()Ldev/kord/common/entity/optional/Optional; - public final fun getKey ()Ljava/lang/String; - public final fun getName ()Ljava/lang/String; - public final fun getNameLocalizations ()Ldev/kord/common/entity/optional/Optional; - public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class dev/kord/core/cache/data/ApplicationRoleConnectionMetadataData$Companion { - public final fun from (Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecord;)Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; -} - public final class dev/kord/core/cache/data/AttachmentData { public static final field Companion Ldev/kord/core/cache/data/AttachmentData$Companion; public fun (Ldev/kord/common/entity/Snowflake;Ljava/lang/String;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;ILjava/lang/String;Ljava/lang/String;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalInt;Ldev/kord/common/entity/optional/OptionalBoolean;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;Ldev/kord/common/entity/optional/Optional;)V @@ -7518,17 +7491,6 @@ public final class dev/kord/core/entity/application/MessageCommand$DefaultImpls public static fun isNsfw (Ldev/kord/core/entity/application/MessageCommand;)Z } -public final class dev/kord/core/entity/application/RoleConnectionMetadataRecord { - public fun (Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData;)V - public final fun getData ()Ldev/kord/core/cache/data/ApplicationRoleConnectionMetadataData; - public final fun getDescription ()Ljava/lang/String; - public final fun getDescriptionLocalizations ()Ljava/util/Map; - public final fun getKey ()Ljava/lang/String; - public final fun getName ()Ljava/lang/String; - public final fun getNameLocalizations ()Ljava/util/Map; - public final fun getType ()Ldev/kord/common/entity/DiscordApplicationRoleConnectionMetadataRecordType; -} - public final class dev/kord/core/entity/application/UnknownGlobalApplicationCommand : dev/kord/core/entity/application/GlobalApplicationCommand { public fun (Ldev/kord/core/cache/data/ApplicationCommandData;Ldev/kord/rest/service/InteractionService;)V public fun compareTo (Ldev/kord/core/entity/Entity;)I diff --git a/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt b/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt deleted file mode 100644 index fd3faf8a2c5..00000000000 --- a/core/src/commonMain/kotlin/cache/data/ApplicationRoleConnectionMetadataData.kt +++ /dev/null @@ -1,39 +0,0 @@ -package dev.kord.core.cache.data - -import dev.kord.common.Locale -import dev.kord.common.entity.DiscordApplication -import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecord -import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType -import dev.kord.common.entity.optional.Optional - -/** - * A representation of role connection metadata for an [application][DiscordApplication]. - * - * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value - * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) - * @property name name of the metadata field (1-100 characters) - * @property nameLocalizations with keys in available locales translations of the name - * @property description description of the metadata field (1-200 characters) - * @property descriptionLocalizations with keys in available locales translations of the description - */ - -public data class ApplicationRoleConnectionMetadataData( - val type: DiscordApplicationRoleConnectionMetadataRecordType, - val key: String, - val name: String, - val nameLocalizations: Optional> = Optional.Missing(), - val description: String, - val descriptionLocalizations: Optional> = Optional.Missing() -) { - public companion object { - public fun from(record: DiscordApplicationRoleConnectionMetadataRecord): ApplicationRoleConnectionMetadataData = - ApplicationRoleConnectionMetadataData( - record.type, - record.key, - record.name, - record.nameLocalizations, - record.description, - record.descriptionLocalizations - ) - } -} diff --git a/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt b/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt deleted file mode 100644 index d3d9c77d673..00000000000 --- a/core/src/commonMain/kotlin/entity/application/RoleConnectionMetadataRecord.kt +++ /dev/null @@ -1,26 +0,0 @@ -package dev.kord.core.entity.application - -import dev.kord.common.Locale -import dev.kord.common.entity.DiscordApplicationRoleConnectionMetadataRecordType -import dev.kord.core.cache.data.ApplicationRoleConnectionMetadataData - -/** - * A representation of role connection metadata for an [application][Application]. - * - * @property type [type][DiscordApplicationRoleConnectionMetadataRecordType] of metadata value - * @property key dictionary key for the metadata field (must be a-z, 0-9, or _ characters; 1-50 characters) - * @property name name of the metadata field (1-100 characters) - * @property nameLocalizations with keys in available locales translations of the name - * @property description description of the metadata field (1-200 characters) - * @property descriptionLocalizations with keys in available locales translations of the description - */ -public class RoleConnectionMetadataRecord(public val data: ApplicationRoleConnectionMetadataData) { - public val type: DiscordApplicationRoleConnectionMetadataRecordType get() = data.type - public val key: String get() = data.key - public val name: String get() = data.name - public val nameLocalizations: Map - get() = data.nameLocalizations.value ?: emptyMap() - public val description: String get() = data.description - public val descriptionLocalizations: Map - get() = data.nameLocalizations.value ?: emptyMap() -} From 640141dda93f01305a5d20154e746209fd44752e Mon Sep 17 00:00:00 2001 From: schlaubi Date: Wed, 24 Jan 2024 19:17:04 +0100 Subject: [PATCH 17/83] Linux support - Create actuals - Switch to kotlinx.io as it supports arm --- .../main/kotlin/kord-native-module.gradle.kts | 5 +++-- common/src/linuxMain/kotlin/HttpEngine.kt | 2 +- gradle/libs.versions.toml | 4 ++-- test-kit/build.gradle.kts | 2 +- test-kit/src/nativeMain/kotlin/Platform.kt | 22 +++++++------------ 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index 3283be52e6e..70ec4e98465 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -5,14 +5,15 @@ plugins { } kotlin { + // There are issues with compiling the linux variant on linux + // Please use WSL if you need to work on the linux port if(!Os.isFamily(Os.FAMILY_WINDOWS)) { linuxX64() // Waiting for Ktor - // https://youtrack.jetbrains.com/issue/KTOR-872 + // https://youtrack.jetbrains.com/issue/KTOR-6173 //linuxArm64() } - mingwX64() macosArm64() diff --git a/common/src/linuxMain/kotlin/HttpEngine.kt b/common/src/linuxMain/kotlin/HttpEngine.kt index f38a8a9aba8..f0cdf5c7018 100644 --- a/common/src/linuxMain/kotlin/HttpEngine.kt +++ b/common/src/linuxMain/kotlin/HttpEngine.kt @@ -6,4 +6,4 @@ import io.ktor.client.engine.curl.* /** @suppress */ @KordInternal -public actual object HttpEngine : HttpClientEngineFactory by Curl +public actual fun httpEngine(): HttpClientEngineFactory = Curl diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 916aac36392..2bf5c5f005a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ kotlinpoet = "1.15.3" # https://github.com/square/kotlinpoet junit5 = "5.10.1" # https://github.com/junit-team/junit5 mockk = "1.13.8" # https://github.com/mockk/mockk slf4j = "2.0.9" # https://www.slf4j.org -okio = "3.5.0" +kotlinx-io = "0.3.0" # https://github.com/Kotlin/kotlinx-io/ # plugins dokka = "1.9.10" # https://github.com/Kotlin/dokka @@ -83,7 +83,7 @@ kotlin-test-junit5 = { module = "org.jetbrains.kotlin:kotlin-test-junit5", versi junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit5" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" } -okio = { module = "com.squareup.okio:okio", version.ref = "okio" } +kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" } # actually plugins, not libraries, but used is 'buildSrc/build.gradle.kts' as implementation dependencies: # https://docs.gradle.org/current/userguide/custom_plugins.html#applying_external_plugins_in_precompiled_script_plugins diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index 40f52c38294..d924f089e5a 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -23,7 +23,7 @@ kotlin { } nativeMain { dependencies { - api(libs.okio) + api(libs.kotlinx.io) } } } diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt index 82e6e61381b..71d88fed0d8 100644 --- a/test-kit/src/nativeMain/kotlin/Platform.kt +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -5,10 +5,9 @@ package dev.kord.test import io.ktor.utils.io.* import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.toKString -import okio.BufferedSource -import okio.FileSystem -import okio.IOException -import okio.Path.Companion.toPath +import kotlinx.io.* +import kotlinx.io.files.Path +import kotlinx.io.files.SystemFileSystem import platform.posix.getenv import kotlin.experimental.ExperimentalNativeApi import kotlin.native.Platform @@ -27,22 +26,17 @@ actual object Platform { @OptIn(ExperimentalForeignApi::class) actual fun getEnv(name: String) = getenv(name)?.toKString() -private fun actutalPath(path: String) = - "src/commonTest/resources/$path".toPath() - -actual suspend fun file(project: String, path: String): String = read(path, BufferedSource::readUtf8) +actual suspend fun file(project: String, path: String): String = read(path, Source::readString) actual suspend fun readFile(project: String, path: String): ByteReadChannel = read(path) { ByteReadChannel(readByteArray()) } -private inline fun read(path: String, readerAction: BufferedSource.() -> T): T { - val actualPath = actutalPath(path) +private inline fun read(path: String, readerAction: Source.() -> T): T { + val actualPath = Path(path) return try { - FileSystem.SYSTEM.read(actualPath, readerAction) + SystemFileSystem.source(actualPath).buffered().readerAction() } catch (e: Throwable) { - val pwd = FileSystem.SYSTEM.canonicalize(".".toPath()) - val absolutePath = pwd / actualPath - throw FileNotFoundException(absolutePath.toString(), e) + throw FileNotFoundException(actualPath.toString(), e) } } From 9cbd7d7cc7f2c3f7cc7ac8ee547fe0b279982371 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Wed, 24 Jan 2024 19:22:43 +0100 Subject: [PATCH 18/83] Code cleanup --- common/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 910c9993806..9de88e5ddd4 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -58,7 +58,7 @@ kotlin { } } - findByName("linuxMain")?.apply { + linuxMain { dependencies { api(libs.ktor.client.curl) } From bb2acbe5478a9912ca390546156e6d040f979a95 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Thu, 25 Jan 2024 19:20:42 +0100 Subject: [PATCH 19/83] Add voice support on native --- build.gradle.kts | 2 + buildSrc/src/main/kotlin/Compiler.kt | 2 +- .../kord-multiplatform-module.gradle.kts | 7 +- .../main/kotlin/kord-native-module.gradle.kts | 7 +- core-voice/build.gradle.kts | 15 +++-- .../BaseVoiceChannelBehaviorExtensions.kt | 1 + core/build.gradle.kts | 3 - .../kotlin/builder/kord/KordBuilder.kt | 3 +- .../kotlin/DefaultGatewayBuilder.kt | 5 -- gradle/libs.versions.toml | 6 +- samples/build.gradle.kts | 32 +++++++++ .../jvmMain/resources/simplelogger.properties | 1 + samples/src/voiceMain/kotlin/VoiceBot.kt | 52 +++++++++++++++ voice/build.gradle.kts | 34 ++++++---- .../kotlin/dev/kord/voice/EncryptionMode.kt | 0 .../kotlin/dev/kord/voice/SpeakingFlag.kt | 0 .../{main => commonMain}/kotlin/AudioFrame.kt | 1 + .../kotlin/AudioProvider.kt | 0 .../kotlin/DefaultFrameInterceptor.kt | 0 .../kotlin/EncryptionMode.kt | 0 .../kotlin/FrameInterceptor.kt | 0 .../kotlin/SpeakingFlag.kt | 0 .../kotlin/VoiceConnection.kt | 0 .../kotlin/VoiceConnectionBuilder.kt | 0 .../strategies/LiteNonceStrategy.kt | 0 .../encryption/strategies/NonceStrategy.kt | 0 .../strategies/NormalNonceStrategy.kt | 0 .../strategies/SuffixNonceStrategy.kt | 0 .../VoiceConnectionInitializationException.kt | 0 .../kotlin/gateway/Command.kt | 0 .../kotlin/gateway/DefaultVoiceGateway.kt | 5 +- .../gateway/DefaultVoiceGatewayBuilder.kt | 9 +-- .../kotlin/gateway/OpCode.kt | 0 .../kotlin/gateway/Ticker.kt | 0 .../kotlin/gateway/VoiceEvent.kt | 0 .../kotlin/gateway/VoiceGateway.kt | 5 -- .../gateway/VoiceGatewayConfiguration.kt | 0 .../gateway/handler/GatewayEventHandler.kt | 0 .../gateway/handler/HandshakeHandler.kt | 0 .../gateway/handler/HeartbeatHandler.kt | 0 .../kotlin/handlers/ConnectionEventHandler.kt | 0 .../kotlin/handlers/StreamsHandler.kt | 0 .../kotlin/handlers/UdpLifeCycleHandler.kt | 0 .../handlers/VoiceUpdateEventHandler.kt | 0 .../kotlin/io/ByteArrayCursors.kt | 0 .../kotlin/io/ByteArrayView.kt | 4 +- .../kotlin/streams/DefaultStreams.kt | 42 ++---------- .../kotlin/streams/NOPStreams.kt | 0 .../kotlin/streams/Streams.kt | 0 .../kotlin/udp/AudioFrameSender.kt | 0 .../kotlin/udp/AudioPacketProvider.kt | 23 +++++++ .../kotlin/udp/DefaultAudioFrameSender.kt | 0 .../kotlin/udp/GlobalVoiceUdpSocket.kt | 3 +- .../kotlin/udp/PayloadType.kt | 4 +- .../kotlin/udp/RTPPacket.kt | 0 .../kotlin/udp/VoiceUdpSocket.kt | 0 .../java/com/iwebpp/crypto/TweetNaclFast.java | 0 .../encryption/XSalsa20Poly1305Codec.kt | 2 +- .../encryption/XSalsa20Poly1305Encryption.kt | 1 + .../dev/kord/voice/streams/DefaultStreams.kt | 45 +++++++++++++ .../voice/udp/DefaultAudioPacketProvider.kt} | 18 ++--- .../dev/kord/voice/streams/DefaultStreams.kt | 28 ++++++++ .../voice/udp/DefaultAudioPacketProvider.kt | 65 +++++++++++++++++++ 63 files changed, 321 insertions(+), 104 deletions(-) rename core-voice/src/{main => commonMain}/kotlin/BaseVoiceChannelBehaviorExtensions.kt (97%) create mode 100644 samples/src/jvmMain/resources/simplelogger.properties create mode 100644 samples/src/voiceMain/kotlin/VoiceBot.kt rename voice/build/generated/ksp/{main => metadata/commonMain}/kotlin/dev/kord/voice/EncryptionMode.kt (100%) rename voice/build/generated/ksp/{main => metadata/commonMain}/kotlin/dev/kord/voice/SpeakingFlag.kt (100%) rename voice/src/{main => commonMain}/kotlin/AudioFrame.kt (94%) rename voice/src/{main => commonMain}/kotlin/AudioProvider.kt (100%) rename voice/src/{main => commonMain}/kotlin/DefaultFrameInterceptor.kt (100%) rename voice/src/{main => commonMain}/kotlin/EncryptionMode.kt (100%) rename voice/src/{main => commonMain}/kotlin/FrameInterceptor.kt (100%) rename voice/src/{main => commonMain}/kotlin/SpeakingFlag.kt (100%) rename voice/src/{main => commonMain}/kotlin/VoiceConnection.kt (100%) rename voice/src/{main => commonMain}/kotlin/VoiceConnectionBuilder.kt (100%) rename voice/src/{main => commonMain}/kotlin/encryption/strategies/LiteNonceStrategy.kt (100%) rename voice/src/{main => commonMain}/kotlin/encryption/strategies/NonceStrategy.kt (100%) rename voice/src/{main => commonMain}/kotlin/encryption/strategies/NormalNonceStrategy.kt (100%) rename voice/src/{main => commonMain}/kotlin/encryption/strategies/SuffixNonceStrategy.kt (100%) rename voice/src/{main => commonMain}/kotlin/exception/VoiceConnectionInitializationException.kt (100%) rename voice/src/{main => commonMain}/kotlin/gateway/Command.kt (100%) rename voice/src/{main => commonMain}/kotlin/gateway/DefaultVoiceGateway.kt (98%) rename voice/src/{main => commonMain}/kotlin/gateway/DefaultVoiceGatewayBuilder.kt (81%) rename voice/src/{main => commonMain}/kotlin/gateway/OpCode.kt (100%) rename voice/src/{main => commonMain}/kotlin/gateway/Ticker.kt (100%) rename voice/src/{main => commonMain}/kotlin/gateway/VoiceEvent.kt (100%) rename voice/src/{main => commonMain}/kotlin/gateway/VoiceGateway.kt (96%) rename voice/src/{main => commonMain}/kotlin/gateway/VoiceGatewayConfiguration.kt (100%) rename voice/src/{main => commonMain}/kotlin/gateway/handler/GatewayEventHandler.kt (100%) rename voice/src/{main => commonMain}/kotlin/gateway/handler/HandshakeHandler.kt (100%) rename voice/src/{main => commonMain}/kotlin/gateway/handler/HeartbeatHandler.kt (100%) rename voice/src/{main => commonMain}/kotlin/handlers/ConnectionEventHandler.kt (100%) rename voice/src/{main => commonMain}/kotlin/handlers/StreamsHandler.kt (100%) rename voice/src/{main => commonMain}/kotlin/handlers/UdpLifeCycleHandler.kt (100%) rename voice/src/{main => commonMain}/kotlin/handlers/VoiceUpdateEventHandler.kt (100%) rename voice/src/{main => commonMain}/kotlin/io/ByteArrayCursors.kt (100%) rename voice/src/{main => commonMain}/kotlin/io/ByteArrayView.kt (95%) rename voice/src/{main => commonMain}/kotlin/streams/DefaultStreams.kt (71%) rename voice/src/{main => commonMain}/kotlin/streams/NOPStreams.kt (100%) rename voice/src/{main => commonMain}/kotlin/streams/Streams.kt (100%) rename voice/src/{main => commonMain}/kotlin/udp/AudioFrameSender.kt (100%) create mode 100644 voice/src/commonMain/kotlin/udp/AudioPacketProvider.kt rename voice/src/{main => commonMain}/kotlin/udp/DefaultAudioFrameSender.kt (100%) rename voice/src/{main => commonMain}/kotlin/udp/GlobalVoiceUdpSocket.kt (95%) rename voice/src/{main => commonMain}/kotlin/udp/PayloadType.kt (78%) rename voice/src/{main => commonMain}/kotlin/udp/RTPPacket.kt (100%) rename voice/src/{main => commonMain}/kotlin/udp/VoiceUdpSocket.kt (100%) rename voice/src/{main => jvmMain}/java/com/iwebpp/crypto/TweetNaclFast.java (100%) rename voice/src/{main/kotlin => jvmMain/kotlin/dev/kord/voice}/encryption/XSalsa20Poly1305Codec.kt (99%) rename voice/src/{main/kotlin => jvmMain/kotlin/dev/kord/voice}/encryption/XSalsa20Poly1305Encryption.kt (99%) create mode 100644 voice/src/jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt rename voice/src/{main/kotlin/udp/AudioPacketProvider.kt => jvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt} (72%) create mode 100644 voice/src/nonJvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt create mode 100644 voice/src/nonJvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt diff --git a/build.gradle.kts b/build.gradle.kts index be333e43178..8bbf38fe3ce 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,6 +4,8 @@ plugins { allprojects { repositories { + // TODO: Remove wants https://github.com/ktorio/ktor/pull/3950 lands + mavenLocal() mavenCentral() maven("https://oss.sonatype.org/content/repositories/snapshots/") } diff --git a/buildSrc/src/main/kotlin/Compiler.kt b/buildSrc/src/main/kotlin/Compiler.kt index 1b8e9f10ac6..fe1d1187f0b 100644 --- a/buildSrc/src/main/kotlin/Compiler.kt +++ b/buildSrc/src/main/kotlin/Compiler.kt @@ -25,7 +25,7 @@ object Jvm { } fun KotlinCommonCompilerOptions.applyKordCompilerOptions() { - allWarningsAsErrors = true +// allWarningsAsErrors = true progressiveMode = true freeCompilerArgs.add("-Xexpect-actual-classes") } diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index a876163a4e6..2a054a6cb54 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -43,8 +43,11 @@ kotlin { explicitApi() jvm() - js { - nodejs() + + if (name != "voice" && name != "core-voice") { + js { + nodejs() + } } jvmToolchain(Jvm.target) diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index 70ec4e98465..dfe78f434ea 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -7,14 +7,16 @@ plugins { kotlin { // There are issues with compiling the linux variant on linux // Please use WSL if you need to work on the linux port - if(!Os.isFamily(Os.FAMILY_WINDOWS)) { + if (!Os.isFamily(Os.FAMILY_WINDOWS)) { linuxX64() // Waiting for Ktor // https://youtrack.jetbrains.com/issue/KTOR-6173 //linuxArm64() } - mingwX64() + if (name != "voice" && name != "core-voice") { + mingwX64() + } macosArm64() macosX64() @@ -23,7 +25,6 @@ kotlin { iosX64() iosSimulatorArm64() - watchosX64() watchosArm64() watchosSimulatorArm64() diff --git a/core-voice/build.gradle.kts b/core-voice/build.gradle.kts index 356fca4c82b..412df014aa5 100644 --- a/core-voice/build.gradle.kts +++ b/core-voice/build.gradle.kts @@ -1,9 +1,16 @@ plugins { - `kord-module` + `kord-native-module` + `kord-multiplatform-module` `kord-publishing` } -dependencies { - api(projects.core) - api(projects.voice) +kotlin { + sourceSets { + commonMain { + dependencies { + api(projects.core) + api(projects.voice) + } + } + } } diff --git a/core-voice/src/main/kotlin/BaseVoiceChannelBehaviorExtensions.kt b/core-voice/src/commonMain/kotlin/BaseVoiceChannelBehaviorExtensions.kt similarity index 97% rename from core-voice/src/main/kotlin/BaseVoiceChannelBehaviorExtensions.kt rename to core-voice/src/commonMain/kotlin/BaseVoiceChannelBehaviorExtensions.kt index c6da181516d..35e8025a8ba 100644 --- a/core-voice/src/main/kotlin/BaseVoiceChannelBehaviorExtensions.kt +++ b/core-voice/src/commonMain/kotlin/BaseVoiceChannelBehaviorExtensions.kt @@ -7,6 +7,7 @@ import dev.kord.core.entity.channel.VoiceChannel import dev.kord.core.exception.GatewayNotFoundException import dev.kord.voice.VoiceConnection import dev.kord.voice.VoiceConnectionBuilder +import kotlin.jvm.JvmName /** * Connect to this [VoiceChannel] and create a [VoiceConnection] for this voice session. diff --git a/core/build.gradle.kts b/core/build.gradle.kts index aef1219e128..ce80e43443d 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -28,9 +28,6 @@ kotlin { api(libs.kord.cache.map) implementation(libs.kotlin.logging) - - // TODO remove when kordLogger is removed - implementation(libs.kotlin.logging.old) } } nonJvmMain { diff --git a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt index c9c1cafc536..934e9a71c26 100644 --- a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt +++ b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt @@ -49,7 +49,8 @@ public abstract class BaseKordBuilder internal constructor(public val token: Str val rateLimiter = IdentifyRateLimiter(resources.maxConcurrency, defaultDispatcher) shards.map { DefaultGateway { - client = resources.httpClient + // Workaround for: https://github.com/ktorio/ktor/pull/3950#issuecomment-1909088751 + // client = resources.httpClient identifyRateLimiter = rateLimiter } } diff --git a/gateway/src/commonMain/kotlin/DefaultGatewayBuilder.kt b/gateway/src/commonMain/kotlin/DefaultGatewayBuilder.kt index 7dd8febc9cc..ac88ec36ced 100644 --- a/gateway/src/commonMain/kotlin/DefaultGatewayBuilder.kt +++ b/gateway/src/commonMain/kotlin/DefaultGatewayBuilder.kt @@ -8,9 +8,7 @@ import dev.kord.gateway.ratelimit.IdentifyRateLimiter import dev.kord.gateway.retry.LinearRetry import dev.kord.gateway.retry.Retry import io.ktor.client.* -import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.plugins.websocket.* -import io.ktor.serialization.kotlinx.json.* import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableSharedFlow @@ -29,9 +27,6 @@ public class DefaultGatewayBuilder { public fun build(): DefaultGateway { val client = client ?: HttpClient(httpEngine()) { install(WebSockets) - install(ContentNegotiation) { - json() - } } val retry = reconnectRetry ?: LinearRetry(2.seconds, 20.seconds, 10) val sendRateLimiter = sendRateLimiter ?: IntervalRateLimiter(limit = 120, interval = 60.seconds) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2bf5c5f005a..457f5269654 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ # api dependencies kotlin = "1.9.21" # https://github.com/JetBrains/kotlin -ktor = "2.3.7" # https://github.com/ktorio/ktor +ktor = "3.0.0-beta-1" # https://github.com/ktorio/ktor kotlinx-coroutines = "1.7.3" # https://github.com/Kotlin/kotlinx.coroutines kotlinx-serialization = "1.6.2" # https://github.com/Kotlin/kotlinx.serialization kotlinx-datetime = "0.5.0" # https://github.com/Kotlin/kotlinx-datetime @@ -16,6 +16,7 @@ kotlin-node = "18.16.12-pre.619" # https://github.com/JetBrains/kotlin-wrappers bignum = "0.3.8" # https://github.com/ionspin/kotlin-multiplatform-bignum stately = "2.0.6" # https://github.com/touchlab/Stately fastZlib = "2.0.1" # https://github.com/timotejroiko/fast-zlib +sodium = "0.9.0" # https://github.com/ionspin/kotlin-multiplatform-libsodium # code generation ksp = "1.9.21-1.0.16" # https://github.com/google/ksp @@ -24,7 +25,7 @@ kotlinpoet = "1.15.3" # https://github.com/square/kotlinpoet # tests junit5 = "5.10.1" # https://github.com/junit-team/junit5 mockk = "1.13.8" # https://github.com/mockk/mockk -slf4j = "2.0.9" # https://www.slf4j.org +slf4j = "2.0.11" # https://www.slf4j.org kotlinx-io = "0.3.0" # https://github.com/Kotlin/kotlinx-io/ # plugins @@ -69,6 +70,7 @@ kotlin-node = { module = "org.jetbrains.kotlin-wrappers:kotlin-node", version.re # JDK replacements bignum = { module = "com.ionspin.kotlin:bignum", version.ref = "bignum" } stately-collections = { module = "co.touchlab:stately-concurrent-collections", version.ref = "stately" } +libsodium = { module = "com.ionspin.kotlin:multiplatform-crypto-libsodium-bindings", version.ref = "sodium" } # code generation ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } diff --git a/samples/build.gradle.kts b/samples/build.gradle.kts index 2e16a83d74d..44344065abf 100644 --- a/samples/build.gradle.kts +++ b/samples/build.gradle.kts @@ -1,16 +1,37 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget + plugins { `kord-internal-multiplatform-module` + `kord-native-module` } +@OptIn(ExperimentalKotlinGradlePluginApi::class) kotlin { + applyDefaultHierarchyTemplate { + common { + group("voice") { + withLinux() + withMacos() + withJvm() + } + } + } js { binaries.executable() } + targets.withType { + binaries.executable { + entryPoint = "dev.kord.voice.test.main" + } + } + sourceSets { commonMain { dependencies { implementation(projects.core) + implementation(libs.kotlin.logging) } } jvmMain { @@ -18,5 +39,16 @@ kotlin { runtimeOnly(libs.slf4j.simple) } } + linuxMain { + dependencies { + implementation(libs.ktor.client.curl) + } + } + + named("voiceMain") { + dependencies { + implementation(projects.coreVoice) + } + } } } diff --git a/samples/src/jvmMain/resources/simplelogger.properties b/samples/src/jvmMain/resources/simplelogger.properties new file mode 100644 index 00000000000..ba270bfe08c --- /dev/null +++ b/samples/src/jvmMain/resources/simplelogger.properties @@ -0,0 +1 @@ +org.slf4j.simpleLogger.defaultLogLevel=trace \ No newline at end of file diff --git a/samples/src/voiceMain/kotlin/VoiceBot.kt b/samples/src/voiceMain/kotlin/VoiceBot.kt new file mode 100644 index 00000000000..e686df74d90 --- /dev/null +++ b/samples/src/voiceMain/kotlin/VoiceBot.kt @@ -0,0 +1,52 @@ +@file:OptIn(KordVoice::class) + +package dev.kord.voice.test + +import dev.kord.common.annotation.KordVoice +import dev.kord.core.Kord +import dev.kord.core.behavior.channel.BaseVoiceChannelBehavior +import dev.kord.core.behavior.channel.connect +import dev.kord.core.behavior.interaction.respondPublic +import dev.kord.core.event.interaction.GuildChatInputCommandInteractionCreateEvent +import dev.kord.core.on +import dev.kord.voice.AudioFrame +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking + +fun main(args: Array) = runBlocking { + val kord = Kord(args.firstOrNull() ?: error("Missing token")) + + kord.createGlobalApplicationCommands { + input("join", "Test command") { + dmPermission = false + } + } + + kord.on { + val channel = interaction.user.asMember(interaction.guildId).getVoiceState().getChannelOrNull() + if (channel == null) { + interaction.respondPublic { content = "not in channel" } + return@on + } + interaction.respondPublic { content = "success" } + channel.connectEcho() + } + + kord.login() +} + +private suspend fun BaseVoiceChannelBehavior.connectEcho() { + val buffer = ArrayList(listOf(AudioFrame.SILENCE, AudioFrame.SILENCE, AudioFrame.SILENCE, AudioFrame.SILENCE)) + val connection = connect { + receiveVoice = true + audioProvider { + buffer.removeLastOrNull() ?: AudioFrame.SILENCE + } + } + connection.scope.launch { + connection.streams.incomingAudioFrames.collect { (userId, frame) -> + println("Received frame from:${userId}") + buffer.add(frame) + } + } +} diff --git a/voice/build.gradle.kts b/voice/build.gradle.kts index fbf4f4eaaad..326c5bae85d 100644 --- a/voice/build.gradle.kts +++ b/voice/build.gradle.kts @@ -1,21 +1,31 @@ plugins { - java // for TweetNaclFast - `kord-module` - `kord-sampled-module` + `kord-native-module` + `kord-multiplatform-module` `kord-publishing` } -dependencies { - api(projects.common) - api(projects.gateway) +kotlin { + jvm { + withJava() + } - implementation(libs.kotlin.logging) - implementation(libs.slf4j.api) + sourceSets { + commonMain { + dependencies { + api(projects.common) + api(projects.gateway) - // TODO remove when voiceGatewayOnLogger is removed - implementation(libs.kotlin.logging.old) + api(libs.ktor.network) + implementation(libs.kotlin.logging) - compileOnly(projects.kspAnnotations) + compileOnly(projects.kspAnnotations) + } + } - api(libs.ktor.network) + nonJvmMain { + dependencies { + implementation(libs.libsodium) + } + } + } } diff --git a/voice/build/generated/ksp/main/kotlin/dev/kord/voice/EncryptionMode.kt b/voice/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/voice/EncryptionMode.kt similarity index 100% rename from voice/build/generated/ksp/main/kotlin/dev/kord/voice/EncryptionMode.kt rename to voice/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/voice/EncryptionMode.kt diff --git a/voice/build/generated/ksp/main/kotlin/dev/kord/voice/SpeakingFlag.kt b/voice/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/voice/SpeakingFlag.kt similarity index 100% rename from voice/build/generated/ksp/main/kotlin/dev/kord/voice/SpeakingFlag.kt rename to voice/build/generated/ksp/metadata/commonMain/kotlin/dev/kord/voice/SpeakingFlag.kt diff --git a/voice/src/main/kotlin/AudioFrame.kt b/voice/src/commonMain/kotlin/AudioFrame.kt similarity index 94% rename from voice/src/main/kotlin/AudioFrame.kt rename to voice/src/commonMain/kotlin/AudioFrame.kt index dbb3d1041d7..0ec8957a22e 100644 --- a/voice/src/main/kotlin/AudioFrame.kt +++ b/voice/src/commonMain/kotlin/AudioFrame.kt @@ -1,6 +1,7 @@ package dev.kord.voice import dev.kord.common.annotation.KordVoice +import kotlin.jvm.JvmInline /** * A frame of 20ms Opus-encoded 48k stereo audio data. diff --git a/voice/src/main/kotlin/AudioProvider.kt b/voice/src/commonMain/kotlin/AudioProvider.kt similarity index 100% rename from voice/src/main/kotlin/AudioProvider.kt rename to voice/src/commonMain/kotlin/AudioProvider.kt diff --git a/voice/src/main/kotlin/DefaultFrameInterceptor.kt b/voice/src/commonMain/kotlin/DefaultFrameInterceptor.kt similarity index 100% rename from voice/src/main/kotlin/DefaultFrameInterceptor.kt rename to voice/src/commonMain/kotlin/DefaultFrameInterceptor.kt diff --git a/voice/src/main/kotlin/EncryptionMode.kt b/voice/src/commonMain/kotlin/EncryptionMode.kt similarity index 100% rename from voice/src/main/kotlin/EncryptionMode.kt rename to voice/src/commonMain/kotlin/EncryptionMode.kt diff --git a/voice/src/main/kotlin/FrameInterceptor.kt b/voice/src/commonMain/kotlin/FrameInterceptor.kt similarity index 100% rename from voice/src/main/kotlin/FrameInterceptor.kt rename to voice/src/commonMain/kotlin/FrameInterceptor.kt diff --git a/voice/src/main/kotlin/SpeakingFlag.kt b/voice/src/commonMain/kotlin/SpeakingFlag.kt similarity index 100% rename from voice/src/main/kotlin/SpeakingFlag.kt rename to voice/src/commonMain/kotlin/SpeakingFlag.kt diff --git a/voice/src/main/kotlin/VoiceConnection.kt b/voice/src/commonMain/kotlin/VoiceConnection.kt similarity index 100% rename from voice/src/main/kotlin/VoiceConnection.kt rename to voice/src/commonMain/kotlin/VoiceConnection.kt diff --git a/voice/src/main/kotlin/VoiceConnectionBuilder.kt b/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt similarity index 100% rename from voice/src/main/kotlin/VoiceConnectionBuilder.kt rename to voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt diff --git a/voice/src/main/kotlin/encryption/strategies/LiteNonceStrategy.kt b/voice/src/commonMain/kotlin/encryption/strategies/LiteNonceStrategy.kt similarity index 100% rename from voice/src/main/kotlin/encryption/strategies/LiteNonceStrategy.kt rename to voice/src/commonMain/kotlin/encryption/strategies/LiteNonceStrategy.kt diff --git a/voice/src/main/kotlin/encryption/strategies/NonceStrategy.kt b/voice/src/commonMain/kotlin/encryption/strategies/NonceStrategy.kt similarity index 100% rename from voice/src/main/kotlin/encryption/strategies/NonceStrategy.kt rename to voice/src/commonMain/kotlin/encryption/strategies/NonceStrategy.kt diff --git a/voice/src/main/kotlin/encryption/strategies/NormalNonceStrategy.kt b/voice/src/commonMain/kotlin/encryption/strategies/NormalNonceStrategy.kt similarity index 100% rename from voice/src/main/kotlin/encryption/strategies/NormalNonceStrategy.kt rename to voice/src/commonMain/kotlin/encryption/strategies/NormalNonceStrategy.kt diff --git a/voice/src/main/kotlin/encryption/strategies/SuffixNonceStrategy.kt b/voice/src/commonMain/kotlin/encryption/strategies/SuffixNonceStrategy.kt similarity index 100% rename from voice/src/main/kotlin/encryption/strategies/SuffixNonceStrategy.kt rename to voice/src/commonMain/kotlin/encryption/strategies/SuffixNonceStrategy.kt diff --git a/voice/src/main/kotlin/exception/VoiceConnectionInitializationException.kt b/voice/src/commonMain/kotlin/exception/VoiceConnectionInitializationException.kt similarity index 100% rename from voice/src/main/kotlin/exception/VoiceConnectionInitializationException.kt rename to voice/src/commonMain/kotlin/exception/VoiceConnectionInitializationException.kt diff --git a/voice/src/main/kotlin/gateway/Command.kt b/voice/src/commonMain/kotlin/gateway/Command.kt similarity index 100% rename from voice/src/main/kotlin/gateway/Command.kt rename to voice/src/commonMain/kotlin/gateway/Command.kt diff --git a/voice/src/main/kotlin/gateway/DefaultVoiceGateway.kt b/voice/src/commonMain/kotlin/gateway/DefaultVoiceGateway.kt similarity index 98% rename from voice/src/main/kotlin/gateway/DefaultVoiceGateway.kt rename to voice/src/commonMain/kotlin/gateway/DefaultVoiceGateway.kt index 8cf5b33844c..b9b5bc7a5c0 100644 --- a/voice/src/main/kotlin/gateway/DefaultVoiceGateway.kt +++ b/voice/src/commonMain/kotlin/gateway/DefaultVoiceGateway.kt @@ -9,6 +9,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging import io.ktor.client.* import io.ktor.client.plugins.websocket.* import io.ktor.client.request.* +import io.ktor.util.network.* import io.ktor.websocket.* import kotlinx.atomicfu.AtomicRef import kotlinx.atomicfu.atomic @@ -88,7 +89,7 @@ public class DefaultVoiceGateway( if (exception is CancellationException) break defaultVoiceGatewayLogger.error(exception) { "" } - if (exception is java.nio.channels.UnresolvedAddressException) { + if (exception is UnresolvedAddressException) { data.eventFlow.emit(Close.Timeout) } @@ -139,7 +140,7 @@ public class DefaultVoiceGateway( } private suspend fun read(frame: Frame) { - val json = String(frame.data, Charsets.UTF_8) + val json = frame.data.decodeToString() try { val event = jsonParser.decodeFromString(VoiceEvent.DeserializationStrategy, json) diff --git a/voice/src/main/kotlin/gateway/DefaultVoiceGatewayBuilder.kt b/voice/src/commonMain/kotlin/gateway/DefaultVoiceGatewayBuilder.kt similarity index 81% rename from voice/src/main/kotlin/gateway/DefaultVoiceGatewayBuilder.kt rename to voice/src/commonMain/kotlin/gateway/DefaultVoiceGatewayBuilder.kt index fa9426296d5..541a1b5c0d9 100644 --- a/voice/src/main/kotlin/gateway/DefaultVoiceGatewayBuilder.kt +++ b/voice/src/commonMain/kotlin/gateway/DefaultVoiceGatewayBuilder.kt @@ -2,13 +2,11 @@ package dev.kord.voice.gateway import dev.kord.common.annotation.KordVoice import dev.kord.common.entity.Snowflake +import dev.kord.common.http.httpEngine import dev.kord.gateway.retry.LinearRetry import dev.kord.gateway.retry.Retry import io.ktor.client.* -import io.ktor.client.engine.cio.* -import io.ktor.client.plugins.contentnegotiation.* import io.ktor.client.plugins.websocket.* -import io.ktor.serialization.kotlinx.json.* import kotlinx.coroutines.flow.MutableSharedFlow import kotlin.time.Duration.Companion.seconds @@ -23,11 +21,8 @@ public class DefaultVoiceGatewayBuilder( public var eventFlow: MutableSharedFlow = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE) public fun build(): DefaultVoiceGateway { - val client = client ?: HttpClient(CIO) { + val client = client ?: HttpClient(httpEngine()) { install(WebSockets) - install(ContentNegotiation) { - json() - } } val retry = reconnectRetry ?: LinearRetry(2.seconds, 20.seconds, 10) diff --git a/voice/src/main/kotlin/gateway/OpCode.kt b/voice/src/commonMain/kotlin/gateway/OpCode.kt similarity index 100% rename from voice/src/main/kotlin/gateway/OpCode.kt rename to voice/src/commonMain/kotlin/gateway/OpCode.kt diff --git a/voice/src/main/kotlin/gateway/Ticker.kt b/voice/src/commonMain/kotlin/gateway/Ticker.kt similarity index 100% rename from voice/src/main/kotlin/gateway/Ticker.kt rename to voice/src/commonMain/kotlin/gateway/Ticker.kt diff --git a/voice/src/main/kotlin/gateway/VoiceEvent.kt b/voice/src/commonMain/kotlin/gateway/VoiceEvent.kt similarity index 100% rename from voice/src/main/kotlin/gateway/VoiceEvent.kt rename to voice/src/commonMain/kotlin/gateway/VoiceEvent.kt diff --git a/voice/src/main/kotlin/gateway/VoiceGateway.kt b/voice/src/commonMain/kotlin/gateway/VoiceGateway.kt similarity index 96% rename from voice/src/main/kotlin/gateway/VoiceGateway.kt rename to voice/src/commonMain/kotlin/gateway/VoiceGateway.kt index f058e0fee36..58799a2d553 100644 --- a/voice/src/main/kotlin/gateway/VoiceGateway.kt +++ b/voice/src/commonMain/kotlin/gateway/VoiceGateway.kt @@ -86,11 +86,6 @@ public interface VoiceGateway { } -@Suppress("unused") -@Deprecated("Binary compatibility, remove after deprecation cycle.", level = DeprecationLevel.ERROR) -@PublishedApi -internal val voiceGatewayOnLogger: mu.KLogger = mu.KotlinLogging.logger("Gateway.on") - /** * Logger used to report [Throwable]s caught in [VoiceGateway.on]. */ diff --git a/voice/src/main/kotlin/gateway/VoiceGatewayConfiguration.kt b/voice/src/commonMain/kotlin/gateway/VoiceGatewayConfiguration.kt similarity index 100% rename from voice/src/main/kotlin/gateway/VoiceGatewayConfiguration.kt rename to voice/src/commonMain/kotlin/gateway/VoiceGatewayConfiguration.kt diff --git a/voice/src/main/kotlin/gateway/handler/GatewayEventHandler.kt b/voice/src/commonMain/kotlin/gateway/handler/GatewayEventHandler.kt similarity index 100% rename from voice/src/main/kotlin/gateway/handler/GatewayEventHandler.kt rename to voice/src/commonMain/kotlin/gateway/handler/GatewayEventHandler.kt diff --git a/voice/src/main/kotlin/gateway/handler/HandshakeHandler.kt b/voice/src/commonMain/kotlin/gateway/handler/HandshakeHandler.kt similarity index 100% rename from voice/src/main/kotlin/gateway/handler/HandshakeHandler.kt rename to voice/src/commonMain/kotlin/gateway/handler/HandshakeHandler.kt diff --git a/voice/src/main/kotlin/gateway/handler/HeartbeatHandler.kt b/voice/src/commonMain/kotlin/gateway/handler/HeartbeatHandler.kt similarity index 100% rename from voice/src/main/kotlin/gateway/handler/HeartbeatHandler.kt rename to voice/src/commonMain/kotlin/gateway/handler/HeartbeatHandler.kt diff --git a/voice/src/main/kotlin/handlers/ConnectionEventHandler.kt b/voice/src/commonMain/kotlin/handlers/ConnectionEventHandler.kt similarity index 100% rename from voice/src/main/kotlin/handlers/ConnectionEventHandler.kt rename to voice/src/commonMain/kotlin/handlers/ConnectionEventHandler.kt diff --git a/voice/src/main/kotlin/handlers/StreamsHandler.kt b/voice/src/commonMain/kotlin/handlers/StreamsHandler.kt similarity index 100% rename from voice/src/main/kotlin/handlers/StreamsHandler.kt rename to voice/src/commonMain/kotlin/handlers/StreamsHandler.kt diff --git a/voice/src/main/kotlin/handlers/UdpLifeCycleHandler.kt b/voice/src/commonMain/kotlin/handlers/UdpLifeCycleHandler.kt similarity index 100% rename from voice/src/main/kotlin/handlers/UdpLifeCycleHandler.kt rename to voice/src/commonMain/kotlin/handlers/UdpLifeCycleHandler.kt diff --git a/voice/src/main/kotlin/handlers/VoiceUpdateEventHandler.kt b/voice/src/commonMain/kotlin/handlers/VoiceUpdateEventHandler.kt similarity index 100% rename from voice/src/main/kotlin/handlers/VoiceUpdateEventHandler.kt rename to voice/src/commonMain/kotlin/handlers/VoiceUpdateEventHandler.kt diff --git a/voice/src/main/kotlin/io/ByteArrayCursors.kt b/voice/src/commonMain/kotlin/io/ByteArrayCursors.kt similarity index 100% rename from voice/src/main/kotlin/io/ByteArrayCursors.kt rename to voice/src/commonMain/kotlin/io/ByteArrayCursors.kt diff --git a/voice/src/main/kotlin/io/ByteArrayView.kt b/voice/src/commonMain/kotlin/io/ByteArrayView.kt similarity index 95% rename from voice/src/main/kotlin/io/ByteArrayView.kt rename to voice/src/commonMain/kotlin/io/ByteArrayView.kt index fdc44913b85..ff99239bc8e 100644 --- a/voice/src/main/kotlin/io/ByteArrayView.kt +++ b/voice/src/commonMain/kotlin/io/ByteArrayView.kt @@ -24,7 +24,7 @@ public class ByteArrayView private constructor(public val data: ByteArray, start public operator fun get(index: Int): Byte { if (dataStart + index > dataEnd) { - throw ArrayIndexOutOfBoundsException(index) + throw IndexOutOfBoundsException("Index is out of bounds: $index") } return data[dataStart + index] @@ -37,7 +37,7 @@ public class ByteArrayView private constructor(public val data: ByteArray, start fun nextByte(): Byte = try { view[index++] - } catch (e: ArrayIndexOutOfBoundsException) { + } catch (e: IndexOutOfBoundsException) { index -= 1 throw NoSuchElementException(e.message) } diff --git a/voice/src/main/kotlin/streams/DefaultStreams.kt b/voice/src/commonMain/kotlin/streams/DefaultStreams.kt similarity index 71% rename from voice/src/main/kotlin/streams/DefaultStreams.kt rename to voice/src/commonMain/kotlin/streams/DefaultStreams.kt index 0907f1ff895..41998813de3 100644 --- a/voice/src/main/kotlin/streams/DefaultStreams.kt +++ b/voice/src/commonMain/kotlin/streams/DefaultStreams.kt @@ -1,14 +1,13 @@ package dev.kord.voice.streams -import com.iwebpp.crypto.TweetNaclFast import dev.kord.common.annotation.KordVoice import dev.kord.common.entity.Snowflake import dev.kord.voice.AudioFrame -import dev.kord.voice.encryption.XSalsa20Poly1305Codec import dev.kord.voice.encryption.strategies.NonceStrategy import dev.kord.voice.gateway.Speaking import dev.kord.voice.gateway.VoiceGateway -import dev.kord.voice.io.* +import dev.kord.voice.io.ByteArrayView +import dev.kord.voice.io.readableCursor import dev.kord.voice.udp.PayloadType import dev.kord.voice.udp.RTPPacket import dev.kord.voice.udp.VoiceUdpSocket @@ -22,7 +21,7 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.* -private val defaultStreamsLogger = KotlinLogging.logger { } +internal val defaultStreamsLogger = KotlinLogging.logger { } @KordVoice public class DefaultStreams( @@ -47,7 +46,7 @@ public class DefaultStreams( .buffer(Channel.UNLIMITED) .onEach { speaking -> _ssrcToUser.update { - it.computeIfAbsent(speaking.ssrc) { + it.getOrPut(speaking.ssrc) { incomingAudioFrames .filter { (ssrc, _) -> speaking.ssrc == ssrc } .map { (_, frame) -> speaking.userId to frame } @@ -86,38 +85,7 @@ public class DefaultStreams( override val ssrcToUser: Map get() = _ssrcToUser.value } -private fun Flow.decrypt(nonceStrategy: NonceStrategy, key: ByteArray): Flow { - val codec = XSalsa20Poly1305Codec(key) - val nonceBuffer = ByteArray(TweetNaclFast.SecretBox.nonceLength).mutableCursor() - - val decryptedBuffer = ByteArray(512) - val decryptedCursor = decryptedBuffer.mutableCursor() - val decryptedView = decryptedBuffer.view() - - return mapNotNull { - nonceBuffer.reset() - decryptedCursor.reset() - - nonceBuffer.writeByteView(nonceStrategy.strip(it)) - - val decrypted = with(it.payload) { - codec.decrypt(data, dataStart, viewSize, nonceBuffer.data, decryptedCursor) - } - - if (!decrypted) { - defaultStreamsLogger.trace { "failed to decrypt the packet with data ${it.payload.data.contentToString()} at offset ${it.payload.dataStart} and length ${it.payload.viewSize - 4}" } - return@mapNotNull null - } - - decryptedView.resize(0, decryptedCursor.cursor) - - // mutate the payload data and update the view - it.payload.data.mutableCursor().writeByteViewOrResize(decryptedView) - it.payload.resize(0, decryptedView.viewSize) - - it - } -} +internal expect fun Flow.decrypt(nonceStrategy: NonceStrategy, key: ByteArray): Flow private fun Flow.clean(): Flow { fun processExtensionHeader(payload: ByteArrayView) = with(payload.readableCursor()) { diff --git a/voice/src/main/kotlin/streams/NOPStreams.kt b/voice/src/commonMain/kotlin/streams/NOPStreams.kt similarity index 100% rename from voice/src/main/kotlin/streams/NOPStreams.kt rename to voice/src/commonMain/kotlin/streams/NOPStreams.kt diff --git a/voice/src/main/kotlin/streams/Streams.kt b/voice/src/commonMain/kotlin/streams/Streams.kt similarity index 100% rename from voice/src/main/kotlin/streams/Streams.kt rename to voice/src/commonMain/kotlin/streams/Streams.kt diff --git a/voice/src/main/kotlin/udp/AudioFrameSender.kt b/voice/src/commonMain/kotlin/udp/AudioFrameSender.kt similarity index 100% rename from voice/src/main/kotlin/udp/AudioFrameSender.kt rename to voice/src/commonMain/kotlin/udp/AudioFrameSender.kt diff --git a/voice/src/commonMain/kotlin/udp/AudioPacketProvider.kt b/voice/src/commonMain/kotlin/udp/AudioPacketProvider.kt new file mode 100644 index 00000000000..ababbc0392f --- /dev/null +++ b/voice/src/commonMain/kotlin/udp/AudioPacketProvider.kt @@ -0,0 +1,23 @@ +package dev.kord.voice.udp + +import dev.kord.voice.encryption.strategies.NonceStrategy +import dev.kord.voice.io.ByteArrayView +import dev.kord.voice.io.MutableByteArrayCursor + +public abstract class AudioPacketProvider(public val key: ByteArray, public val nonceStrategy: NonceStrategy) { + public abstract fun provide(sequence: UShort, timestamp: UInt, ssrc: UInt, data: ByteArray): ByteArrayView +} + +internal class CouldNotEncryptDataException(data: ByteArray, cause: Throwable? = null) : + RuntimeException("Couldn't encrypt the following data: [${data.joinToString(", ")}]", cause) + +public expect fun DefaultAudioPacketProvider(key: ByteArray, nonceStrategy: NonceStrategy) : AudioPacketProvider + + +internal fun MutableByteArrayCursor.writeHeader(sequence: Short, timestamp: Int, ssrc: Int) { + writeByte(((2 shl 6) or (0x0) or (0x0)).toByte()) // first 2 bytes are version. the rest + writeByte(PayloadType.Audio.raw) + writeShort(sequence) + writeInt(timestamp) + writeInt(ssrc) +} diff --git a/voice/src/main/kotlin/udp/DefaultAudioFrameSender.kt b/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt similarity index 100% rename from voice/src/main/kotlin/udp/DefaultAudioFrameSender.kt rename to voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt diff --git a/voice/src/main/kotlin/udp/GlobalVoiceUdpSocket.kt b/voice/src/commonMain/kotlin/udp/GlobalVoiceUdpSocket.kt similarity index 95% rename from voice/src/main/kotlin/udp/GlobalVoiceUdpSocket.kt rename to voice/src/commonMain/kotlin/udp/GlobalVoiceUdpSocket.kt index d4577e45cf3..f81f5c64b12 100644 --- a/voice/src/main/kotlin/udp/GlobalVoiceUdpSocket.kt +++ b/voice/src/commonMain/kotlin/udp/GlobalVoiceUdpSocket.kt @@ -10,7 +10,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.* -import kotlin.text.String private val globalVoiceSocketLogger = KotlinLogging.logger { } @@ -32,7 +31,7 @@ public object GlobalVoiceUdpSocket : VoiceUdpSocket { private val _incoming: MutableSharedFlow = MutableSharedFlow() override val incoming: SharedFlow = _incoming - private val socket = aSocket(ActorSelectorManager(socketScope.coroutineContext)).udp().bind() + private val socket = aSocket(SelectorManager(socketScope.coroutineContext)).udp().bind() private val EMPTY_DATA = ByteArray(DISCOVERY_DATA_SIZE) diff --git a/voice/src/main/kotlin/udp/PayloadType.kt b/voice/src/commonMain/kotlin/udp/PayloadType.kt similarity index 78% rename from voice/src/main/kotlin/udp/PayloadType.kt rename to voice/src/commonMain/kotlin/udp/PayloadType.kt index 45fa0fb8564..e6b529f037d 100644 --- a/voice/src/main/kotlin/udp/PayloadType.kt +++ b/voice/src/commonMain/kotlin/udp/PayloadType.kt @@ -6,7 +6,9 @@ package dev.kord.voice.udp public sealed class PayloadType(public val raw: Byte) { public object Alive : PayloadType(0x37.toByte()) public object Audio : PayloadType(0x78.toByte()) - public class Unknown(value: Byte) : PayloadType(value) + public class Unknown(value: Byte) : PayloadType(value) { + override fun toString(): String = raw.toString(16) + } public companion object { public fun from(value: Byte): PayloadType = when (value) { diff --git a/voice/src/main/kotlin/udp/RTPPacket.kt b/voice/src/commonMain/kotlin/udp/RTPPacket.kt similarity index 100% rename from voice/src/main/kotlin/udp/RTPPacket.kt rename to voice/src/commonMain/kotlin/udp/RTPPacket.kt diff --git a/voice/src/main/kotlin/udp/VoiceUdpSocket.kt b/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt similarity index 100% rename from voice/src/main/kotlin/udp/VoiceUdpSocket.kt rename to voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt diff --git a/voice/src/main/java/com/iwebpp/crypto/TweetNaclFast.java b/voice/src/jvmMain/java/com/iwebpp/crypto/TweetNaclFast.java similarity index 100% rename from voice/src/main/java/com/iwebpp/crypto/TweetNaclFast.java rename to voice/src/jvmMain/java/com/iwebpp/crypto/TweetNaclFast.java diff --git a/voice/src/main/kotlin/encryption/XSalsa20Poly1305Codec.kt b/voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Codec.kt similarity index 99% rename from voice/src/main/kotlin/encryption/XSalsa20Poly1305Codec.kt rename to voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Codec.kt index 5e1083e2c29..d17057ca8de 100644 --- a/voice/src/main/kotlin/encryption/XSalsa20Poly1305Codec.kt +++ b/voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Codec.kt @@ -46,4 +46,4 @@ public fun XSalsa20Poly1305Codec.decrypt( val buffer = ByteArray(boxLength - TweetNaclFast.SecretBox.boxzerobytesLength) if (!decrypt(box, boxOffset, boxLength, nonce, buffer.mutableCursor())) return null return buffer -} \ No newline at end of file +} diff --git a/voice/src/main/kotlin/encryption/XSalsa20Poly1305Encryption.kt b/voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Encryption.kt similarity index 99% rename from voice/src/main/kotlin/encryption/XSalsa20Poly1305Encryption.kt rename to voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Encryption.kt index 808e9d502ae..47363cfbfc6 100644 --- a/voice/src/main/kotlin/encryption/XSalsa20Poly1305Encryption.kt +++ b/voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Encryption.kt @@ -5,6 +5,7 @@ import com.iwebpp.crypto.TweetNaclFast.SecretBox.boxzerobytesLength import com.iwebpp.crypto.TweetNaclFast.SecretBox.zerobytesLength import dev.kord.voice.io.MutableByteArrayCursor + // https://datatracker.ietf.org/doc/html/rfc6716#section-3.2.1 private const val OPUS_MAX_LENGTH = 1276 diff --git a/voice/src/jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt b/voice/src/jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt new file mode 100644 index 00000000000..2e91381139c --- /dev/null +++ b/voice/src/jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt @@ -0,0 +1,45 @@ +@file:JvmName("DefaultStreamsJvm") +package dev.kord.voice.streams + +import com.iwebpp.crypto.TweetNaclFast +import dev.kord.voice.encryption.XSalsa20Poly1305Codec +import dev.kord.voice.encryption.strategies.NonceStrategy +import dev.kord.voice.io.mutableCursor +import dev.kord.voice.io.view +import dev.kord.voice.io.writeByteViewOrResize +import dev.kord.voice.udp.RTPPacket +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.mapNotNull + +internal actual fun Flow.decrypt(nonceStrategy: NonceStrategy, key: ByteArray): Flow { + val codec = XSalsa20Poly1305Codec(key) + val nonceBuffer = ByteArray(TweetNaclFast.SecretBox.nonceLength).mutableCursor() + + val decryptedBuffer = ByteArray(512) + val decryptedCursor = decryptedBuffer.mutableCursor() + val decryptedView = decryptedBuffer.view() + + return mapNotNull { + nonceBuffer.reset() + decryptedCursor.reset() + + nonceBuffer.writeByteView(nonceStrategy.strip(it)) + + val decrypted = with(it.payload) { + codec.decrypt(data, dataStart, viewSize, nonceBuffer.data, decryptedCursor) + } + + if (!decrypted) { + defaultStreamsLogger.trace { "failed to decrypt the packet with data ${it.payload.data.contentToString()} at offset ${it.payload.dataStart} and length ${it.payload.viewSize - 4}" } + return@mapNotNull null + } + + decryptedView.resize(0, decryptedCursor.cursor) + + // mutate the payload data and update the view + it.payload.data.mutableCursor().writeByteViewOrResize(decryptedView) + it.payload.resize(0, decryptedView.viewSize) + + it + } +} diff --git a/voice/src/main/kotlin/udp/AudioPacketProvider.kt b/voice/src/jvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt similarity index 72% rename from voice/src/main/kotlin/udp/AudioPacketProvider.kt rename to voice/src/jvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt index 05f2e522d4c..367d042b3fc 100644 --- a/voice/src/main/kotlin/udp/AudioPacketProvider.kt +++ b/voice/src/jvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt @@ -8,14 +8,12 @@ import dev.kord.voice.io.MutableByteArrayCursor import dev.kord.voice.io.mutableCursor import dev.kord.voice.io.view -public abstract class AudioPacketProvider(public val key: ByteArray, public val nonceStrategy: NonceStrategy) { - public abstract fun provide(sequence: UShort, timestamp: UInt, ssrc: UInt, data: ByteArray): ByteArrayView -} +@Suppress("FunctionName") +public actual fun DefaultAudioPacketProvider(key: ByteArray, nonceStrategy: NonceStrategy) : AudioPacketProvider = + DefaultJvmAudioPacketProvider(key, nonceStrategy) -private class CouldNotEncryptDataException(data: ByteArray) : - RuntimeException("Couldn't encrypt the following data: [${data.joinToString(", ")}]") -public class DefaultAudioPacketProvider(key: ByteArray, nonceStrategy: NonceStrategy) : +public class DefaultJvmAudioPacketProvider(key: ByteArray, nonceStrategy: NonceStrategy) : AudioPacketProvider(key, nonceStrategy) { private val codec = XSalsa20Poly1305Codec(key) @@ -29,14 +27,6 @@ public class DefaultAudioPacketProvider(key: ByteArray, nonceStrategy: NonceStra private val lock: Any = Any() - private fun MutableByteArrayCursor.writeHeader(sequence: Short, timestamp: Int, ssrc: Int) { - writeByte(((2 shl 6) or (0x0) or (0x0)).toByte()) // first 2 bytes are version. the rest - writeByte(PayloadType.Audio.raw) - writeShort(sequence) - writeInt(timestamp) - writeInt(ssrc) - } - override fun provide(sequence: UShort, timestamp: UInt, ssrc: UInt, data: ByteArray): ByteArrayView = synchronized(lock) { with(packetBufferCursor) { diff --git a/voice/src/nonJvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt b/voice/src/nonJvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt new file mode 100644 index 00000000000..6225c38a54f --- /dev/null +++ b/voice/src/nonJvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt @@ -0,0 +1,28 @@ +package dev.kord.voice.streams + +import com.ionspin.kotlin.crypto.secretbox.SecretBox +import com.ionspin.kotlin.crypto.secretbox.crypto_secretbox_NONCEBYTES +import dev.kord.voice.encryption.strategies.NonceStrategy +import dev.kord.voice.io.mutableCursor +import dev.kord.voice.io.view +import dev.kord.voice.udp.RTPPacket +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.mapNotNull + +internal actual fun Flow.decrypt(nonceStrategy: NonceStrategy, key: ByteArray): Flow { + val nonceBuffer = ByteArray(crypto_secretbox_NONCEBYTES).mutableCursor() + val uKey = key.asUByteArray() + + return mapNotNull { + nonceBuffer.reset() + nonceBuffer.writeByteView(nonceStrategy.strip(it)) + + val decrypted = SecretBox.openEasy( + it.payload.toByteArray().asUByteArray(), + nonceBuffer.data.asUByteArray(), + uKey + ) + + it.copy(payload = decrypted.asByteArray().view()) + } +} diff --git a/voice/src/nonJvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt b/voice/src/nonJvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt new file mode 100644 index 00000000000..de7fa8d3c65 --- /dev/null +++ b/voice/src/nonJvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt @@ -0,0 +1,65 @@ +package dev.kord.voice.udp + +import com.ionspin.kotlin.crypto.secretbox.SecretBox +import dev.kord.voice.encryption.strategies.NonceStrategy +import dev.kord.voice.io.ByteArrayView +import dev.kord.voice.io.MutableByteArrayCursor +import dev.kord.voice.io.mutableCursor +import dev.kord.voice.io.view +import kotlinx.atomicfu.locks.SynchronizedObject +import kotlinx.atomicfu.locks.synchronized + +@Suppress("FunctionName") +public actual fun DefaultAudioPacketProvider(key: ByteArray, nonceStrategy: NonceStrategy): AudioPacketProvider = + DefaultNativeAudioPacketProvider(key, nonceStrategy) + +public class DefaultNativeAudioPacketProvider(key: ByteArray, nonceStrategy: NonceStrategy) : + AudioPacketProvider(key, nonceStrategy) { + + private val packetBuffer = ByteArray(2048) + private val packetBufferCursor: MutableByteArrayCursor = packetBuffer.mutableCursor() + private val packetBufferView: ByteArrayView = packetBuffer.view() + + private val rtpHeaderView: ByteArrayView = packetBuffer.view(0, RTP_HEADER_LENGTH)!! + + private val nonceBuffer: MutableByteArrayCursor = ByteArray(4).mutableCursor() + + private val lock = SynchronizedObject() + + override fun provide(sequence: UShort, timestamp: UInt, ssrc: UInt, data: ByteArray): ByteArrayView = + synchronized(lock) { + with(packetBufferCursor) { + this.reset() + nonceBuffer.reset() + + // make sure we enough room in this buffer + resize(RTP_HEADER_LENGTH + (data.size + 16) + nonceStrategy.nonceLength) + + // write header and generate nonce + writeHeader(sequence.toShort(), timestamp.toInt(), ssrc.toInt()) + + val rawNonce = nonceStrategy.generate { rtpHeaderView } + nonceBuffer.writeByteView(rawNonce) + + // encrypt data and write into our buffer + try { + writeByteArray( + SecretBox.easy( + data.toUByteArray(), + nonceBuffer.data.toUByteArray(), + key.toUByteArray() + ).toByteArray() + ) + } catch (e: Throwable) { + throw CouldNotEncryptDataException(data, e) + } + + nonceStrategy.append(rawNonce, this) + + // let's make sure we have the correct view of the packet + if (!packetBufferView.resize(0, cursor)) error("couldn't resize packet buffer view?!") + + packetBufferView + } + } +} From 45ef6fc4493d282c02aa6c77988b1b7885e59880 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Thu, 25 Jan 2024 19:43:02 +0100 Subject: [PATCH 20/83] Use zError in inflater for proper error codes --- gateway/src/nativeMain/kotlin/Inflater.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index 80b4a9abe6c..e94cd75020f 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -15,7 +15,7 @@ private class NativeInflater : Inflater { val initResponse = inflateInit2(ptr, MAX_WBITS) if (initResponse != Z_OK) { nativeHeap.free(this) - throw IllegalStateException("Could not initialize zlib: $initResponse") + throw ZLibException("Could not initialize zlib: ${zErrorMessage(initResponse)}") } } @@ -37,7 +37,9 @@ private class NativeInflater : Inflater { } val resultCode = inflate(zStream.ptr, Z_NO_FLUSH) if (resultCode != Z_OK && resultCode != Z_STREAM_END) { - throw IllegalStateException("An error occurred during decompression of frame: $resultCode") + throw ZLibException( + "An error occurred during decompression of frame: ${zErrorMessage(resultCode)}" + ) } out += uncompressedData.readBytes(uncompressedDataSize - zStream.avail_out.convert()) } while (zStream.avail_out == 0u) @@ -51,3 +53,8 @@ private class NativeInflater : Inflater { nativeHeap.free(zStream) } } + +private class ZLibException(message: String?) : IllegalStateException(message) + +@OptIn(ExperimentalForeignApi::class) +private fun zErrorMessage(errorCode: Int) = zError(errorCode)?.toKString() ?: errorCode From 855733cb4c83da359271e82228dd46219fc8e441 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Thu, 25 Jan 2024 19:45:16 +0100 Subject: [PATCH 21/83] Print error of inflateEnd --- gateway/src/nativeMain/kotlin/Inflater.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index e94cd75020f..3abeafcd393 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -49,8 +49,14 @@ private class NativeInflater : Inflater { } override fun close() { - inflateEnd(zStream.ptr) - nativeHeap.free(zStream) + try { + val response = inflateEnd(zStream.ptr) + if(response != Z_OK) { + throw ZLibException("Could not end zstream: ${zErrorMessage(response)}") + } + } finally { + nativeHeap.free(zStream) + } } } From 45bb300065b7114146a89b9a5dd0b5b316cd7134 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Tue, 30 Jan 2024 00:56:50 +0100 Subject: [PATCH 22/83] Update to published cache library --- build.gradle.kts | 2 +- core/src/commonMain/kotlin/Kord.kt | 3 --- core/src/commonMain/kotlin/builder/kord/KordBuilder.kt | 2 +- gradle/libs.versions.toml | 3 +-- samples/build.gradle.kts | 7 +++++-- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8bbf38fe3ce..4f9622b2557 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ plugins { allprojects { repositories { // TODO: Remove wants https://github.com/ktorio/ktor/pull/3950 lands - mavenLocal() + maven("https://europe-west3-maven.pkg.dev/mik-music/kord") mavenCentral() maven("https://oss.sonatype.org/content/repositories/snapshots/") } diff --git a/core/src/commonMain/kotlin/Kord.kt b/core/src/commonMain/kotlin/Kord.kt index 1e14ac8ea2f..b44b09474f7 100644 --- a/core/src/commonMain/kotlin/Kord.kt +++ b/core/src/commonMain/kotlin/Kord.kt @@ -39,9 +39,6 @@ import kotlin.contracts.contract import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.channels.Channel as CoroutineChannel -@Deprecated("Use your own logger instead, this will be removed in the future.", level = DeprecationLevel.ERROR) -public val kordLogger: mu.KLogger = mu.KotlinLogging.logger { } - private val logger = KotlinLogging.logger { } @PublishedApi diff --git a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt index 934e9a71c26..32657e9d00e 100644 --- a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt +++ b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt @@ -50,7 +50,7 @@ public abstract class BaseKordBuilder internal constructor(public val token: Str shards.map { DefaultGateway { // Workaround for: https://github.com/ktorio/ktor/pull/3950#issuecomment-1909088751 - // client = resources.httpClient + client = resources.httpClient identifyRateLimiter = rateLimiter } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 457f5269654..33d42618849 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,8 +8,7 @@ kotlinx-serialization = "1.6.2" # https://github.com/Kotlin/kotlinx.serializatio kotlinx-datetime = "0.5.0" # https://github.com/Kotlin/kotlinx-datetime kotlin-logging = "6.0.1" # https://github.com/oshai/kotlin-logging kotlin-logging-old = "3.0.5" # TODO remove after dependency is removed in rest, gateway, voice and core -# This is the specific release supporting native, until we setup CI -kord-cache = "0.5.x-20230806.144015-3" # https://github.com/kordlib/cache +kord-cache = "0.5.0-SNAPSHOT" # https://github.com/kordlib/cache # implementation dependencies kotlin-node = "18.16.12-pre.619" # https://github.com/JetBrains/kotlin-wrappers diff --git a/samples/build.gradle.kts b/samples/build.gradle.kts index 44344065abf..cf0112239c1 100644 --- a/samples/build.gradle.kts +++ b/samples/build.gradle.kts @@ -1,5 +1,6 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.konan.target.KonanTarget plugins { `kord-internal-multiplatform-module` @@ -22,8 +23,10 @@ kotlin { } targets.withType { - binaries.executable { - entryPoint = "dev.kord.voice.test.main" + if (konanTarget != KonanTarget.MINGW_X64) { + binaries.executable { + entryPoint = "dev.kord.voice.test.main" + } } } From ba758c9eae00f4bb50216a18dbc5599dddbd681f Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 14:39:34 +0100 Subject: [PATCH 23/83] Sadly the Ktor bug is not fixed yet --- core/src/commonMain/kotlin/builder/kord/KordBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt index 32657e9d00e..e04f44102c3 100644 --- a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt +++ b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt @@ -50,7 +50,7 @@ public abstract class BaseKordBuilder internal constructor(public val token: Str shards.map { DefaultGateway { // Workaround for: https://github.com/ktorio/ktor/pull/3950#issuecomment-1909088751 - client = resources.httpClient +// client = resources.httpClient identifyRateLimiter = rateLimiter } } From 30f072c9408947cb3a3e59526c1450c72b90bfc0 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 15:20:56 +0100 Subject: [PATCH 24/83] Finalize snapshot builds - Use Kord gradle tools - Use vanniktech maven-publish.plugin - Match Kotlin Version with cache (1.9.22) - Update ksp to 1.9.22-1.0.16 - Enable -Werror again, as underlying issue with cache got fixed --- .github/workflows/deployment-ci.yml | 66 ------------- .github/workflows/docs-ci.yml | 36 +------ .../workflows/gradle-wrapper-validation.yml | 14 --- bom/build.gradle.kts | 4 +- build.gradle.kts | 1 - buildSrc/build.gradle.kts | 2 + buildSrc/src/main/kotlin/Compiler.kt | 2 +- buildSrc/src/main/kotlin/Documentation.kt | 1 + buildSrc/src/main/kotlin/Git.kt | 13 --- buildSrc/src/main/kotlin/Projects.kt | 27 ------ .../kord-multiplatform-module.gradle.kts | 30 ------ .../main/kotlin/kord-publishing.gradle.kts | 96 ++++++------------- common/build.gradle.kts | 5 +- gradle/libs.versions.toml | 10 +- 14 files changed, 50 insertions(+), 257 deletions(-) delete mode 100644 .github/workflows/deployment-ci.yml delete mode 100644 .github/workflows/gradle-wrapper-validation.yml delete mode 100644 buildSrc/src/main/kotlin/Git.kt diff --git a/.github/workflows/deployment-ci.yml b/.github/workflows/deployment-ci.yml deleted file mode 100644 index 380dd25838f..00000000000 --- a/.github/workflows/deployment-ci.yml +++ /dev/null @@ -1,66 +0,0 @@ -# This workflow will build a package using Gradle and then publish it to maven - -name: Kotlin CI - -on: - push: - branches: - - '**' # We want to run this on all branch pushes - tags-ignore: - - '**' # We don't want this to run on tags pushes - branches-ignore: - # CI is not setup for Native - - 'feature/native' - pull_request: - release: - types: [ published ] - -jobs: - build: - name: Build Kord - runs-on: ubuntu-latest - if: | - !contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.pull_request.title, '[ci skip]') - && !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'kordlib/kord') - env: - KORD_TEST_TOKEN: ${{ secrets.KORD_TEST_TOKEN }} - steps: - - uses: actions/checkout@v4 - - name: Set up JDK - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 11 - - name: Build with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: --stacktrace --info build - release: - name: Publish artifacts - runs-on: ubuntu-latest - needs: build - if: | - !contains(github.event.head_commit.message, '[publish skip]') && github.event_name != 'pull_request' && github.ref != 'refs/heads/master' - env: - KORD_TEST_TOKEN: ${{ secrets.KORD_TEST_TOKEN }} - NEXUS_USER: ${{ secrets.NEXUS_USER }} - NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} - SIGNING_KEY: ${{ secrets.signingKey }} - SIGNING_PASSWORD: ${{ secrets.signingPassword }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Set up JDK - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 11 - - name: Build with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: --stacktrace --info build - - name: Publish with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: --no-parallel -x test publish diff --git a/.github/workflows/docs-ci.yml b/.github/workflows/docs-ci.yml index 4a2522ec3f1..9c754879ba5 100644 --- a/.github/workflows/docs-ci.yml +++ b/.github/workflows/docs-ci.yml @@ -1,38 +1,12 @@ -# This workflow will build and deploy docs to GitHub Pages whenever something is pushed to the main branch - -name: Docs - +name: Documentation CI on: push: - branches: - - main + pull_request: permissions: - contents: write + id-token: write + pages: write jobs: docs: - name: Build and deploy docs - runs-on: ubuntu-latest - concurrency: # Allow one concurrent deployment - group: pages - cancel-in-progress: true - steps: - - uses: actions/checkout@v4 - - name: Set up JDK - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 11 - - name: Build docs with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: --stacktrace --info dokkaHtmlMultiModule - - name: Deploy docs to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4 - with: - folder: build/dokka/htmlMultiModule - branch: gh-pages - git-config-name: GitHub Actions - git-config-email: actions@github.com - commit-message: Update docs + uses: kordlib/.teamcity/.github/workflows/documentation.yml@main diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml deleted file mode 100644 index e58b1ef402f..00000000000 --- a/.github/workflows/gradle-wrapper-validation.yml +++ /dev/null @@ -1,14 +0,0 @@ -# This workflow will validate the checksums of Gradle Wrapper JAR files - -name: Gradle Wrapper Validation - -on: [ push, pull_request ] - -jobs: - validation: - name: Validate Gradle Wrapper - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Validate Gradle Wrapper - uses: gradle/wrapper-validation-action@v1 diff --git a/bom/build.gradle.kts b/bom/build.gradle.kts index 534d252b314..fb32d631c76 100644 --- a/bom/build.gradle.kts +++ b/bom/build.gradle.kts @@ -1,6 +1,6 @@ plugins { `java-platform` - `maven-publish` + `kord-publishing` } val me = project @@ -31,5 +31,3 @@ publishing { from(components["javaPlatform"]) } } - -apply(plugin = "kord-publishing") diff --git a/build.gradle.kts b/build.gradle.kts index 4f9622b2557..b79e93f2729 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,4 +12,3 @@ allprojects { } group = Library.group -version = libraryVersion diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 350ddece2c0..d6abfed304d 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -5,6 +5,8 @@ plugins { repositories { gradlePluginPortal() mavenCentral() + // Repo providing the Kord Gradle plugin + maven("https://europe-west3-maven.pkg.dev/mik-music/kord") } kotlin { diff --git a/buildSrc/src/main/kotlin/Compiler.kt b/buildSrc/src/main/kotlin/Compiler.kt index fe1d1187f0b..1b8e9f10ac6 100644 --- a/buildSrc/src/main/kotlin/Compiler.kt +++ b/buildSrc/src/main/kotlin/Compiler.kt @@ -25,7 +25,7 @@ object Jvm { } fun KotlinCommonCompilerOptions.applyKordCompilerOptions() { -// allWarningsAsErrors = true + allWarningsAsErrors = true progressiveMode = true freeCompilerArgs.add("-Xexpect-actual-classes") } diff --git a/buildSrc/src/main/kotlin/Documentation.kt b/buildSrc/src/main/kotlin/Documentation.kt index 92eb73e751c..fef44a76bab 100644 --- a/buildSrc/src/main/kotlin/Documentation.kt +++ b/buildSrc/src/main/kotlin/Documentation.kt @@ -1,3 +1,4 @@ +import dev.kord.gradle.tools.util.commitHash import org.gradle.kotlin.dsl.assign import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask import java.net.URI diff --git a/buildSrc/src/main/kotlin/Git.kt b/buildSrc/src/main/kotlin/Git.kt deleted file mode 100644 index 321fe3fbbc1..00000000000 --- a/buildSrc/src/main/kotlin/Git.kt +++ /dev/null @@ -1,13 +0,0 @@ -import org.gradle.api.Project -import java.io.ByteArrayOutputStream - -internal fun Project.git(vararg command: String): String { - val output = ByteArrayOutputStream() - exec { - commandLine("git", *command) - standardOutput = output - errorOutput = output - workingDir = rootDir - }.rethrowFailure().assertNormalExitValue() - return output.toString().trim() -} diff --git a/buildSrc/src/main/kotlin/Projects.kt b/buildSrc/src/main/kotlin/Projects.kt index be8c41f12ee..3ffba637fce 100644 --- a/buildSrc/src/main/kotlin/Projects.kt +++ b/buildSrc/src/main/kotlin/Projects.kt @@ -1,33 +1,6 @@ -import org.gradle.api.Project - object Library { const val name = "kord" const val group = "dev.kord" const val description = "Idiomatic Kotlin Wrapper for The Discord API" const val projectUrl = "https://github.com/kordlib/kord" } - -private val Project.tag - get() = git("tag", "--no-column", "--points-at", "HEAD") - .takeIf { it.isNotBlank() } - ?.lines() - ?.single() - -val Project.libraryVersion - get() = tag ?: run { - val snapshotPrefix = when (val branch = git("branch", "--show-current")) { - "main" -> providers.gradleProperty("nextPlannedVersion").get() - else -> branch.replace('/', '-') - } - "$snapshotPrefix-SNAPSHOT" - } - -val Project.commitHash get() = git("rev-parse", "--verify", "HEAD") -val Project.shortCommitHash get() = git("rev-parse", "--short", "HEAD") - -val Project.isRelease get() = tag != null - -object Repo { - const val releasesUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" - const val snapshotsUrl = "https://oss.sonatype.org/content/repositories/snapshots/" -} diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 2a054a6cb54..a5e9ef293fa 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -99,36 +99,6 @@ tasks { } } - - register("publishNonNative") { - dependsOn( - "publishKotlinMultiplatformPublicationToMavenRepository", - "publishJsPublicationToMavenRepository", - "publishJvmPublicationToMavenRepository" - ) - } - - register("publishLinux") { - dependsOn("publishLinuxX64PublicationToMavenRepository") - } - - register("publishMingw") { - dependsOn("publishMingwX64PublicationToMavenRepository") - } - - register("publishDarwin") { - dependsOn( - "publishMacosArm64PublicationToMavenRepository", - "publishMacosX64PublicationToMavenRepository", - "publishIosArm64PublicationToMavenRepository", - "publishIosX64PublicationToMavenRepository", - "publishWatchosX64PublicationToMavenRepository", - "publishWatchosArm64PublicationToMavenRepository", - "publishTvosX64PublicationToMavenRepository", - "publishTvosArm64PublicationToMavenRepository" - ) - } - afterEvaluate { named("sourcesJar") { dependsOn("kspCommonMainKotlinMetadata") diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index 6c01f603544..e709093e630 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -1,81 +1,45 @@ -import java.lang.System.getenv -import java.util.Base64 - plugins { - `maven-publish` - signing + id("com.vanniktech.maven.publish.base") + dev.kord.`gradle-tools` } -fun MavenPublication.registerDokkaJar() = - tasks.register("${name}DokkaJar") { - archiveClassifier = "javadoc" - destinationDirectory = destinationDirectory.get().dir(name) - from(tasks.named("dokkaHtml")) - } - -publishing { - publications { - withType().configureEach { - if (project.name != "bom") artifact(registerDokkaJar()) - - groupId = Library.group - artifactId = "kord-$artifactId" - version = libraryVersion - - pom { - name = Library.name - description = Library.description - url = Library.projectUrl - - organization { - name = "Kord" - url = "https://github.com/kordlib" - } - - developers { - developer { - name = "The Kord Team" - } - } +mavenPublishing { + coordinates(Library.group, "cache-${project.name}") + publishToMavenCentral() + signAllPublications() - issueManagement { - system = "GitHub" - url = "https://github.com/kordlib/kord/issues" - } + pom { + name = Library.name + description = Library.description + url = Library.projectUrl - licenses { - license { - name = "MIT" - url = "https://opensource.org/licenses/MIT" - } - } + organization { + name = "Kord" + url = "https://github.com/kordlib" + } - scm { - connection = "scm:git:ssh://github.com/kordlib/kord.git" - developerConnection = "scm:git:ssh://git@github.com:kordlib/kord.git" - url = Library.projectUrl - } + developers { + developer { + name = "The Kord Team" } } - } - repositories { - maven { - url = uri(if (isRelease) Repo.releasesUrl else Repo.snapshotsUrl) + issueManagement { + system = "GitHub" + url = "https://github.com/kordlib/kord/issues" + } - credentials { - username = getenv("NEXUS_USER") - password = getenv("NEXUS_PASSWORD") + licenses { + license { + name = "MIT" + url = "https://opensource.org/licenses/MIT" } } - } -} -signing { - val secretKey = getenv("SIGNING_KEY")?.let { String(Base64.getDecoder().decode(it)) } - val password = getenv("SIGNING_PASSWORD") - useInMemoryPgpKeys(secretKey, password) - if (secretKey != null && password != null) { - sign(publishing.publications) + scm { + connection = "scm:git:ssh://github.com/kordlib/kord.git" + developerConnection = "scm:git:ssh://git@github.com:kordlib/kord.git" + url = Library.projectUrl + } } } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 9de88e5ddd4..1c4c3473a02 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,3 +1,6 @@ +import dev.kord.gradle.tools.util.commitHash +import dev.kord.gradle.tools.util.shortCommitHash + plugins { `kord-native-module` `kord-multiplatform-module` @@ -84,7 +87,7 @@ buildConfig { internalVisibility = true } - buildConfigField("BUILD_CONFIG_GENERATED_LIBRARY_VERSION", libraryVersion) + buildConfigField("BUILD_CONFIG_GENERATED_LIBRARY_VERSION", provider { project.version.toString() }) buildConfigField("BUILD_CONFIG_GENERATED_COMMIT_HASH", commitHash) buildConfigField("BUILD_CONFIG_GENERATED_SHORT_COMMIT_HASH", shortCommitHash) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 33d42618849..fe2a0fa7a72 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,13 +1,12 @@ [versions] # api dependencies -kotlin = "1.9.21" # https://github.com/JetBrains/kotlin +kotlin = "1.9.22" # https://github.com/JetBrains/kotlin ktor = "3.0.0-beta-1" # https://github.com/ktorio/ktor kotlinx-coroutines = "1.7.3" # https://github.com/Kotlin/kotlinx.coroutines kotlinx-serialization = "1.6.2" # https://github.com/Kotlin/kotlinx.serialization kotlinx-datetime = "0.5.0" # https://github.com/Kotlin/kotlinx-datetime kotlin-logging = "6.0.1" # https://github.com/oshai/kotlin-logging -kotlin-logging-old = "3.0.5" # TODO remove after dependency is removed in rest, gateway, voice and core kord-cache = "0.5.0-SNAPSHOT" # https://github.com/kordlib/cache # implementation dependencies @@ -18,7 +17,7 @@ fastZlib = "2.0.1" # https://github.com/timotejroiko/fast-zlib sodium = "0.9.0" # https://github.com/ionspin/kotlin-multiplatform-libsodium # code generation -ksp = "1.9.21-1.0.16" # https://github.com/google/ksp +ksp = "1.9.22-1.0.16" # https://github.com/google/ksp kotlinpoet = "1.15.3" # https://github.com/square/kotlinpoet # tests @@ -62,7 +61,6 @@ kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version. # other kotlin-logging = { module = "io.github.oshai:kotlin-logging", version.ref = "kotlin-logging" } -kotlin-logging-old = { module = "io.github.microutils:kotlin-logging", version.ref = "kotlin-logging-old" } slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } kotlin-node = { module = "org.jetbrains.kotlin-wrappers:kotlin-node", version.ref = "kotlin-node" } @@ -94,6 +92,8 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } +kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.5" } +maven-publish-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.27.0" } [bundles] @@ -110,6 +110,8 @@ pluginsForBuildSrc = [ "atomicfu-plugin", "binary-compatibility-validator-plugin", "ksp-plugin", + "kord-gradle-plugin", + "maven-publish-plugin" ] From 79dfd50964cf8712bd2b2f96ef52862dd4884979 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 15:49:37 +0100 Subject: [PATCH 25/83] Ignore file based tests on Apple Simulators --- common/src/commonTest/kotlin/json/ChannelTest.kt | 2 ++ common/src/commonTest/kotlin/json/EmojiTest.kt | 2 ++ common/src/commonTest/kotlin/json/GuildTest.kt | 2 ++ common/src/commonTest/kotlin/json/InteractionTest.kt | 2 ++ common/src/commonTest/kotlin/json/MessageTest.kt | 2 ++ common/src/commonTest/kotlin/json/PermissionsTest.kt | 2 ++ common/src/commonTest/kotlin/json/UserTest.kt | 2 ++ common/src/commonTest/kotlin/json/VoiceStateTest.kt | 2 ++ gateway/src/commonTest/kotlin/json/CommandTest.kt | 2 ++ .../src/commonTest/kotlin/json/RegressionTests.kt | 2 ++ .../src/commonTest/kotlin/json/SerializationTest.kt | 2 ++ gateway/src/commonTest/kotlin/json/SnowflakeTest.kt | 2 ++ .../commonTest/kotlin/json/AuditLogResponseTest.kt | 2 ++ rest/src/commonTest/kotlin/json/ErrorTest.kt | 2 ++ test-kit/build.gradle.kts | 12 ++++++++++++ test-kit/src/commonMain/kotlin/Annotations.kt | 5 +++++ .../kotlin/IgnoreOnSimulatorPlatforms.kt | 5 +++++ 17 files changed, 50 insertions(+) create mode 100644 test-kit/src/simulatorMain/kotlin/IgnoreOnSimulatorPlatforms.kt diff --git a/common/src/commonTest/kotlin/json/ChannelTest.kt b/common/src/commonTest/kotlin/json/ChannelTest.kt index 9851007c24d..5a0da21c1b1 100644 --- a/common/src/commonTest/kotlin/json/ChannelTest.kt +++ b/common/src/commonTest/kotlin/json/ChannelTest.kt @@ -3,6 +3,7 @@ package dev.kord.common.json import dev.kord.common.entity.DiscordChannel import dev.kord.common.entity.optional.value import dev.kord.common.readFile +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import kotlin.js.JsName @@ -11,6 +12,7 @@ import kotlin.test.Test private suspend fun file(name: String): String = readFile("channel", name) +@IgnoreOnSimulatorPlatforms class ChannelTest { @Test diff --git a/common/src/commonTest/kotlin/json/EmojiTest.kt b/common/src/commonTest/kotlin/json/EmojiTest.kt index 7af78e1c6ef..3d6b6cd649a 100644 --- a/common/src/commonTest/kotlin/json/EmojiTest.kt +++ b/common/src/commonTest/kotlin/json/EmojiTest.kt @@ -3,6 +3,7 @@ package dev.kord.common.json import dev.kord.common.entity.DiscordEmoji import dev.kord.common.entity.Snowflake import dev.kord.common.readFile +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import kotlin.js.JsName @@ -10,6 +11,7 @@ import kotlin.test.Test private suspend fun file(name: String): String = readFile("emoji", name) +@IgnoreOnSimulatorPlatforms class EmojiTest { @Test diff --git a/common/src/commonTest/kotlin/json/GuildTest.kt b/common/src/commonTest/kotlin/json/GuildTest.kt index 93549a01ca0..136c9e5a4d0 100644 --- a/common/src/commonTest/kotlin/json/GuildTest.kt +++ b/common/src/commonTest/kotlin/json/GuildTest.kt @@ -3,6 +3,7 @@ package dev.kord.common.json import dev.kord.common.entity.* import dev.kord.common.entity.Permission.* import dev.kord.common.readFile +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.datetime.Instant import kotlinx.serialization.json.Json @@ -12,6 +13,7 @@ import kotlin.time.Duration.Companion.seconds private suspend fun file(name: String): String = readFile("guild", name) +@IgnoreOnSimulatorPlatforms class GuildTest { @Test diff --git a/common/src/commonTest/kotlin/json/InteractionTest.kt b/common/src/commonTest/kotlin/json/InteractionTest.kt index 6d73f785727..3e7113ac9c9 100644 --- a/common/src/commonTest/kotlin/json/InteractionTest.kt +++ b/common/src/commonTest/kotlin/json/InteractionTest.kt @@ -4,6 +4,7 @@ import dev.kord.common.entity.* import dev.kord.common.entity.Permission.* import dev.kord.common.entity.optional.orEmpty import dev.kord.common.readFile +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import kotlin.js.JsName @@ -20,6 +21,7 @@ private val perms = Permissions( ManageGuildExpressions, ) +@IgnoreOnSimulatorPlatforms class InteractionTest { val json = Json { diff --git a/common/src/commonTest/kotlin/json/MessageTest.kt b/common/src/commonTest/kotlin/json/MessageTest.kt index 2b4332166de..bef454cc9e8 100644 --- a/common/src/commonTest/kotlin/json/MessageTest.kt +++ b/common/src/commonTest/kotlin/json/MessageTest.kt @@ -2,6 +2,7 @@ package dev.kord.common.json import dev.kord.common.entity.* import dev.kord.common.readFile +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.datetime.Instant import kotlinx.serialization.json.Json @@ -10,6 +11,7 @@ import kotlin.test.Test private suspend fun file(name: String): String = readFile("message", name) +@IgnoreOnSimulatorPlatforms class MessageTest { @Test diff --git a/common/src/commonTest/kotlin/json/PermissionsTest.kt b/common/src/commonTest/kotlin/json/PermissionsTest.kt index 291985a2aec..98b1b066ecc 100644 --- a/common/src/commonTest/kotlin/json/PermissionsTest.kt +++ b/common/src/commonTest/kotlin/json/PermissionsTest.kt @@ -3,6 +3,7 @@ package dev.kord.common.json import dev.kord.common.entity.DiscordRole import dev.kord.common.entity.Permission import dev.kord.common.entity.Permissions +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.serialization.json.Json import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.put @@ -10,6 +11,7 @@ import kotlin.js.JsName import kotlin.test.Test import kotlin.test.assertEquals +@IgnoreOnSimulatorPlatforms class PermissionsTest { @Test diff --git a/common/src/commonTest/kotlin/json/UserTest.kt b/common/src/commonTest/kotlin/json/UserTest.kt index 4b1fc18877a..071cbdcaec9 100644 --- a/common/src/commonTest/kotlin/json/UserTest.kt +++ b/common/src/commonTest/kotlin/json/UserTest.kt @@ -4,6 +4,7 @@ import dev.kord.common.entity.DiscordUser import dev.kord.common.entity.UserFlag.HouseBravery import dev.kord.common.entity.UserFlags import dev.kord.common.readFile +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import kotlin.js.JsName @@ -11,6 +12,7 @@ import kotlin.test.Test private suspend fun file(name: String): String = readFile("user", name) +@IgnoreOnSimulatorPlatforms class UserTest { @Test diff --git a/common/src/commonTest/kotlin/json/VoiceStateTest.kt b/common/src/commonTest/kotlin/json/VoiceStateTest.kt index 1d73de02faf..d3988d802a0 100644 --- a/common/src/commonTest/kotlin/json/VoiceStateTest.kt +++ b/common/src/commonTest/kotlin/json/VoiceStateTest.kt @@ -2,6 +2,7 @@ package dev.kord.common.json import dev.kord.common.entity.DiscordVoiceState import dev.kord.common.readFile +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.datetime.Instant import kotlinx.serialization.json.Json @@ -10,6 +11,7 @@ import kotlin.test.Test private suspend fun file(name: String): String = readFile("voice", name) +@IgnoreOnSimulatorPlatforms class VoiceStateTest { @Test diff --git a/gateway/src/commonTest/kotlin/json/CommandTest.kt b/gateway/src/commonTest/kotlin/json/CommandTest.kt index ffb1174f0c7..24114b5a5bb 100644 --- a/gateway/src/commonTest/kotlin/json/CommandTest.kt +++ b/gateway/src/commonTest/kotlin/json/CommandTest.kt @@ -9,6 +9,7 @@ import dev.kord.common.entity.optional.coerceToMissing import dev.kord.common.entity.optional.optional import dev.kord.common.entity.optional.optionalInt import dev.kord.gateway.* +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.datetime.Instant import kotlinx.serialization.json.* import kotlin.js.JsName @@ -17,6 +18,7 @@ import kotlin.test.assertEquals private val json = Json { encodeDefaults = false } +@IgnoreOnSimulatorPlatforms class CommandTest { @Test @JsName("test1") diff --git a/gateway/src/commonTest/kotlin/json/RegressionTests.kt b/gateway/src/commonTest/kotlin/json/RegressionTests.kt index 831aade5e82..c174bc42dae 100644 --- a/gateway/src/commonTest/kotlin/json/RegressionTests.kt +++ b/gateway/src/commonTest/kotlin/json/RegressionTests.kt @@ -2,6 +2,7 @@ package dev.kord.gateway.json import dev.kord.gateway.Event import dev.kord.gateway.Reconnect +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import kotlin.js.JsName @@ -9,6 +10,7 @@ import kotlin.test.Test private suspend fun file(name: String): String = readFile("regression", name) +@IgnoreOnSimulatorPlatforms class RegressionTests { @Test @JsName("test1") diff --git a/gateway/src/commonTest/kotlin/json/SerializationTest.kt b/gateway/src/commonTest/kotlin/json/SerializationTest.kt index 8d546fd04bd..a5edd6c7fb8 100644 --- a/gateway/src/commonTest/kotlin/json/SerializationTest.kt +++ b/gateway/src/commonTest/kotlin/json/SerializationTest.kt @@ -6,6 +6,7 @@ import dev.kord.common.entity.UserPremium import dev.kord.common.entity.optional.Optional import dev.kord.common.entity.optional.value import dev.kord.gateway.* +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.datetime.Instant import kotlinx.serialization.json.Json @@ -15,6 +16,7 @@ import kotlin.time.Duration.Companion.seconds private suspend fun file(name: String): String = readFile("event", name) +@IgnoreOnSimulatorPlatforms class SerializationTest { @Test diff --git a/gateway/src/commonTest/kotlin/json/SnowflakeTest.kt b/gateway/src/commonTest/kotlin/json/SnowflakeTest.kt index d3db76c8ccd..9945d395105 100644 --- a/gateway/src/commonTest/kotlin/json/SnowflakeTest.kt +++ b/gateway/src/commonTest/kotlin/json/SnowflakeTest.kt @@ -1,6 +1,7 @@ package dev.kord.gateway.json import dev.kord.common.entity.Snowflake +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString @@ -9,6 +10,7 @@ import kotlin.js.JsName import kotlin.test.Test import kotlin.test.assertEquals +@IgnoreOnSimulatorPlatforms class SnowflakeTest { @Serializable diff --git a/rest/src/commonTest/kotlin/json/AuditLogResponseTest.kt b/rest/src/commonTest/kotlin/json/AuditLogResponseTest.kt index c53cb4a83cf..b87d7724f40 100644 --- a/rest/src/commonTest/kotlin/json/AuditLogResponseTest.kt +++ b/rest/src/commonTest/kotlin/json/AuditLogResponseTest.kt @@ -1,11 +1,13 @@ package dev.kord.rest.json import dev.kord.common.entity.DiscordAuditLog +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import kotlin.js.JsName import kotlin.test.Test +@IgnoreOnSimulatorPlatforms class AuditLogResponseTest { @Test diff --git a/rest/src/commonTest/kotlin/json/ErrorTest.kt b/rest/src/commonTest/kotlin/json/ErrorTest.kt index 7b641c3b218..8155bb8cb31 100644 --- a/rest/src/commonTest/kotlin/json/ErrorTest.kt +++ b/rest/src/commonTest/kotlin/json/ErrorTest.kt @@ -1,12 +1,14 @@ package dev.kord.rest.json import dev.kord.rest.json.response.DiscordErrorResponse +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import kotlin.js.JsName import kotlin.test.Test import kotlin.test.assertEquals +@IgnoreOnSimulatorPlatforms class ErrorTest { private val parser = Json { encodeDefaults = false diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index d924f089e5a..ad89334e64f 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -1,9 +1,21 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi + plugins { `kord-native-module` `kord-internal-multiplatform-module` } +@OptIn(ExperimentalKotlinGradlePluginApi::class) kotlin { + applyDefaultHierarchyTemplate { + common { + group("simulator") { + withIos() + withTvos() + withWasm() + } + } + } sourceSets { commonMain { dependencies { diff --git a/test-kit/src/commonMain/kotlin/Annotations.kt b/test-kit/src/commonMain/kotlin/Annotations.kt index a2b8b3ae23d..1da1d84342a 100644 --- a/test-kit/src/commonMain/kotlin/Annotations.kt +++ b/test-kit/src/commonMain/kotlin/Annotations.kt @@ -19,3 +19,8 @@ expect annotation class IgnoreOnJvm() @Target(CLASS, FUNCTION) @OptionalExpectation expect annotation class IgnoreOnNative() + +/** Ignores this test on simulator platforms. */ +@Target(CLASS, FUNCTION) +@OptionalExpectation +expect annotation class IgnoreOnSimulatorPlatforms() diff --git a/test-kit/src/simulatorMain/kotlin/IgnoreOnSimulatorPlatforms.kt b/test-kit/src/simulatorMain/kotlin/IgnoreOnSimulatorPlatforms.kt new file mode 100644 index 00000000000..f0b4f1a3624 --- /dev/null +++ b/test-kit/src/simulatorMain/kotlin/IgnoreOnSimulatorPlatforms.kt @@ -0,0 +1,5 @@ +package dev.kord.test + +import kotlin.test.Ignore + +actual typealias IgnoreOnSimulatorPlatforms = Ignore From dfaae7526ca4ad26fd8e02df577877effd959f34 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 15:59:54 +0100 Subject: [PATCH 26/83] Fix resolution of test files on Kotlin/Native --- .../src/main/kotlin/kord-multiplatform-module.gradle.kts | 5 +++++ test-kit/src/nativeMain/kotlin/Platform.kt | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index a5e9ef293fa..2a7963d404f 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -2,6 +2,7 @@ import org.gradle.configurationcache.extensions.capitalized import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest +import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest plugins { org.jetbrains.kotlin.multiplatform @@ -84,6 +85,10 @@ tasks { environment("PROJECT_ROOT", rootProject.projectDir.absolutePath) } + withType().configureEach { + environment("PROJECT_ROOT", rootProject.projectDir.absolutePath) + } + afterEvaluate { val compilationTasks = kotlin.targets.flatMap { buildList { diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt index 71d88fed0d8..4ae488eb3a6 100644 --- a/test-kit/src/nativeMain/kotlin/Platform.kt +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -26,13 +26,13 @@ actual object Platform { @OptIn(ExperimentalForeignApi::class) actual fun getEnv(name: String) = getenv(name)?.toKString() -actual suspend fun file(project: String, path: String): String = read(path, Source::readString) +actual suspend fun file(project: String, path: String): String = read(project, path, Source::readString) actual suspend fun readFile(project: String, path: String): ByteReadChannel = - read(path) { ByteReadChannel(readByteArray()) } + read(project, path) { ByteReadChannel(readByteArray()) } -private inline fun read(path: String, readerAction: Source.() -> T): T { - val actualPath = Path(path) +private inline fun read(project: String, path: String, readerAction: Source.() -> T): T { + val actualPath = Path("${getEnv("PROJECT_ROOT")}/$project/src/commonTest/resources/$path") return try { SystemFileSystem.source(actualPath).buffered().readerAction() } catch (e: Throwable) { From 091f1a88f73c6015be8faf526ad6902f624e2f02 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 16:06:07 +0100 Subject: [PATCH 27/83] Replace withWasm() with withWatchos() as intended --- test-kit/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index ad89334e64f..ef1e6491205 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -12,7 +12,7 @@ kotlin { group("simulator") { withIos() withTvos() - withWasm() + withWatchos() } } } From f5f3d103221a2bf227ea51997c23ce3094b55d17 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 16:29:44 +0100 Subject: [PATCH 28/83] Fix build --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fe2a0fa7a72..c79ba94b5bc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ kotlinx-coroutines = "1.7.3" # https://github.com/Kotlin/kotlinx.coroutines kotlinx-serialization = "1.6.2" # https://github.com/Kotlin/kotlinx.serialization kotlinx-datetime = "0.5.0" # https://github.com/Kotlin/kotlinx-datetime kotlin-logging = "6.0.1" # https://github.com/oshai/kotlin-logging -kord-cache = "0.5.0-SNAPSHOT" # https://github.com/kordlib/cache +kord-cache = "0.5.0-20240130.022209-2" # https://github.com/kordlib/cache # implementation dependencies kotlin-node = "18.16.12-pre.619" # https://github.com/JetBrains/kotlin-wrappers @@ -92,7 +92,7 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } -kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.5" } +kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.6" } maven-publish-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.27.0" } [bundles] From 7580dd7e6c51bac8951a5f9022bd41c3d0b7ddf8 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 16:42:19 +0100 Subject: [PATCH 29/83] Disable flaky tests --- rest/src/commonTest/kotlin/request/MessageRequests.kt | 2 ++ rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/rest/src/commonTest/kotlin/request/MessageRequests.kt b/rest/src/commonTest/kotlin/request/MessageRequests.kt index 6e43c1d9dec..4ce92ad2cff 100644 --- a/rest/src/commonTest/kotlin/request/MessageRequests.kt +++ b/rest/src/commonTest/kotlin/request/MessageRequests.kt @@ -8,6 +8,7 @@ import dev.kord.common.entity.Snowflake import dev.kord.common.entity.optional.Optional import dev.kord.rest.json.readFile import dev.kord.rest.service.ChannelService +import dev.kord.test.IgnoreOnSimulatorPlatforms import dev.kord.test.Platform import io.ktor.client.* import io.ktor.client.engine.mock.* @@ -52,6 +53,7 @@ private val mockMessage = DiscordMessage( class MessageRequests { @Test @JsName("test1") + @IgnoreOnSimulatorPlatforms fun `attachment channel is read and closed lazily`() = runTest { val mockEngine = MockEngine { request -> diff --git a/rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt b/rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt index 69aa3eadcd2..df53d84ad2e 100644 --- a/rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt +++ b/rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt @@ -2,6 +2,7 @@ package dev.kord.rest.request import dev.kord.rest.json.response.GatewayResponse import dev.kord.rest.route.Route +import dev.kord.test.IgnoreOnSimulatorPlatforms import io.ktor.client.* import io.ktor.client.engine.mock.* import io.ktor.http.* @@ -15,6 +16,7 @@ expect class StackTraceElement expect fun currentThreadStackTrace(): StackTraceElement internal expect fun RecoveredStackTrace.validate(expected: StackTraceElement) +@IgnoreOnSimulatorPlatforms class StackTraceRecoveryTest { @Test From 3ffd8c8854e2d13b2401cebad25b84151932c507 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 17:08:28 +0100 Subject: [PATCH 30/83] Fix stack trace recovery tests on Kotlin/Native --- rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt | 2 -- .../src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt b/rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt index df53d84ad2e..69aa3eadcd2 100644 --- a/rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt +++ b/rest/src/commonTest/kotlin/request/StackTraceRecoveryTest.kt @@ -2,7 +2,6 @@ package dev.kord.rest.request import dev.kord.rest.json.response.GatewayResponse import dev.kord.rest.route.Route -import dev.kord.test.IgnoreOnSimulatorPlatforms import io.ktor.client.* import io.ktor.client.engine.mock.* import io.ktor.http.* @@ -16,7 +15,6 @@ expect class StackTraceElement expect fun currentThreadStackTrace(): StackTraceElement internal expect fun RecoveredStackTrace.validate(expected: StackTraceElement) -@IgnoreOnSimulatorPlatforms class StackTraceRecoveryTest { @Test diff --git a/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt b/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt index 41e0a08d13a..9a63fd0cd99 100644 --- a/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt +++ b/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt @@ -13,11 +13,11 @@ actual typealias StackTraceElement = String //-->at 5 ??? 7ff684fbdeca kfun:dev.kord.rest.request.StackTraceRecoveryTest.$test stack trace<-- actual fun currentThreadStackTrace(): StackTraceElement = Exception().stackTraceToString().lineSequence().filterNot(String::isBlank).drop(5).first().trim() - .substringAfter("???") + .substringAfter("0x") internal actual fun RecoveredStackTrace.validate(expected: StackTraceElement) { // The first few lines are artifacts from coroutines which are not present in expected val actual = stackTraceToString().lineSequence().drop(6).first().trim() - .substringAfter("???") // index is off at call site + .substringAfter("0x") // index is off at call site assertEquals(expected, actual) } From 3dbc6dcbb01e8d958b039187c8db7fb983f2c269 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 17:20:17 +0100 Subject: [PATCH 31/83] Fix build agian --- buildSrc/src/main/kotlin/kord-publishing.gradle.kts | 7 +++++++ gradle/libs.versions.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index e709093e630..7ed8f12af41 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -1,8 +1,15 @@ +import org.jetbrains.kotlin.konan.target.KonanTarget + plugins { id("com.vanniktech.maven.publish.base") dev.kord.`gradle-tools` } +kord { + publicationName = "mavenCentral" + metadataHost = KonanTarget.MACOS_ARM64 +} + mavenPublishing { coordinates(Library.group, "cache-${project.name}") publishToMavenCentral() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c79ba94b5bc..377bd864f69 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -92,7 +92,7 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } -kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.6" } +kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.7" } maven-publish-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.27.0" } [bundles] From 7227398015c121eb45f981bb03bd457707809572 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 18:00:50 +0100 Subject: [PATCH 32/83] Fix build again --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 377bd864f69..f6293267b13 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -92,7 +92,7 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } -kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.7" } +kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.8" } maven-publish-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.27.0" } [bundles] From 3d145e66dd634d0d715ad1512d81a112bdcf460f Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 18:21:00 +0100 Subject: [PATCH 33/83] Fix broken StackTraceRecovery test on Windows --- .../src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt b/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt index 9a63fd0cd99..8c9d00a4697 100644 --- a/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt +++ b/rest/src/nativeTest/kotlin/dev/kord/rest/request/StackTrace.kt @@ -13,11 +13,11 @@ actual typealias StackTraceElement = String //-->at 5 ??? 7ff684fbdeca kfun:dev.kord.rest.request.StackTraceRecoveryTest.$test stack trace<-- actual fun currentThreadStackTrace(): StackTraceElement = Exception().stackTraceToString().lineSequence().filterNot(String::isBlank).drop(5).first().trim() - .substringAfter("0x") + .substringAfter("kfun:") internal actual fun RecoveredStackTrace.validate(expected: StackTraceElement) { // The first few lines are artifacts from coroutines which are not present in expected val actual = stackTraceToString().lineSequence().drop(6).first().trim() - .substringAfter("0x") // index is off at call site + .substringAfter("kfun:") // index is off at call site assertEquals(expected, actual) } From 1ca3ea61493656a7f67e08e5ab5bec90a556171e Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 19:34:32 +0100 Subject: [PATCH 34/83] Api dump --- core/api/core.api | 1 - voice/api/voice.api | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/api/core.api b/core/api/core.api index a535d1f6dd6..e509d02fb30 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -101,7 +101,6 @@ public final class dev/kord/core/Kord$Companion { public final class dev/kord/core/KordKt { public static final fun Kord (Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun Kord$default (Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun getKordLogger ()Lmu/KLogger; public static final fun logCaughtThrowable (Ljava/lang/Throwable;)V } diff --git a/voice/api/voice.api b/voice/api/voice.api index e213650a0dc..48af75591dd 100644 --- a/voice/api/voice.api +++ b/voice/api/voice.api @@ -994,7 +994,6 @@ public final class dev/kord/voice/gateway/VoiceGatewayConfiguration { } public final class dev/kord/voice/gateway/VoiceGatewayKt { - public static final fun getVoiceGatewayOnLogger ()Lmu/KLogger; public static final fun logCaughtThrowable (Ljava/lang/Throwable;)V } @@ -1146,7 +1145,11 @@ public final class dev/kord/voice/udp/DefaultAudioFrameSenderData { public fun toString ()Ljava/lang/String; } -public final class dev/kord/voice/udp/DefaultAudioPacketProvider : dev/kord/voice/udp/AudioPacketProvider { +public final class dev/kord/voice/udp/DefaultAudioPacketProviderKt { + public static final fun DefaultAudioPacketProvider ([BLdev/kord/voice/encryption/strategies/NonceStrategy;)Ldev/kord/voice/udp/AudioPacketProvider; +} + +public final class dev/kord/voice/udp/DefaultJvmAudioPacketProvider : dev/kord/voice/udp/AudioPacketProvider { public fun ([BLdev/kord/voice/encryption/strategies/NonceStrategy;)V public fun provide-jfaDVJw (SII[B)Ldev/kord/voice/io/ByteArrayView; } @@ -1179,6 +1182,7 @@ public final class dev/kord/voice/udp/PayloadType$Companion { public final class dev/kord/voice/udp/PayloadType$Unknown : dev/kord/voice/udp/PayloadType { public fun (B)V + public fun toString ()Ljava/lang/String; } public final class dev/kord/voice/udp/RTPPacket { From c584c6de89c0377952743ddd6187040212795ab7 Mon Sep 17 00:00:00 2001 From: schlaubi Date: Mon, 29 Jan 2024 20:03:13 +0100 Subject: [PATCH 35/83] Fix invalid coordinates --- buildSrc/src/main/kotlin/kord-publishing.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index 7ed8f12af41..724848e837f 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -11,7 +11,7 @@ kord { } mavenPublishing { - coordinates(Library.group, "cache-${project.name}") + coordinates(Library.group, "kord-${project.name}") publishToMavenCentral() signAllPublications() From 07450189fd7980c73b11c055562934c0b26f1ef7 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 30 Jan 2024 19:32:49 +0100 Subject: [PATCH 36/83] Enable linuxArm64 & disable broken test --- buildSrc/src/main/kotlin/kord-native-module.gradle.kts | 4 +--- core/src/commonTest/kotlin/performance/KordEventDropTest.kt | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index dfe78f434ea..54c2a5ef695 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -9,9 +9,7 @@ kotlin { // Please use WSL if you need to work on the linux port if (!Os.isFamily(Os.FAMILY_WINDOWS)) { linuxX64() - // Waiting for Ktor - // https://youtrack.jetbrains.com/issue/KTOR-6173 - //linuxArm64() + linuxArm64() } if (name != "voice" && name != "core-voice") { diff --git a/core/src/commonTest/kotlin/performance/KordEventDropTest.kt b/core/src/commonTest/kotlin/performance/KordEventDropTest.kt index 637a0fbe10d..7b7c18d25f3 100644 --- a/core/src/commonTest/kotlin/performance/KordEventDropTest.kt +++ b/core/src/commonTest/kotlin/performance/KordEventDropTest.kt @@ -12,6 +12,7 @@ import dev.kord.gateway.* import dev.kord.gateway.builder.Shards import dev.kord.rest.request.KtorRequestHandler import dev.kord.rest.service.RestClient + import dev.kord.test.IgnoreOnNative import io.ktor.client.* import kotlinx.atomicfu.atomic import kotlinx.coroutines.CompletableDeferred @@ -63,6 +64,8 @@ class KordEventDropTest { ) @Test + // This test seems to timeout sometimes on native + @IgnoreOnNative @JsName("test1") fun `hammering the gateway does not drop core events`() = runTest { val amount = 1_000 From 1f64effd48af3d454d6ffcca42e63b2ac20b39c8 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Wed, 31 Jan 2024 18:58:12 +0100 Subject: [PATCH 37/83] ci test From 91b6de5f6a0bfb7c9c4ad3ea22cc42d0ad5491de Mon Sep 17 00:00:00 2001 From: schlaubi Date: Wed, 31 Jan 2024 14:53:59 +0100 Subject: [PATCH 38/83] Remove workaround for ktor --- core/src/commonMain/kotlin/builder/kord/KordBuilder.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt index e04f44102c3..c9c1cafc536 100644 --- a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt +++ b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt @@ -49,8 +49,7 @@ public abstract class BaseKordBuilder internal constructor(public val token: Str val rateLimiter = IdentifyRateLimiter(resources.maxConcurrency, defaultDispatcher) shards.map { DefaultGateway { - // Workaround for: https://github.com/ktorio/ktor/pull/3950#issuecomment-1909088751 -// client = resources.httpClient + client = resources.httpClient identifyRateLimiter = rateLimiter } } From 70c6458e44a1609c9125af05421e644333b79464 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Wed, 31 Jan 2024 18:40:30 +0100 Subject: [PATCH 39/83] Update libs.versions.toml --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f6293267b13..9801b851804 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -92,7 +92,7 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } -kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.8" } +kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.9" } maven-publish-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.27.0" } [bundles] From 9a270ea78b7bde72a9452a84aa92b7d4e0214186 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Thu, 29 Feb 2024 16:37:38 +0100 Subject: [PATCH 40/83] Upgrade gradle-tools to 1.3.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9801b851804..a4e2bb31d8a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -92,7 +92,7 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } -kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.2.9" } +kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.3.0" } maven-publish-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.27.0" } [bundles] From 0066b28247de2d4c2db8c5f90cbd3e0de122f774 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Mon, 4 Mar 2024 02:51:04 +0100 Subject: [PATCH 41/83] Fix dokka jar not being generated --- buildSrc/src/main/kotlin/kord-publishing.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index 724848e837f..6836cce11ae 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -1,3 +1,5 @@ +import com.vanniktech.maven.publish.JavadocJar +import com.vanniktech.maven.publish.KotlinMultiplatform import org.jetbrains.kotlin.konan.target.KonanTarget plugins { @@ -15,6 +17,10 @@ mavenPublishing { publishToMavenCentral() signAllPublications() + if (plugins.hasPlugin("org.jetbrains.kotlin.multiplatform")) { + configure(KotlinMultiplatform(javadocJar = JavadocJar.Dokka("dokkaHtml"))) + } + pom { name = Library.name description = Library.description From 3b3dbb5c84bd92f704461636b7339e0d47602060 Mon Sep 17 00:00:00 2001 From: lukellmann Date: Mon, 4 Mar 2024 19:51:49 +0100 Subject: [PATCH 42/83] Remove kotlin-logging-old version I missed this when merging main into feature/native. --- gradle/libs.versions.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7f7f35c5da4..61983d8f10d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,6 @@ kord-cache = "0.5.0-20240130.022209-2" # https://github.com/kordlib/cache # implementation dependencies kotlin-logging = "6.0.3" # https://github.com/oshai/kotlin-logging -kotlin-logging-old = "3.0.5" # TODO remove after dependency is removed in rest, gateway, voice and core slf4j = "2.0.12" # https://www.slf4j.org kotlin-node = "20.11.5-pre.706" # https://github.com/JetBrains/kotlin-wrappers bignum = "0.3.9" # https://github.com/ionspin/kotlin-multiplatform-bignum From dd69ed90dfaf7e4051012b4d670e1371b425e8cf Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Mon, 4 Mar 2024 21:53:39 +0100 Subject: [PATCH 43/83] Apply suggestions from code review Co-authored-by: Luca Kellermann --- .../src/main/kotlin/kord-multiplatform-module.gradle.kts | 6 +----- buildSrc/src/main/kotlin/kord-native-module.gradle.kts | 2 +- samples/src/voiceMain/kotlin/VoiceBot.kt | 2 +- test-kit/src/nativeMain/kotlin/Platform.kt | 2 +- voice/src/commonMain/kotlin/udp/PayloadType.kt | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 9adc3960ef4..d5afd7918b6 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -92,11 +92,7 @@ tasks { afterEvaluate { val compilationTasks = kotlin.targets.flatMap { - buildList { - add("compileKotlin${it.name.capitalized()}") - val sourcesJarName = "${it.name}SourcesJar" - add(sourcesJarName) - } + listOf("compileKotlin${it.name.capitalized()}", "${it.name}SourcesJar") } for (task in compilationTasks) { named(task) { diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts index 54c2a5ef695..a6e5a849285 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-native-module.gradle.kts @@ -5,7 +5,7 @@ plugins { } kotlin { - // There are issues with compiling the linux variant on linux + // There are issues with compiling the linux variant on windows // Please use WSL if you need to work on the linux port if (!Os.isFamily(Os.FAMILY_WINDOWS)) { linuxX64() diff --git a/samples/src/voiceMain/kotlin/VoiceBot.kt b/samples/src/voiceMain/kotlin/VoiceBot.kt index e686df74d90..c34224b35ef 100644 --- a/samples/src/voiceMain/kotlin/VoiceBot.kt +++ b/samples/src/voiceMain/kotlin/VoiceBot.kt @@ -36,7 +36,7 @@ fun main(args: Array) = runBlocking { } private suspend fun BaseVoiceChannelBehavior.connectEcho() { - val buffer = ArrayList(listOf(AudioFrame.SILENCE, AudioFrame.SILENCE, AudioFrame.SILENCE, AudioFrame.SILENCE)) + val buffer = mutableListOf(AudioFrame.SILENCE, AudioFrame.SILENCE, AudioFrame.SILENCE, AudioFrame.SILENCE) val connection = connect { receiveVoice = true audioProvider { diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt index 4ae488eb3a6..eb4e9e8a879 100644 --- a/test-kit/src/nativeMain/kotlin/Platform.kt +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -12,7 +12,7 @@ import platform.posix.getenv import kotlin.experimental.ExperimentalNativeApi import kotlin.native.Platform -private val darwinFamilies = listOf(OsFamily.WATCHOS, OsFamily.TVOS, OsFamily.MACOSX) +private val darwinFamilies = listOf(OsFamily.WATCHOS, OsFamily.IOS, OsFamily.TVOS, OsFamily.MACOSX) actual object Platform { actual val IS_JVM: Boolean = false diff --git a/voice/src/commonMain/kotlin/udp/PayloadType.kt b/voice/src/commonMain/kotlin/udp/PayloadType.kt index e6b529f037d..bf229d81d85 100644 --- a/voice/src/commonMain/kotlin/udp/PayloadType.kt +++ b/voice/src/commonMain/kotlin/udp/PayloadType.kt @@ -7,7 +7,7 @@ public sealed class PayloadType(public val raw: Byte) { public object Alive : PayloadType(0x37.toByte()) public object Audio : PayloadType(0x78.toByte()) public class Unknown(value: Byte) : PayloadType(value) { - override fun toString(): String = raw.toString(16) + override fun toString(): String = "PayloadType.Unknown(0x${raw.toString(16)})" } public companion object { From 5869b9aa16b45a236c6da8d60028b24225d96447 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Mon, 4 Mar 2024 21:51:53 +0100 Subject: [PATCH 44/83] Suggestions - Remove blank lines in common/build.gradle.kts - Replace kord-internal-multiplatform-module.gradle.kts and kord-native-module.gradle.kts with kord-targets.gradle.kts - Check for target family rather than explicit target in samples/build.gradle.kts - Add slf4j dependency to voice - Remove nonNative target group - Use HostManager.hostIsMingw instead of Ant's Os class - Move nativeMain builder and jsMain to nonJvmMain - Add versions of remaining Gradle plugins to [versions] block - No longer catch exception in native test kit --- ...d-internal-multiplatform-module.gradle.kts | 26 --------- .../src/main/kotlin/kord-module.gradle.kts | 58 ------------------- .../kord-multiplatform-module.gradle.kts | 14 ----- ...ule.gradle.kts => kord-targets.gradle.kts} | 10 +++- common/build.gradle.kts | 6 +- core-voice/build.gradle.kts | 2 +- core/build.gradle.kts | 2 +- core/live-tests/build.gradle.kts | 2 +- core/src/nativeMain/kotlin/KordBuilder.kt | 3 - .../kotlin/KordBuilder.kt | 0 gateway/build.gradle.kts | 2 +- gradle/libs.versions.toml | 7 ++- ksp-annotations/build.gradle.kts | 3 +- rest/build.gradle.kts | 2 +- samples/build.gradle.kts | 8 +-- test-kit/build.gradle.kts | 3 +- test-kit/src/nativeMain/kotlin/Platform.kt | 8 +-- voice/build.gradle.kts | 7 ++- 18 files changed, 31 insertions(+), 132 deletions(-) delete mode 100644 buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/kord-module.gradle.kts rename buildSrc/src/main/kotlin/{kord-native-module.gradle.kts => kord-targets.gradle.kts} (74%) delete mode 100644 core/src/nativeMain/kotlin/KordBuilder.kt rename core/src/{jsMain => nonJvmMain}/kotlin/KordBuilder.kt (100%) diff --git a/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts deleted file mode 100644 index a5624e16aba..00000000000 --- a/buildSrc/src/main/kotlin/kord-internal-multiplatform-module.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi - -plugins { - org.jetbrains.kotlin.multiplatform -} - -repositories { - mavenCentral() -} - -@OptIn(ExperimentalKotlinGradlePluginApi::class) -kotlin { - applyDefaultHierarchyTemplate() - jvm() - js { - nodejs() - useCommonJs() - } - jvmToolchain(Jvm.target) - - targets.all { - compilations.all { - compilerOptions.options.applyKordCompilerOptions() - } - } -} diff --git a/buildSrc/src/main/kotlin/kord-module.gradle.kts b/buildSrc/src/main/kotlin/kord-module.gradle.kts deleted file mode 100644 index c373ec3279f..00000000000 --- a/buildSrc/src/main/kotlin/kord-module.gradle.kts +++ /dev/null @@ -1,58 +0,0 @@ -import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask - -plugins { - org.jetbrains.kotlin.jvm - org.jetbrains.kotlin.plugin.serialization - org.jetbrains.dokka - `kotlinx-atomicfu` - org.jetbrains.kotlinx.`binary-compatibility-validator` - com.google.devtools.ksp - `maven-publish` -} - -repositories { - mavenCentral() -} - -dependencies { - ksp(project(":ksp-processors")) -} - -apiValidation { - applyKordBCVOptions() -} - -kotlin { - explicitApi() - - jvmToolchain(Jvm.target) - - compilerOptions { - applyKordCompilerOptions() - optIn.addAll(kordOptIns) - } - - sourceSets { - // allow `ExperimentalCoroutinesApi` for `TestScope.currentTime` - test { languageSettings.optIn(OptIns.coroutines) } - } -} - -configureAtomicFU() - -tasks { - withType().configureEach { - useJUnitPlatform() - } - - withType().configureEach { - applyKordDokkaOptions() - } -} - -publishing { - publications.register(Library.name) { - from(components["java"]) - artifact(tasks.kotlinSourcesJar) - } -} diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index d5afd7918b6..d34b122835e 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -33,24 +33,10 @@ kotlin { withNative() withJs() } - - group("nonNative") { - withJs() - withJvm() - } } } explicitApi() - - jvm() - - if (name != "voice" && name != "core-voice") { - js { - nodejs() - useCommonJs() - } - } jvmToolchain(Jvm.target) targets.all { diff --git a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts b/buildSrc/src/main/kotlin/kord-targets.gradle.kts similarity index 74% rename from buildSrc/src/main/kotlin/kord-native-module.gradle.kts rename to buildSrc/src/main/kotlin/kord-targets.gradle.kts index a6e5a849285..63125e6daf7 100644 --- a/buildSrc/src/main/kotlin/kord-native-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-targets.gradle.kts @@ -1,4 +1,4 @@ -import org.apache.tools.ant.taskdefs.condition.Os +import org.jetbrains.kotlin.konan.target.HostManager plugins { org.jetbrains.kotlin.multiplatform @@ -7,13 +7,19 @@ plugins { kotlin { // There are issues with compiling the linux variant on windows // Please use WSL if you need to work on the linux port - if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + if (!HostManager.hostIsMingw) { linuxX64() linuxArm64() } + jvm() + if (name != "voice" && name != "core-voice") { mingwX64() + js { + nodejs() + useCommonJs() + } } macosArm64() diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 1c4c3473a02..927677dde73 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -2,7 +2,7 @@ import dev.kord.gradle.tools.util.commitHash import dev.kord.gradle.tools.util.shortCommitHash plugins { - `kord-native-module` + `kord-targets` `kord-multiplatform-module` `kord-publishing` alias(libs.plugins.buildconfig) @@ -41,26 +41,22 @@ kotlin { implementation(projects.kspAnnotations) } } - nativeMain { dependencies { // Native does not have compileOnly implementation(projects.kspAnnotations) } } - mingwMain { dependencies { api(libs.ktor.client.winhttp) } } - appleMain { dependencies { api(libs.ktor.client.darwin) } } - linuxMain { dependencies { api(libs.ktor.client.curl) diff --git a/core-voice/build.gradle.kts b/core-voice/build.gradle.kts index 412df014aa5..d8efe0d18a8 100644 --- a/core-voice/build.gradle.kts +++ b/core-voice/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - `kord-native-module` + `kord-targets` `kord-multiplatform-module` `kord-publishing` } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index d0059c9c312..c326190d659 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - `kord-native-module` + `kord-targets` `kord-multiplatform-module` `kord-publishing` } diff --git a/core/live-tests/build.gradle.kts b/core/live-tests/build.gradle.kts index 86fe49a30fc..ea3b8e3de70 100644 --- a/core/live-tests/build.gradle.kts +++ b/core/live-tests/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - `kord-internal-multiplatform-module` + `kord-targets` } kotlin { diff --git a/core/src/nativeMain/kotlin/KordBuilder.kt b/core/src/nativeMain/kotlin/KordBuilder.kt deleted file mode 100644 index a3d196befb4..00000000000 --- a/core/src/nativeMain/kotlin/KordBuilder.kt +++ /dev/null @@ -1,3 +0,0 @@ -package dev.kord.core.builder.kord - -public actual class KordBuilder actual constructor(token: String) : BaseKordBuilder(token) diff --git a/core/src/jsMain/kotlin/KordBuilder.kt b/core/src/nonJvmMain/kotlin/KordBuilder.kt similarity index 100% rename from core/src/jsMain/kotlin/KordBuilder.kt rename to core/src/nonJvmMain/kotlin/KordBuilder.kt diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index 4d910dce089..6e3372b6f27 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - `kord-native-module` + `kord-targets` `kord-multiplatform-module` `kord-publishing` } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 61983d8f10d..b15b7247abb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,8 @@ dokka = "1.9.20" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.23.2" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.14.0" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "5.3.5" # https://github.com/gmazzo/gradle-buildconfig-plugin - +kord-gradle-tools = "1.3.0" # https://github.com/kordlib/gradle-tools +maven-publish-plugin = "0.27.0" # https://github.com/vanniktech/gradle-maven-publish-plugin [libraries] @@ -92,8 +93,8 @@ dokka-plugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref atomicfu-plugin = { module = "org.jetbrains.kotlinx:atomicfu-gradle-plugin", version.ref = "kotlinx-atomicfu" } binary-compatibility-validator-plugin = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binary-compatibility-validator" } ksp-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } -kord-gradle-plugin = { module = "dev.kord:gradle-tools", version = "1.3.0" } -maven-publish-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version = "0.27.0" } +kord-gradle-plugin = { module = "dev.kord:gradle-tools", version.ref = "kord-gradle-tools" } +maven-publish-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "maven-publish-plugin" } [bundles] diff --git a/ksp-annotations/build.gradle.kts b/ksp-annotations/build.gradle.kts index 74548672acb..4d38af49489 100644 --- a/ksp-annotations/build.gradle.kts +++ b/ksp-annotations/build.gradle.kts @@ -1,8 +1,7 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask plugins { - `kord-native-module` - `kord-internal-multiplatform-module` + `kord-targets` // workaround for https://youtrack.jetbrains.com/issue/KT-43500 (not intended to be published) org.jetbrains.dokka diff --git a/rest/build.gradle.kts b/rest/build.gradle.kts index 6ccbec4d98a..7db0c64b3ef 100644 --- a/rest/build.gradle.kts +++ b/rest/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - `kord-native-module` + `kord-targets` `kord-multiplatform-module` `kord-publishing` } diff --git a/samples/build.gradle.kts b/samples/build.gradle.kts index cf0112239c1..84b8ef3b862 100644 --- a/samples/build.gradle.kts +++ b/samples/build.gradle.kts @@ -1,10 +1,9 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget -import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.Family plugins { - `kord-internal-multiplatform-module` - `kord-native-module` + `kord-targets` } @OptIn(ExperimentalKotlinGradlePluginApi::class) @@ -23,7 +22,8 @@ kotlin { } targets.withType { - if (konanTarget != KonanTarget.MINGW_X64) { + // Voice does not target windows, so we disable it + if (konanTarget.family != Family.MINGW) { binaries.executable { entryPoint = "dev.kord.voice.test.main" } diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index ef1e6491205..4c25f2582ee 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -1,8 +1,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi plugins { - `kord-native-module` - `kord-internal-multiplatform-module` + `kord-targets` } @OptIn(ExperimentalKotlinGradlePluginApi::class) diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt index eb4e9e8a879..01887908a3e 100644 --- a/test-kit/src/nativeMain/kotlin/Platform.kt +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -33,11 +33,5 @@ actual suspend fun readFile(project: String, path: String): ByteReadChannel = private inline fun read(project: String, path: String, readerAction: Source.() -> T): T { val actualPath = Path("${getEnv("PROJECT_ROOT")}/$project/src/commonTest/resources/$path") - return try { - SystemFileSystem.source(actualPath).buffered().readerAction() - } catch (e: Throwable) { - throw FileNotFoundException(actualPath.toString(), e) - } + return SystemFileSystem.source(actualPath).buffered().readerAction() } - -class FileNotFoundException(absolutePath: String, cause: Throwable) : IOException("Absolute Path: $absolutePath", cause) diff --git a/voice/build.gradle.kts b/voice/build.gradle.kts index 326c5bae85d..86ba3458131 100644 --- a/voice/build.gradle.kts +++ b/voice/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - `kord-native-module` + `kord-targets` `kord-multiplatform-module` `kord-publishing` } @@ -27,5 +27,10 @@ kotlin { implementation(libs.libsodium) } } + jvmMain { + dependencies { + implementation(libs.slf4j.api) + } + } } } From 92d05e7c782ab9cc74cad5e0bc035e23e1c4dcf7 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Mon, 4 Mar 2024 22:19:04 +0100 Subject: [PATCH 45/83] Replace kotlin-targets with Targets.kt --- buildSrc/build.gradle.kts | 1 + .../kotlin/{kord-targets.gradle.kts => Targets.kt} | 12 ++++++------ .../main/kotlin/kord-multiplatform-module.gradle.kts | 1 + common/build.gradle.kts | 2 +- core-voice/build.gradle.kts | 1 - core/build.gradle.kts | 1 - core/live-tests/build.gradle.kts | 3 ++- gateway/build.gradle.kts | 1 - ksp-annotations/build.gradle.kts | 7 +++++-- rest/build.gradle.kts | 1 - samples/build.gradle.kts | 6 ++---- test-kit/build.gradle.kts | 3 ++- voice/build.gradle.kts | 1 - 13 files changed, 20 insertions(+), 20 deletions(-) rename buildSrc/src/main/kotlin/{kord-targets.gradle.kts => Targets.kt} (62%) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index d6abfed304d..41189bbfb2a 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,6 +12,7 @@ repositories { kotlin { compilerOptions { allWarningsAsErrors = true + freeCompilerArgs.add("-Xcontext-receivers") } } diff --git a/buildSrc/src/main/kotlin/kord-targets.gradle.kts b/buildSrc/src/main/kotlin/Targets.kt similarity index 62% rename from buildSrc/src/main/kotlin/kord-targets.gradle.kts rename to buildSrc/src/main/kotlin/Targets.kt index 63125e6daf7..63f7476e501 100644 --- a/buildSrc/src/main/kotlin/kord-targets.gradle.kts +++ b/buildSrc/src/main/kotlin/Targets.kt @@ -1,10 +1,10 @@ +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.kpm.external.ExternalVariantApi +import org.jetbrains.kotlin.gradle.kpm.external.project import org.jetbrains.kotlin.konan.target.HostManager -plugins { - org.jetbrains.kotlin.multiplatform -} - -kotlin { +@OptIn(ExternalVariantApi::class) +fun KotlinMultiplatformExtension.targets() { // There are issues with compiling the linux variant on windows // Please use WSL if you need to work on the linux port if (!HostManager.hostIsMingw) { @@ -14,7 +14,7 @@ kotlin { jvm() - if (name != "voice" && name != "core-voice") { + if (project.name != "voice" && project.name != "core-voice") { mingwX64() js { nodejs() diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index d34b122835e..b429ef81d04 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -36,6 +36,7 @@ kotlin { } } + targets() explicitApi() jvmToolchain(Jvm.target) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 927677dde73..d702180bf1a 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -2,13 +2,13 @@ import dev.kord.gradle.tools.util.commitHash import dev.kord.gradle.tools.util.shortCommitHash plugins { - `kord-targets` `kord-multiplatform-module` `kord-publishing` alias(libs.plugins.buildconfig) } kotlin { + targets() sourceSets { commonMain { dependencies { diff --git a/core-voice/build.gradle.kts b/core-voice/build.gradle.kts index d8efe0d18a8..e0aa14087fa 100644 --- a/core-voice/build.gradle.kts +++ b/core-voice/build.gradle.kts @@ -1,5 +1,4 @@ plugins { - `kord-targets` `kord-multiplatform-module` `kord-publishing` } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index c326190d659..9940a3e3158 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,4 @@ plugins { - `kord-targets` `kord-multiplatform-module` `kord-publishing` } diff --git a/core/live-tests/build.gradle.kts b/core/live-tests/build.gradle.kts index ea3b8e3de70..6ff2ebf0210 100644 --- a/core/live-tests/build.gradle.kts +++ b/core/live-tests/build.gradle.kts @@ -1,8 +1,9 @@ plugins { - `kord-targets` + org.jetbrains.kotlin.multiplatform } kotlin { + targets() sourceSets { all { applyKordOptIns() diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index 6e3372b6f27..39c09f00a66 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -1,5 +1,4 @@ plugins { - `kord-targets` `kord-multiplatform-module` `kord-publishing` } diff --git a/ksp-annotations/build.gradle.kts b/ksp-annotations/build.gradle.kts index 4d38af49489..470698576a3 100644 --- a/ksp-annotations/build.gradle.kts +++ b/ksp-annotations/build.gradle.kts @@ -1,13 +1,16 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask plugins { - `kord-targets` - + org.jetbrains.kotlin.multiplatform // workaround for https://youtrack.jetbrains.com/issue/KT-43500 (not intended to be published) org.jetbrains.dokka `kord-publishing` } +kotlin { + targets() +} + tasks.withType().configureEach { dokkaSourceSets.configureEach { suppress = true diff --git a/rest/build.gradle.kts b/rest/build.gradle.kts index 7db0c64b3ef..1e96bd4847c 100644 --- a/rest/build.gradle.kts +++ b/rest/build.gradle.kts @@ -1,5 +1,4 @@ plugins { - `kord-targets` `kord-multiplatform-module` `kord-publishing` } diff --git a/samples/build.gradle.kts b/samples/build.gradle.kts index 84b8ef3b862..f97f0f061b5 100644 --- a/samples/build.gradle.kts +++ b/samples/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.konan.target.Family plugins { - `kord-targets` + org.jetbrains.kotlin.multiplatform } @OptIn(ExperimentalKotlinGradlePluginApi::class) @@ -17,9 +17,7 @@ kotlin { } } } - js { - binaries.executable() - } + targets() targets.withType { // Voice does not target windows, so we disable it diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index 4c25f2582ee..caf73baae0e 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi plugins { - `kord-targets` + org.jetbrains.kotlin.multiplatform } @OptIn(ExperimentalKotlinGradlePluginApi::class) @@ -15,6 +15,7 @@ kotlin { } } } + targets() sourceSets { commonMain { dependencies { diff --git a/voice/build.gradle.kts b/voice/build.gradle.kts index 86ba3458131..94c25ca2818 100644 --- a/voice/build.gradle.kts +++ b/voice/build.gradle.kts @@ -1,5 +1,4 @@ plugins { - `kord-targets` `kord-multiplatform-module` `kord-publishing` } From 2e1f52e63dc896bb2615b0659b7f10dff7f0d4c0 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 5 Mar 2024 16:31:55 +0100 Subject: [PATCH 46/83] Apply gradle plugin everywhere --- buildSrc/src/main/kotlin/kord-internal-module.gradle.kts | 1 + buildSrc/src/main/kotlin/kord-publishing.gradle.kts | 4 ++-- gradle/libs.versions.toml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-internal-module.gradle.kts b/buildSrc/src/main/kotlin/kord-internal-module.gradle.kts index 102f730ea2e..ee062d1899c 100644 --- a/buildSrc/src/main/kotlin/kord-internal-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-internal-module.gradle.kts @@ -1,5 +1,6 @@ plugins { org.jetbrains.kotlin.jvm + dev.kord.`gradle-tools` } repositories { diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index 6836cce11ae..103cd78ec27 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -1,6 +1,6 @@ import com.vanniktech.maven.publish.JavadocJar import com.vanniktech.maven.publish.KotlinMultiplatform -import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.Family plugins { id("com.vanniktech.maven.publish.base") @@ -9,7 +9,7 @@ plugins { kord { publicationName = "mavenCentral" - metadataHost = KonanTarget.MACOS_ARM64 + metadataHost = Family.OSX } mavenPublishing { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b15b7247abb..317cff0c985 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,7 @@ dokka = "1.9.20" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.23.2" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.14.0" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "5.3.5" # https://github.com/gmazzo/gradle-buildconfig-plugin -kord-gradle-tools = "1.3.0" # https://github.com/kordlib/gradle-tools +kord-gradle-tools = "1.5.2" # https://github.com/kordlib/gradle-tools maven-publish-plugin = "0.27.0" # https://github.com/vanniktech/gradle-maven-publish-plugin [libraries] From 3dfbe1cdc1343f7de06f280e318b0fd384e58733 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 5 Mar 2024 16:47:29 +0100 Subject: [PATCH 47/83] Really apply gradle plugin everywhere --- test-kit/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index caf73baae0e..aee1524f14b 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi plugins { org.jetbrains.kotlin.multiplatform + dev.kord.`gradle-tools` } @OptIn(ExperimentalKotlinGradlePluginApi::class) From 3d90b89b24f363d6d43323aa00705f1dc957602a Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 5 Mar 2024 17:08:01 +0100 Subject: [PATCH 48/83] Update gradle-tools --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 317cff0c985..7265e95e093 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,7 @@ dokka = "1.9.20" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.23.2" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.14.0" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "5.3.5" # https://github.com/gmazzo/gradle-buildconfig-plugin -kord-gradle-tools = "1.5.2" # https://github.com/kordlib/gradle-tools +kord-gradle-tools = "1.5.3" # https://github.com/kordlib/gradle-tools maven-publish-plugin = "0.27.0" # https://github.com/vanniktech/gradle-maven-publish-plugin [libraries] From 7a1f87a906601c75343c84ee5ffd314b2c28fda7 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sun, 10 Mar 2024 16:38:52 +0100 Subject: [PATCH 49/83] Configure targets compiler options in Targets.kt --- buildSrc/src/main/kotlin/Targets.kt | 6 ++++++ .../src/main/kotlin/kord-multiplatform-module.gradle.kts | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/buildSrc/src/main/kotlin/Targets.kt b/buildSrc/src/main/kotlin/Targets.kt index 63f7476e501..0c66b927d1d 100644 --- a/buildSrc/src/main/kotlin/Targets.kt +++ b/buildSrc/src/main/kotlin/Targets.kt @@ -35,4 +35,10 @@ fun KotlinMultiplatformExtension.targets() { tvosX64() tvosArm64() tvosSimulatorArm64() + + targets.all { + compilations.all { + compilerOptions.options.applyKordCompilerOptions() + } + } } diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index b429ef81d04..aad134274ae 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -40,12 +40,6 @@ kotlin { explicitApi() jvmToolchain(Jvm.target) - targets.all { - compilations.all { - compilerOptions.options.applyKordCompilerOptions() - } - } - sourceSets { all { applyKordOptIns() From 0b3848c7c6eab666638b48c62c41c5f2e6c7d559 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Mon, 11 Mar 2024 22:12:49 +0100 Subject: [PATCH 50/83] Improve native inflater - Correctly process ZLIB_SUFFIX - Make new check function to check exit codes --- .../src/commonMain/kotlin/DefaultGateway.kt | 2 +- gateway/src/commonMain/kotlin/Inflater.kt | 7 +++- gateway/src/nativeMain/kotlin/Inflater.kt | 42 +++++++++++-------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/gateway/src/commonMain/kotlin/DefaultGateway.kt b/gateway/src/commonMain/kotlin/DefaultGateway.kt index 635fd38b905..8aa56ebca56 100644 --- a/gateway/src/commonMain/kotlin/DefaultGateway.kt +++ b/gateway/src/commonMain/kotlin/DefaultGateway.kt @@ -180,7 +180,7 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { private suspend fun read(frame: Frame) { defaultGatewayLogger.trace { "Received raw frame: $frame" } val json = when { - compression -> with(inflater) { frame.inflateData() } + compression -> with(inflater) { frame.inflateData() } ?: return else -> frame.data.decodeToString() } diff --git a/gateway/src/commonMain/kotlin/Inflater.kt b/gateway/src/commonMain/kotlin/Inflater.kt index c2a642fa5c7..384091ef88a 100644 --- a/gateway/src/commonMain/kotlin/Inflater.kt +++ b/gateway/src/commonMain/kotlin/Inflater.kt @@ -4,7 +4,12 @@ import io.ktor.utils.io.core.* import io.ktor.websocket.* internal interface Inflater : Closeable { - fun Frame.inflateData(): String + /** + * Inflates this frame. + * + * @return the inflated frame or null if the received frame was incomplete + */ + fun Frame.inflateData(): String? } internal expect fun Inflater(): Inflater diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index 3abeafcd393..dc41eabb46c 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -6,28 +6,35 @@ import platform.zlib.* private const val MAX_WBITS = 15 // Maximum window size in bits private const val CHUNK_SIZE = 256 * 1000 +private val ZLIB_SUFFIX = ubyteArrayOf(0x00u, 0x00u, 0xffu, 0xffu) internal actual fun Inflater(): Inflater = NativeInflater() @OptIn(ExperimentalForeignApi::class) private class NativeInflater : Inflater { + private var frameBuffer = UByteArray(0) + private val zStream = nativeHeap.alloc().apply { - val initResponse = inflateInit2(ptr, MAX_WBITS) - if (initResponse != Z_OK) { + inflateInit2(ptr, MAX_WBITS).check { nativeHeap.free(this) - throw ZLibException("Could not initialize zlib: ${zErrorMessage(initResponse)}") } } - override fun Frame.inflateData(): String { - val compressedData = data + override fun Frame.inflateData(): String? { + frameBuffer += data.asUByteArray() + // check if the last four bytes are equal to ZLIB_SUFFIX + if (frameBuffer.size < 4 || + !frameBuffer.copyOfRange(frameBuffer.size - 4, frameBuffer.size).contentEquals(ZLIB_SUFFIX) + ) { + return null + } var out = ByteArray(0) memScoped { val uncompressedDataSize = CHUNK_SIZE // allocate enough space for the uncompressed data val uncompressedData = allocArray(uncompressedDataSize) zStream.apply { - next_in = compressedData.refTo(0).getPointer(memScope).reinterpret() - avail_in = compressedData.size.convert() + next_in = frameBuffer.refTo(0).getPointer(memScope) + avail_in = frameBuffer.size.convert() } do { @@ -35,27 +42,28 @@ private class NativeInflater : Inflater { next_out = uncompressedData avail_out = uncompressedDataSize.convert() } - val resultCode = inflate(zStream.ptr, Z_NO_FLUSH) - if (resultCode != Z_OK && resultCode != Z_STREAM_END) { - throw ZLibException( - "An error occurred during decompression of frame: ${zErrorMessage(resultCode)}" - ) + inflate(zStream.ptr, Z_NO_FLUSH).check(listOf(Z_OK, Z_STREAM_END)) { + frameBuffer = UByteArray(0) } out += uncompressedData.readBytes(uncompressedDataSize - zStream.avail_out.convert()) } while (zStream.avail_out == 0u) } + frameBuffer = UByteArray(0) return out.decodeToString() } override fun close() { + inflateEnd(zStream.ptr).check { nativeHeap.free(zStream) } + } +} + +private fun Int.check(validCodes: List = listOf(Z_OK), cleanup: () -> Unit = {}) { + if (this !in validCodes) { try { - val response = inflateEnd(zStream.ptr) - if(response != Z_OK) { - throw ZLibException("Could not end zstream: ${zErrorMessage(response)}") - } + throw ZLibException(zErrorMessage(this).toString()) } finally { - nativeHeap.free(zStream) + cleanup() } } } From 00530794ba1c5ab23d9e24bdeecd37dffe0e1ce0 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Wed, 20 Mar 2024 21:53:56 +0100 Subject: [PATCH 51/83] Switch to OkHttp as http client on jvm --- common/build.gradle.kts | 2 +- common/src/jvmMain/kotlin/http/HttpEngine.kt | 4 ++-- gradle/libs.versions.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index d702180bf1a..17a47430f5a 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -22,7 +22,7 @@ kotlin { } jvmMain { dependencies { - api(libs.ktor.client.cio) + api(libs.ktor.client.okhttp) } } nonJvmMain { diff --git a/common/src/jvmMain/kotlin/http/HttpEngine.kt b/common/src/jvmMain/kotlin/http/HttpEngine.kt index 0d73e596c9b..baaaf35bb58 100644 --- a/common/src/jvmMain/kotlin/http/HttpEngine.kt +++ b/common/src/jvmMain/kotlin/http/HttpEngine.kt @@ -2,8 +2,8 @@ package dev.kord.common.http import dev.kord.common.annotation.KordInternal import io.ktor.client.engine.* -import io.ktor.client.engine.cio.* +import io.ktor.client.engine.okhttp.OkHttp /** @suppress */ @KordInternal -public actual fun httpEngine(): HttpClientEngineFactory = CIO +public actual fun httpEngine(): HttpClientEngineFactory = OkHttp diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7265e95e093..157af8f7bf1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,7 +48,7 @@ ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" } ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor" } ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" } ktor-client-curl = { module = "io.ktor:ktor-client-curl", version.ref = "ktor" } -ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" } +ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" } ktor-client-websockets = { module = "io.ktor:ktor-client-websockets", version.ref = "ktor" } ktor-client-mock = { module = "io.ktor:ktor-client-mock", version.ref = "ktor" } ktor-network = { module = "io.ktor:ktor-network", version.ref = "ktor" } From 450323e9075ba03a569691dbbfca524f35596bdc Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Wed, 20 Mar 2024 21:57:22 +0100 Subject: [PATCH 52/83] Revert "Switch to OkHttp as http client on jvm" This reverts commit 00530794ba1c5ab23d9e24bdeecd37dffe0e1ce0. --- common/build.gradle.kts | 2 +- common/src/jvmMain/kotlin/http/HttpEngine.kt | 4 ++-- gradle/libs.versions.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 17a47430f5a..d702180bf1a 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -22,7 +22,7 @@ kotlin { } jvmMain { dependencies { - api(libs.ktor.client.okhttp) + api(libs.ktor.client.cio) } } nonJvmMain { diff --git a/common/src/jvmMain/kotlin/http/HttpEngine.kt b/common/src/jvmMain/kotlin/http/HttpEngine.kt index baaaf35bb58..0d73e596c9b 100644 --- a/common/src/jvmMain/kotlin/http/HttpEngine.kt +++ b/common/src/jvmMain/kotlin/http/HttpEngine.kt @@ -2,8 +2,8 @@ package dev.kord.common.http import dev.kord.common.annotation.KordInternal import io.ktor.client.engine.* -import io.ktor.client.engine.okhttp.OkHttp +import io.ktor.client.engine.cio.* /** @suppress */ @KordInternal -public actual fun httpEngine(): HttpClientEngineFactory = OkHttp +public actual fun httpEngine(): HttpClientEngineFactory = CIO diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 157af8f7bf1..7265e95e093 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,7 +48,7 @@ ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" } ktor-client-winhttp = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor" } ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" } ktor-client-curl = { module = "io.ktor:ktor-client-curl", version.ref = "ktor" } -ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" } +ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" } ktor-client-websockets = { module = "io.ktor:ktor-client-websockets", version.ref = "ktor" } ktor-client-mock = { module = "io.ktor:ktor-client-mock", version.ref = "ktor" } ktor-network = { module = "io.ktor:ktor-network", version.ref = "ktor" } From 3944b8dcd1bd4e1f02fd5a08eef9cde8243834a5 Mon Sep 17 00:00:00 2001 From: lukellmann Date: Mon, 25 Mar 2024 02:42:37 +0100 Subject: [PATCH 53/83] Improve initializing and ending z_stream --- gateway/src/nativeMain/kotlin/Inflater.kt | 40 ++++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index dc41eabb46c..5734b1eed5a 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -4,7 +4,6 @@ import io.ktor.websocket.* import kotlinx.cinterop.* import platform.zlib.* -private const val MAX_WBITS = 15 // Maximum window size in bits private const val CHUNK_SIZE = 256 * 1000 private val ZLIB_SUFFIX = ubyteArrayOf(0x00u, 0x00u, 0xffu, 0xffu) @@ -12,11 +11,26 @@ internal actual fun Inflater(): Inflater = NativeInflater() @OptIn(ExperimentalForeignApi::class) private class NativeInflater : Inflater { + // see https://www.zlib.net/manual.html + private var frameBuffer = UByteArray(0) - private val zStream = nativeHeap.alloc().apply { - inflateInit2(ptr, MAX_WBITS).check { - nativeHeap.free(this) + private val zStream = nativeHeap.alloc().also { zStream -> + // next_in, avail_in, zalloc, zfree and opaque must be initialized before calling inflateInit + zStream.next_in = null + zStream.avail_in = 0u + zStream.zalloc = null + zStream.zfree = null + zStream.opaque = null + // initialize msg just in case, we use it for throwing exceptions + zStream.msg = null + val ret = inflateInit(zStream.ptr) + if (ret != Z_OK) { + try { + throwZlibException(zStream.msg, ret) + } finally { + nativeHeap.free(zStream) + } } } @@ -54,21 +68,31 @@ private class NativeInflater : Inflater { } override fun close() { - inflateEnd(zStream.ptr).check { nativeHeap.free(zStream) } + val ret = inflateEnd(zStream.ptr) + try { + if (ret != Z_OK) throwZlibException(zStream.msg, ret) + } finally { + nativeHeap.free(zStream) + } } } +@ExperimentalForeignApi private fun Int.check(validCodes: List = listOf(Z_OK), cleanup: () -> Unit = {}) { if (this !in validCodes) { try { - throw ZLibException(zErrorMessage(this).toString()) + throw ZlibException(zErrorMessage(this).toString()) } finally { cleanup() } } } -private class ZLibException(message: String?) : IllegalStateException(message) +private class ZlibException(message: String?) : IllegalStateException(message) -@OptIn(ExperimentalForeignApi::class) +@ExperimentalForeignApi private fun zErrorMessage(errorCode: Int) = zError(errorCode)?.toKString() ?: errorCode + +@ExperimentalForeignApi +private fun throwZlibException(msg: CPointer?, ret: Int): Nothing = + throw ZlibException(msg?.toKString() ?: zError(ret)?.toKString() ?: ret.toString()) From 0f4df3363eb25764a75ce807b36e4c5d9118a9be Mon Sep 17 00:00:00 2001 From: lukellmann Date: Fri, 5 Apr 2024 17:30:16 +0200 Subject: [PATCH 54/83] More inflater improvements Co-authored-by: Michael Rittmeister --- .../src/commonMain/kotlin/DefaultGateway.kt | 38 +++++---- gateway/src/commonMain/kotlin/Inflater.kt | 46 +++++++++-- gateway/src/jsMain/kotlin/Inflater.kt | 5 +- gateway/src/jvmMain/kotlin/Inflater.kt | 13 ++- gateway/src/nativeMain/kotlin/Inflater.kt | 81 ++++++------------- 5 files changed, 91 insertions(+), 92 deletions(-) diff --git a/gateway/src/commonMain/kotlin/DefaultGateway.kt b/gateway/src/commonMain/kotlin/DefaultGateway.kt index 75e89c1969d..669f456760f 100644 --- a/gateway/src/commonMain/kotlin/DefaultGateway.kt +++ b/gateway/src/commonMain/kotlin/DefaultGateway.kt @@ -168,30 +168,28 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { private suspend fun readSocket() { - socket.incoming.asFlow().buffer(Channel.UNLIMITED).collect { - when (it) { - is Frame.Binary, is Frame.Text -> read(it) - else -> { /*ignore*/ + val frames = socket.incoming.asFlow() + .buffer(Channel.UNLIMITED) + .onEach { frame -> defaultGatewayLogger.trace { "Received raw frame: $frame" } } + val eventsJson = if (compression) { + frames.decompressFrames(inflater) + } else { + frames.mapNotNull { frame -> + when (frame) { + is Frame.Binary, is Frame.Text -> frame.data.decodeToString() + else -> null // ignore other frame types } } } - } - - private suspend fun read(frame: Frame) { - defaultGatewayLogger.trace { "Received raw frame: $frame" } - val json = when { - compression -> with(inflater) { frame.inflateData() } ?: return - else -> frame.data.decodeToString() - } - - try { - defaultGatewayLogger.trace { "Gateway <<< $json" } - val event = jsonParser.decodeFromString(Event.DeserializationStrategy, json) - data.eventFlow.emit(event) - } catch (exception: Exception) { - defaultGatewayLogger.error(exception) { "" } + eventsJson.collect { json -> + try { + defaultGatewayLogger.trace { "Gateway <<< $json" } + val event = jsonParser.decodeFromString(Event.DeserializationStrategy, json) + data.eventFlow.emit(event) + } catch (exception: Exception) { + defaultGatewayLogger.error(exception) { "" } + } } - } private suspend fun handleClose() { diff --git a/gateway/src/commonMain/kotlin/Inflater.kt b/gateway/src/commonMain/kotlin/Inflater.kt index 384091ef88a..bd9257d5f73 100644 --- a/gateway/src/commonMain/kotlin/Inflater.kt +++ b/gateway/src/commonMain/kotlin/Inflater.kt @@ -2,14 +2,48 @@ package dev.kord.gateway import io.ktor.utils.io.core.* import io.ktor.websocket.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.transform internal interface Inflater : Closeable { - /** - * Inflates this frame. - * - * @return the inflated frame or null if the received frame was incomplete - */ - fun Frame.inflateData(): String? + /** Decompresses [compressedLen] bytes from [compressed] and decodes them to a [String]. */ + fun inflate(compressed: ByteArray, compressedLen: Int): String } internal expect fun Inflater(): Inflater + +// check if the last four bytes are equal to Z_SYNC_FLUSH suffix (00 00 ff ff), +// see https://discord.com/developers/docs/topics/gateway#transport-compression +private fun ByteArray.endsWithZlibSuffix(len: Int) = len >= 4 + && this[len - 4] == 0x00.toByte() + && this[len - 3] == 0x00.toByte() + && this[len - 2] == 0xff.toByte() + && this[len - 1] == 0xff.toByte() + +internal fun Flow.decompressFrames(inflater: Inflater): Flow { + var buffer = ByteArray(0) + var bufferLen = 0 + return transform { frame -> + when (frame) { + is Frame.Text, is Frame.Binary -> { + val data = frame.data + val dataLen = data.size + // skip copying into buffer if buffer is empty and data has suffix + if (bufferLen == 0 && data.endsWithZlibSuffix(dataLen)) { + emit(inflater.inflate(data, dataLen)) + } else { + if (buffer.size - bufferLen < dataLen) { + buffer = buffer.copyOf(bufferLen + dataLen) + } + data.copyInto(buffer, destinationOffset = bufferLen) + bufferLen += dataLen + if (buffer.endsWithZlibSuffix(bufferLen)) { + emit(inflater.inflate(buffer, bufferLen)) + bufferLen = 0 + } + } + } + else -> {} // ignore other frame types + } + } +} diff --git a/gateway/src/jsMain/kotlin/Inflater.kt b/gateway/src/jsMain/kotlin/Inflater.kt index 418c269d094..53d725b00f3 100644 --- a/gateway/src/jsMain/kotlin/Inflater.kt +++ b/gateway/src/jsMain/kotlin/Inflater.kt @@ -1,15 +1,14 @@ package dev.kord.gateway import dev.kord.gateway.internal.Inflate -import io.ktor.websocket.* import node.buffer.Buffer import node.buffer.BufferEncoding internal actual fun Inflater() = object : Inflater { private val inflate = Inflate() - override fun Frame.inflateData(): String { - val buffer = Buffer.from(data) + override fun inflate(compressed: ByteArray, compressedLen: Int): String { + val buffer = Buffer.from(compressed, byteOffset = 0, length = compressedLen) return inflate.process(buffer).toString(BufferEncoding.utf8) } diff --git a/gateway/src/jvmMain/kotlin/Inflater.kt b/gateway/src/jvmMain/kotlin/Inflater.kt index 348ba9ae389..ccfc286488c 100644 --- a/gateway/src/jvmMain/kotlin/Inflater.kt +++ b/gateway/src/jvmMain/kotlin/Inflater.kt @@ -1,19 +1,18 @@ package dev.kord.gateway -import io.ktor.websocket.* import java.io.ByteArrayOutputStream import java.util.zip.InflaterOutputStream internal actual fun Inflater() = object : Inflater { private val delegate = java.util.zip.Inflater() + private val buffer = ByteArrayOutputStream() - override fun Frame.inflateData(): String { - val outputStream = ByteArrayOutputStream() - InflaterOutputStream(outputStream, delegate).use { - it.write(data) + override fun inflate(compressed: ByteArray, compressedLen: Int): String { + buffer.reset() + InflaterOutputStream(buffer, delegate).use { + it.write(compressed, /* off = */ 0, /* len = */ compressedLen) } - - return outputStream.use { it.toByteArray().decodeToString() } + return buffer.toString("UTF-8") } override fun close() = delegate.end() diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index 5734b1eed5a..d61e15da5c3 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -1,19 +1,16 @@ package dev.kord.gateway -import io.ktor.websocket.* import kotlinx.cinterop.* import platform.zlib.* -private const val CHUNK_SIZE = 256 * 1000 -private val ZLIB_SUFFIX = ubyteArrayOf(0x00u, 0x00u, 0xffu, 0xffu) - -internal actual fun Inflater(): Inflater = NativeInflater() +private class ZlibException(message: String) : IllegalStateException(message) @OptIn(ExperimentalForeignApi::class) -private class NativeInflater : Inflater { - // see https://www.zlib.net/manual.html +internal actual fun Inflater(): Inflater = object : Inflater { + // see https://zlib.net/manual.html - private var frameBuffer = UByteArray(0) + private var decompressed = UByteArray(1024) // buffer only grows, is reused for every zlib inflate call + private var decompressedLen = 0 private val zStream = nativeHeap.alloc().also { zStream -> // next_in, avail_in, zalloc, zfree and opaque must be initialized before calling inflateInit @@ -34,39 +31,31 @@ private class NativeInflater : Inflater { } } - override fun Frame.inflateData(): String? { - frameBuffer += data.asUByteArray() - // check if the last four bytes are equal to ZLIB_SUFFIX - if (frameBuffer.size < 4 || - !frameBuffer.copyOfRange(frameBuffer.size - 4, frameBuffer.size).contentEquals(ZLIB_SUFFIX) - ) { - return null - } - var out = ByteArray(0) - memScoped { - val uncompressedDataSize = CHUNK_SIZE // allocate enough space for the uncompressed data - val uncompressedData = allocArray(uncompressedDataSize) - zStream.apply { - next_in = frameBuffer.refTo(0).getPointer(memScope) - avail_in = frameBuffer.size.convert() - } + private fun throwZlibException(msg: CPointer?, ret: Int): Nothing = + throw ZlibException(msg?.toKString() ?: zError(ret)?.toKString() ?: ret.toString()) - do { - zStream.apply { - next_out = uncompressedData - avail_out = uncompressedDataSize.convert() + override fun inflate(compressed: ByteArray, compressedLen: Int): String = + compressed.asUByteArray().usePinned { compressedPinned -> + zStream.next_in = compressedPinned.addressOf(0) + zStream.avail_in = compressedLen.convert() + decompressedLen = 0 + while (true) { + val ret = decompressed.usePinned { decompressedPinned -> + zStream.next_out = decompressedPinned.addressOf(decompressedLen) + zStream.avail_out = (decompressed.size - decompressedLen).convert() + inflate(zStream.ptr, Z_NO_FLUSH) } - inflate(zStream.ptr, Z_NO_FLUSH).check(listOf(Z_OK, Z_STREAM_END)) { - frameBuffer = UByteArray(0) + if (ret != Z_OK && ret != Z_STREAM_END) { + throwZlibException(zStream.msg, ret) } - out += uncompressedData.readBytes(uncompressedDataSize - zStream.avail_out.convert()) - } while (zStream.avail_out == 0u) + if (zStream.avail_in == 0u || zStream.avail_out != 0u) break + // grow decompressed buffer + decompressedLen = decompressed.size + decompressed = decompressed.copyOf(decompressed.size * 2) + } + decompressed.asByteArray().decodeToString(endIndex = decompressed.size - zStream.avail_out.convert()) } - frameBuffer = UByteArray(0) - return out.decodeToString() - } - override fun close() { val ret = inflateEnd(zStream.ptr) try { @@ -76,23 +65,3 @@ private class NativeInflater : Inflater { } } } - -@ExperimentalForeignApi -private fun Int.check(validCodes: List = listOf(Z_OK), cleanup: () -> Unit = {}) { - if (this !in validCodes) { - try { - throw ZlibException(zErrorMessage(this).toString()) - } finally { - cleanup() - } - } -} - -private class ZlibException(message: String?) : IllegalStateException(message) - -@ExperimentalForeignApi -private fun zErrorMessage(errorCode: Int) = zError(errorCode)?.toKString() ?: errorCode - -@ExperimentalForeignApi -private fun throwZlibException(msg: CPointer?, ret: Int): Nothing = - throw ZlibException(msg?.toKString() ?: zError(ret)?.toKString() ?: ret.toString()) From 9baf82f6c13d50ffb1b2cfa7264c5bb62192688c Mon Sep 17 00:00:00 2001 From: lukellmann Date: Sat, 6 Apr 2024 12:02:44 +0200 Subject: [PATCH 55/83] Fix duplicate jvm class name --- gateway/src/jvmMain/kotlin/{Inflater.kt => InflaterJvm.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename gateway/src/jvmMain/kotlin/{Inflater.kt => InflaterJvm.kt} (100%) diff --git a/gateway/src/jvmMain/kotlin/Inflater.kt b/gateway/src/jvmMain/kotlin/InflaterJvm.kt similarity index 100% rename from gateway/src/jvmMain/kotlin/Inflater.kt rename to gateway/src/jvmMain/kotlin/InflaterJvm.kt From b8021fea23f15ff308efe0ccd9821202b5eb5421 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 9 Apr 2024 20:02:21 +0200 Subject: [PATCH 56/83] Update libsodium --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8aefbd71579..7e16c1e0227 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ kotlin-node = "20.11.5-pre.706" # https://github.com/JetBrains/kotlin-wrappers bignum = "0.3.9" # https://github.com/ionspin/kotlin-multiplatform-bignum stately = "2.0.6" # https://github.com/touchlab/Stately fastZlib = "2.0.1" # https://github.com/timotejroiko/fast-zlib -sodium = "0.9.0" # https://github.com/ionspin/kotlin-multiplatform-libsodium +sodium = "0.9.1" # https://github.com/ionspin/kotlin-multiplatform-libsodium # code generation ksp = "1.9.22-1.0.17" # https://github.com/google/ksp From 35227fc346d30f4af5c5409f37c66f61ba029af8 Mon Sep 17 00:00:00 2001 From: viztea <44017640+viztea@users.noreply.github.com> Date: Fri, 12 Apr 2024 16:06:21 -0700 Subject: [PATCH 57/83] feat(voice)!: add support for node.js (#931) * chore: configure gradle for js voice * fix(samples/voice): support js * fix(voice/non-jvm): use correct nonce length * feat(voice): support js * chore(voice): api dump * chore: requested changes * fix(gradle): use correct kotlin-node version * feat(voice): configurable dispatcher * chore: api dump --- buildSrc/src/main/kotlin/Targets.kt | 20 ++--- .../kord-multiplatform-module.gradle.kts | 5 ++ .../BaseVoiceChannelBehaviorExtensions.kt | 9 ++- gradle/libs.versions.toml | 2 +- kotlin-js-store/yarn.lock | 12 +++ samples/build.gradle.kts | 6 ++ .../kotlin/dev/kord/gateway/GatewayExample.kt | 4 +- samples/src/commonMain/kotlin/runMain.kt | 3 + samples/src/jsMain/kotlin/runMain.js.kt | 7 ++ samples/src/jvmMain/kotlin/runMain.jvm.kt | 8 ++ .../src/nativeMain/kotlin/runMain.native.kt | 6 ++ samples/src/voiceMain/kotlin/VoiceBot.kt | 10 ++- voice/api/voice.api | 39 +++++----- voice/build.gradle.kts | 36 +++++---- .../src/commonMain/kotlin/VoiceConnection.kt | 4 +- .../kotlin/VoiceConnectionBuilder.kt | 22 +++++- .../kotlin/handlers/StreamsHandler.kt | 4 +- .../kotlin/handlers/UdpLifeCycleHandler.kt | 19 ++--- .../kotlin/streams/DefaultStreams.kt | 7 +- .../commonMain/kotlin/streams/NOPStreams.kt | 2 +- .../src/commonMain/kotlin/streams/Streams.kt | 2 +- .../commonMain/kotlin/udp/AudioFrameSender.kt | 1 - .../kotlin/udp/DefaultAudioFrameSender.kt | 4 +- .../kotlin/udp/GlobalVoiceUdpSocket.kt | 77 ------------------- .../commonMain/kotlin/udp/VoiceUdpSocket.kt | 40 +++++----- .../src/commonMain/kotlin/udp/ipDiscovery.kt | 41 ++++++++++ .../jsMain/kotlin/udp/VoiceUdpSocket.js.kt | 66 ++++++++++++++++ .../kotlin/udp/VoiceUdpSocket.nonJs.kt | 46 +++++++++++ .../dev/kord/voice/streams/DefaultStreams.kt | 1 + .../voice/udp/DefaultAudioPacketProvider.kt | 4 +- 30 files changed, 330 insertions(+), 177 deletions(-) create mode 100644 samples/src/commonMain/kotlin/runMain.kt create mode 100644 samples/src/jsMain/kotlin/runMain.js.kt create mode 100644 samples/src/jvmMain/kotlin/runMain.jvm.kt create mode 100644 samples/src/nativeMain/kotlin/runMain.native.kt delete mode 100644 voice/src/commonMain/kotlin/udp/GlobalVoiceUdpSocket.kt create mode 100644 voice/src/commonMain/kotlin/udp/ipDiscovery.kt create mode 100644 voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt create mode 100644 voice/src/nonJsMain/kotlin/udp/VoiceUdpSocket.nonJs.kt diff --git a/buildSrc/src/main/kotlin/Targets.kt b/buildSrc/src/main/kotlin/Targets.kt index 83beb5b109d..d1712a8d0ea 100644 --- a/buildSrc/src/main/kotlin/Targets.kt +++ b/buildSrc/src/main/kotlin/Targets.kt @@ -15,19 +15,21 @@ fun KotlinMultiplatformExtension.targets() { jvm() if (project.name != "voice" && project.name != "core-voice") { + // https://youtrack.jetbrains.com/issue/KTOR-4080 mingwX64() - js { - nodejs { - testTask { - useMocha { - // disable timeouts, some tests are too slow for default 2-second timeout: - // https://mochajs.org/#-timeout-ms-t-ms - timeout = "0" - } + } + + js { + nodejs { + testTask { + useMocha { + // disable timeouts, some tests are too slow for default 2-second timeout: + // https://mochajs.org/#-timeout-ms-t-ms + timeout = "0" } } - useCommonJs() } + useCommonJs() } macosArm64() diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index aad134274ae..9a03abb9b6a 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -33,6 +33,11 @@ kotlin { withNative() withJs() } + + group("nonJs") { + withNative() + withJvm() + } } } diff --git a/core-voice/src/commonMain/kotlin/BaseVoiceChannelBehaviorExtensions.kt b/core-voice/src/commonMain/kotlin/BaseVoiceChannelBehaviorExtensions.kt index 35e8025a8ba..77e02a166bb 100644 --- a/core-voice/src/commonMain/kotlin/BaseVoiceChannelBehaviorExtensions.kt +++ b/core-voice/src/commonMain/kotlin/BaseVoiceChannelBehaviorExtensions.kt @@ -7,6 +7,9 @@ import dev.kord.core.entity.channel.VoiceChannel import dev.kord.core.exception.GatewayNotFoundException import dev.kord.voice.VoiceConnection import dev.kord.voice.VoiceConnectionBuilder +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.job +import kotlinx.coroutines.plus import kotlin.jvm.JvmName /** @@ -24,8 +27,10 @@ public suspend fun BaseVoiceChannelBehavior.connect(builder: VoiceConnectionBuil kord.selfId, id, guildId, - builder - ) + ) { + scope { guild.kord + SupervisorJob(guild.kord.coroutineContext.job) } + builder() + } voiceConnection.connect() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7e16c1e0227..1b7f72c9dd5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ kord-cache = "0.5.0-20240130.022209-2" # https://github.com/kordlib/cache # implementation dependencies kotlin-logging = "6.0.3" # https://github.com/oshai/kotlin-logging slf4j = "2.0.12" # https://www.slf4j.org -kotlin-node = "20.11.5-pre.706" # https://github.com/JetBrains/kotlin-wrappers +kotlin-node = "20.11.30-pre.723" # https://github.com/JetBrains/kotlin-wrappers bignum = "0.3.9" # https://github.com/ionspin/kotlin-multiplatform-bignum stately = "2.0.6" # https://github.com/touchlab/Stately fastZlib = "2.0.1" # https://github.com/timotejroiko/fast-zlib diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 28defc34c42..0c517888742 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -310,6 +310,18 @@ js-yaml@4.1.0: dependencies: argparse "^2.0.1" +libsodium-sumo@^0.7.13: + version "0.7.13" + resolved "https://registry.yarnpkg.com/libsodium-sumo/-/libsodium-sumo-0.7.13.tgz#533b97d2be44b1277e59c1f9f60805978ac5542d" + integrity sha512-zTGdLu4b9zSNLfovImpBCbdAA4xkpkZbMnSQjP8HShyOutnGjRHmSOKlsylh1okao6QhLiz7nG98EGn+04cZjQ== + +libsodium-wrappers-sumo@0.7.13: + version "0.7.13" + resolved "https://registry.yarnpkg.com/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.13.tgz#a33aea845a0bb56db067548f04feba28c730ab8e" + integrity sha512-lz4YdplzDRh6AhnLGF2Dj2IUj94xRN6Bh8T0HLNwzYGwPehQJX6c7iYVrFUPZ3QqxE0bqC+K0IIqqZJYWumwSQ== + dependencies: + libsodium-sumo "^0.7.13" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" diff --git a/samples/build.gradle.kts b/samples/build.gradle.kts index f97f0f061b5..fd53f4585a6 100644 --- a/samples/build.gradle.kts +++ b/samples/build.gradle.kts @@ -14,11 +14,17 @@ kotlin { withLinux() withMacos() withJvm() + withJs() } } } + targets() + js { + binaries.executable() + } + targets.withType { // Voice does not target windows, so we disable it if (konanTarget.family != Family.MINGW) { diff --git a/samples/src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt b/samples/src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt index 60d729f9011..02e1fb0a4c3 100644 --- a/samples/src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt +++ b/samples/src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt @@ -19,7 +19,7 @@ suspend fun main(args: Array) { gateway.events.filterIsInstance().onEach { val words = it.message.content.split(' ') when (words.firstOrNull()) { - "!close" -> gateway.stop() + "!close" -> gateway.stop() "!detach" -> gateway.detach() "!status" -> when (words.getOrNull(1)) { "playing" -> gateway.editPresence { @@ -29,7 +29,7 @@ suspend fun main(args: Array) { } } - "!ping" -> gateway.editPresence { + "!ping" -> gateway.editPresence { status = PresenceStatus.Online afk = false listening("a ${gateway.ping.value?.inWholeMilliseconds} ms ping") diff --git a/samples/src/commonMain/kotlin/runMain.kt b/samples/src/commonMain/kotlin/runMain.kt new file mode 100644 index 00000000000..6d358d86576 --- /dev/null +++ b/samples/src/commonMain/kotlin/runMain.kt @@ -0,0 +1,3 @@ +import kotlinx.coroutines.CoroutineScope + +expect fun runMain(block: suspend CoroutineScope.() -> Unit) diff --git a/samples/src/jsMain/kotlin/runMain.js.kt b/samples/src/jsMain/kotlin/runMain.js.kt new file mode 100644 index 00000000000..1a8d9a7a28c --- /dev/null +++ b/samples/src/jsMain/kotlin/runMain.js.kt @@ -0,0 +1,7 @@ +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch + +actual fun runMain(block: suspend CoroutineScope.() -> Unit) { + GlobalScope.launch { block() } +} \ No newline at end of file diff --git a/samples/src/jvmMain/kotlin/runMain.jvm.kt b/samples/src/jvmMain/kotlin/runMain.jvm.kt new file mode 100644 index 00000000000..1166532b1e4 --- /dev/null +++ b/samples/src/jvmMain/kotlin/runMain.jvm.kt @@ -0,0 +1,8 @@ +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking + +actual fun runMain(block: suspend CoroutineScope.() -> Unit) { + runBlocking { block() } +} \ No newline at end of file diff --git a/samples/src/nativeMain/kotlin/runMain.native.kt b/samples/src/nativeMain/kotlin/runMain.native.kt new file mode 100644 index 00000000000..ca2234a0986 --- /dev/null +++ b/samples/src/nativeMain/kotlin/runMain.native.kt @@ -0,0 +1,6 @@ +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.runBlocking + +actual fun runMain(block: suspend CoroutineScope.() -> Unit) { + runBlocking { block() } +} \ No newline at end of file diff --git a/samples/src/voiceMain/kotlin/VoiceBot.kt b/samples/src/voiceMain/kotlin/VoiceBot.kt index c34224b35ef..a933224986a 100644 --- a/samples/src/voiceMain/kotlin/VoiceBot.kt +++ b/samples/src/voiceMain/kotlin/VoiceBot.kt @@ -11,10 +11,11 @@ import dev.kord.core.event.interaction.GuildChatInputCommandInteractionCreateEve import dev.kord.core.on import dev.kord.voice.AudioFrame import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking +import runMain -fun main(args: Array) = runBlocking { - val kord = Kord(args.firstOrNull() ?: error("Missing token")) +fun main(args: Array) = runMain { + val kord = + Kord(args.firstOrNull() ?: error("Missing token")) kord.createGlobalApplicationCommands { input("join", "Test command") { @@ -35,12 +36,13 @@ fun main(args: Array) = runBlocking { kord.login() } +@OptIn(KordVoice::class) private suspend fun BaseVoiceChannelBehavior.connectEcho() { val buffer = mutableListOf(AudioFrame.SILENCE, AudioFrame.SILENCE, AudioFrame.SILENCE, AudioFrame.SILENCE) val connection = connect { receiveVoice = true audioProvider { - buffer.removeLastOrNull() ?: AudioFrame.SILENCE + buffer.removeFirstOrNull() ?: AudioFrame.SILENCE } } connection.scope.launch { diff --git a/voice/api/voice.api b/voice/api/voice.api index 9319dc65c41..d261de8b3fe 100644 --- a/voice/api/voice.api +++ b/voice/api/voice.api @@ -317,7 +317,7 @@ public final class dev/kord/voice/SpeakingFlags$Companion { } public final class dev/kord/voice/VoiceConnection { - public synthetic fun (Ldev/kord/voice/VoiceConnectionData;Ldev/kord/gateway/Gateway;Ldev/kord/voice/gateway/VoiceGateway;Ldev/kord/voice/udp/VoiceUdpSocket;Ldev/kord/voice/gateway/VoiceGatewayConfiguration;Ldev/kord/voice/streams/Streams;Ldev/kord/voice/AudioProvider;Ldev/kord/voice/FrameInterceptor;Ldev/kord/voice/udp/AudioFrameSender;Ldev/kord/voice/encryption/strategies/NonceStrategy;JLkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Lkotlinx/coroutines/CoroutineScope;Ldev/kord/voice/VoiceConnectionData;Ldev/kord/gateway/Gateway;Ldev/kord/voice/gateway/VoiceGateway;Ldev/kord/voice/udp/VoiceUdpSocket;Ldev/kord/voice/gateway/VoiceGatewayConfiguration;Ldev/kord/voice/streams/Streams;Ldev/kord/voice/AudioProvider;Ldev/kord/voice/FrameInterceptor;Ldev/kord/voice/udp/AudioFrameSender;Ldev/kord/voice/encryption/strategies/NonceStrategy;JLkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun connect (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun connect$default (Ldev/kord/voice/VoiceConnection;Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public final fun disconnect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -348,6 +348,7 @@ public final class dev/kord/voice/VoiceConnectionBuilder { public final fun getAudioSender ()Ldev/kord/voice/udp/AudioFrameSender; public final fun getChannelId ()Ldev/kord/common/entity/Snowflake; public final fun getConnectionDetachDuration-UwyO8pc ()J + public final fun getDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher; public final fun getFrameInterceptor ()Ldev/kord/voice/FrameInterceptor; public final fun getGateway ()Ldev/kord/gateway/Gateway; public final fun getGuildId ()Ldev/kord/common/entity/Snowflake; @@ -363,6 +364,7 @@ public final class dev/kord/voice/VoiceConnectionBuilder { public final fun setAudioSender (Ldev/kord/voice/udp/AudioFrameSender;)V public final fun setChannelId (Ldev/kord/common/entity/Snowflake;)V public final fun setConnectionDetachDuration-LRDsOJo (J)V + public final fun setDispatcher (Lkotlinx/coroutines/CoroutineDispatcher;)V public final fun setFrameInterceptor (Ldev/kord/voice/FrameInterceptor;)V public final fun setGateway (Ldev/kord/gateway/Gateway;)V public final fun setGuildId (Ldev/kord/common/entity/Snowflake;)V @@ -1068,7 +1070,7 @@ public final class dev/kord/voice/streams/DefaultStreams : dev/kord/voice/stream public synthetic fun getIncomingUserStreams ()Lkotlinx/coroutines/flow/Flow; public fun getIncomingUserStreams ()Lkotlinx/coroutines/flow/SharedFlow; public fun getSsrcToUser ()Ljava/util/Map; - public fun listen ([BLio/ktor/network/sockets/SocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun listen ([BLio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class dev/kord/voice/streams/NOPStreams : dev/kord/voice/streams/Streams { @@ -1077,7 +1079,7 @@ public final class dev/kord/voice/streams/NOPStreams : dev/kord/voice/streams/St public fun getIncomingAudioPackets ()Lkotlinx/coroutines/flow/Flow; public fun getIncomingUserStreams ()Lkotlinx/coroutines/flow/Flow; public fun getSsrcToUser ()Ljava/util/Map; - public fun listen ([BLio/ktor/network/sockets/SocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun listen ([BLio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public abstract interface class dev/kord/voice/streams/Streams { @@ -1085,7 +1087,7 @@ public abstract interface class dev/kord/voice/streams/Streams { public abstract fun getIncomingAudioPackets ()Lkotlinx/coroutines/flow/Flow; public abstract fun getIncomingUserStreams ()Lkotlinx/coroutines/flow/Flow; public abstract fun getSsrcToUser ()Ljava/util/Map; - public abstract fun listen ([BLio/ktor/network/sockets/SocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun listen ([BLio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public abstract interface class dev/kord/voice/udp/AudioFrameSender { @@ -1093,17 +1095,17 @@ public abstract interface class dev/kord/voice/udp/AudioFrameSender { } public final class dev/kord/voice/udp/AudioFrameSenderConfiguration { - public synthetic fun (Lio/ktor/network/sockets/SocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Lio/ktor/network/sockets/SocketAddress; + public synthetic fun (Lio/ktor/network/sockets/InetSocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lio/ktor/network/sockets/InetSocketAddress; public final fun component2-pVg5ArA ()I public final fun component3 ()[B public final fun component4 ()Ldev/kord/voice/FrameInterceptorConfiguration; - public final fun copy-Yuhug_o (Lio/ktor/network/sockets/SocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;)Ldev/kord/voice/udp/AudioFrameSenderConfiguration; - public static synthetic fun copy-Yuhug_o$default (Ldev/kord/voice/udp/AudioFrameSenderConfiguration;Lio/ktor/network/sockets/SocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;ILjava/lang/Object;)Ldev/kord/voice/udp/AudioFrameSenderConfiguration; + public final fun copy-Yuhug_o (Lio/ktor/network/sockets/InetSocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;)Ldev/kord/voice/udp/AudioFrameSenderConfiguration; + public static synthetic fun copy-Yuhug_o$default (Ldev/kord/voice/udp/AudioFrameSenderConfiguration;Lio/ktor/network/sockets/InetSocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;ILjava/lang/Object;)Ldev/kord/voice/udp/AudioFrameSenderConfiguration; public fun equals (Ljava/lang/Object;)Z public final fun getInterceptorConfiguration ()Ldev/kord/voice/FrameInterceptorConfiguration; public final fun getKey ()[B - public final fun getServer ()Lio/ktor/network/sockets/SocketAddress; + public final fun getServer ()Lio/ktor/network/sockets/InetSocketAddress; public final fun getSsrc-pVg5ArA ()I public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -1148,12 +1150,8 @@ public final class dev/kord/voice/udp/DefaultJvmAudioPacketProvider : dev/kord/v public fun provide-jfaDVJw (SII[B)Ldev/kord/voice/io/ByteArrayView; } -public final class dev/kord/voice/udp/GlobalVoiceUdpSocket : dev/kord/voice/udp/VoiceUdpSocket { - public static final field INSTANCE Ldev/kord/voice/udp/GlobalVoiceUdpSocket; - public fun discoverIp (Lio/ktor/network/sockets/InetSocketAddress;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun getIncoming ()Lkotlinx/coroutines/flow/SharedFlow; - public fun send (Lio/ktor/network/sockets/Datagram;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun stop (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +public final class dev/kord/voice/udp/IpDiscoveryKt { + public static final fun discoverIP (Ldev/kord/voice/udp/VoiceUdpSocket;Lio/ktor/network/sockets/InetSocketAddress;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; } public abstract class dev/kord/voice/udp/PayloadType { @@ -1246,9 +1244,8 @@ public final class dev/kord/voice/udp/RTPPacketKt { public abstract interface class dev/kord/voice/udp/VoiceUdpSocket { public static final field Companion Ldev/kord/voice/udp/VoiceUdpSocket$Companion; - public abstract fun discoverIp (Lio/ktor/network/sockets/InetSocketAddress;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun getIncoming ()Lkotlinx/coroutines/flow/SharedFlow; - public abstract fun send (Lio/ktor/network/sockets/Datagram;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun all (Lio/ktor/network/sockets/InetSocketAddress;)Lkotlinx/coroutines/flow/Flow; + public abstract fun send (Lio/ktor/network/sockets/InetSocketAddress;Ldev/kord/voice/io/ByteArrayView;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun stop (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } @@ -1257,6 +1254,10 @@ public final class dev/kord/voice/udp/VoiceUdpSocket$Companion { } public final class dev/kord/voice/udp/VoiceUdpSocketKt { - public static final fun receiveFrom (Ldev/kord/voice/udp/VoiceUdpSocket;Lio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun recv (Ldev/kord/voice/udp/VoiceUdpSocket;Lio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class dev/kord/voice/udp/VoiceUdpSocket_nonJsKt { + public static final fun getGlobalVoiceUdpSocket ()Ldev/kord/voice/udp/VoiceUdpSocket; } diff --git a/voice/build.gradle.kts b/voice/build.gradle.kts index 94c25ca2818..fb30ec969ab 100644 --- a/voice/build.gradle.kts +++ b/voice/build.gradle.kts @@ -5,31 +5,33 @@ plugins { kotlin { jvm { - withJava() + withJava() } sourceSets { - commonMain { - dependencies { - api(projects.common) - api(projects.gateway) + commonMain.dependencies { + api(projects.common) + api(projects.gateway) - api(libs.ktor.network) - implementation(libs.kotlin.logging) + implementation(libs.kotlin.logging) - compileOnly(projects.kspAnnotations) - } + compileOnly(projects.kspAnnotations) } - nonJvmMain { - dependencies { - implementation(libs.libsodium) - } + nonJsMain.dependencies { + api(libs.ktor.network) } - jvmMain { - dependencies { - implementation(libs.slf4j.api) - } + + jsMain.dependencies { + implementation(libs.kotlin.node) + } + + nonJvmMain.dependencies { + implementation(libs.libsodium) + } + + jvmMain.dependencies { + implementation(libs.slf4j.api) } } } diff --git a/voice/src/commonMain/kotlin/VoiceConnection.kt b/voice/src/commonMain/kotlin/VoiceConnection.kt index c034484c90b..b62969cc263 100644 --- a/voice/src/commonMain/kotlin/VoiceConnection.kt +++ b/voice/src/commonMain/kotlin/VoiceConnection.kt @@ -45,6 +45,7 @@ public data class VoiceConnectionData( */ @KordVoice public class VoiceConnection( + public val scope: CoroutineScope, public val data: VoiceConnectionData, public val gateway: Gateway, public val voiceGateway: VoiceGateway, @@ -57,9 +58,6 @@ public class VoiceConnection( public val nonceStrategy: NonceStrategy, connectionDetachDuration: Duration ) { - public val scope: CoroutineScope = - CoroutineScope(SupervisorJob() + CoroutineName("kord-voice-connection[${data.guildId.value}]")) - init { with(scope) { launch { VoiceUpdateEventHandler(gateway.events, connectionDetachDuration, this@VoiceConnection).start() } diff --git a/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt b/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt index 62765a73701..f9aa30990d7 100644 --- a/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt +++ b/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt @@ -1,6 +1,7 @@ package dev.kord.voice import dev.kord.common.KordConfiguration +import dev.kord.common.annotation.KordInternal import dev.kord.common.annotation.KordVoice import dev.kord.common.entity.Snowflake import dev.kord.gateway.Gateway @@ -17,12 +18,10 @@ import dev.kord.voice.streams.DefaultStreams import dev.kord.voice.streams.NOPStreams import dev.kord.voice.streams.Streams import dev.kord.voice.udp.* -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.* import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first -import kotlinx.coroutines.withTimeoutOrNull import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -38,6 +37,22 @@ public class VoiceConnectionBuilder( */ public var timeout: Long = 5000 + /** + * + */ + public var dispatcher: CoroutineDispatcher = Dispatchers.Default + + /** + * The [CoroutineScope] to use. By default, the scope will be created using the given [dispatcher] when [build] is called. + */ + @KordInternal + public var scopeFactory: () -> CoroutineScope = { CoroutineScope(dispatcher + SupervisorJob()) } + + @KordInternal + public fun scope(factory: () -> CoroutineScope) { + this.scopeFactory = factory + } + /** * The [AudioProvider] for this [VoiceConnection]. No audio will be provided when one is not set. */ @@ -181,6 +196,7 @@ public class VoiceConnectionBuilder( streams ?: if (receiveVoice) DefaultStreams(voiceGateway, udpSocket, nonceStrategy) else NOPStreams return VoiceConnection( + scopeFactory() + CoroutineName("kord-voice-connection[${guildId.value}]"), voiceConnectionData, gateway, voiceGateway, diff --git a/voice/src/commonMain/kotlin/handlers/StreamsHandler.kt b/voice/src/commonMain/kotlin/handlers/StreamsHandler.kt index 61efad03e5f..319e2c50beb 100644 --- a/voice/src/commonMain/kotlin/handlers/StreamsHandler.kt +++ b/voice/src/commonMain/kotlin/handlers/StreamsHandler.kt @@ -6,7 +6,7 @@ import dev.kord.voice.gateway.SessionDescription import dev.kord.voice.gateway.VoiceEvent import dev.kord.voice.gateway.handler.GatewayEventHandler import dev.kord.voice.streams.Streams -import io.ktor.network.sockets.* +import dev.kord.voice.udp.SocketAddress import kotlinx.atomicfu.AtomicRef import kotlinx.atomicfu.atomic import kotlinx.coroutines.Job @@ -25,7 +25,7 @@ internal class StreamsHandler( @OptIn(ExperimentalUnsignedTypes::class) override suspend fun start() = coroutineScope { on { - server.value = InetSocketAddress(it.ip, it.port) + server.value = SocketAddress(it.ip, it.port) } on { diff --git a/voice/src/commonMain/kotlin/handlers/UdpLifeCycleHandler.kt b/voice/src/commonMain/kotlin/handlers/UdpLifeCycleHandler.kt index 7d9004417a6..fc37e221618 100644 --- a/voice/src/commonMain/kotlin/handlers/UdpLifeCycleHandler.kt +++ b/voice/src/commonMain/kotlin/handlers/UdpLifeCycleHandler.kt @@ -8,8 +8,9 @@ import dev.kord.voice.encryption.strategies.NormalNonceStrategy import dev.kord.voice.encryption.strategies.SuffixNonceStrategy import dev.kord.voice.gateway.* import dev.kord.voice.udp.AudioFrameSenderConfiguration +import dev.kord.voice.udp.SocketAddress +import dev.kord.voice.udp.discoverIP import io.github.oshai.kotlinlogging.KotlinLogging -import io.ktor.network.sockets.* import kotlinx.atomicfu.atomic import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope @@ -22,18 +23,18 @@ internal class UdpLifeCycleHandler( flow: Flow, private val connection: VoiceConnection ) : ConnectionEventHandler(flow, "UdpInterceptor") { - private var ssrc: UInt? by atomic(null) - private var server: InetSocketAddress? by atomic(null) + private val ssrc = atomic(null) + private val server = atomic(null) private var audioSenderJob: Job? by atomic(null) @OptIn(ExperimentalUnsignedTypes::class) override suspend fun start() = coroutineScope { on { - ssrc = it.ssrc - server = InetSocketAddress(it.ip, it.port) + ssrc.value = it.ssrc + server.value = SocketAddress(it.ip, it.port) - val ip: InetSocketAddress = connection.socket.discoverIp(server!!, ssrc!!.toInt()) + val ip: SocketAddress = connection.socket.discoverIP(server.value!!, ssrc.value!!.toInt()) udpLifeCycleLogger.trace { "ip discovered for voice successfully" } @@ -58,10 +59,10 @@ internal class UdpLifeCycleHandler( on { with(connection) { val config = AudioFrameSenderConfiguration( - ssrc = ssrc!!, + ssrc = ssrc.value!!, key = it.secretKey.toUByteArray().toByteArray(), - server = server!!, - interceptorConfiguration = FrameInterceptorConfiguration(gateway, voiceGateway, ssrc!!) + server = server.value!!, + interceptorConfiguration = FrameInterceptorConfiguration(gateway, voiceGateway, ssrc.value!!) ) audioSenderJob?.cancel() diff --git a/voice/src/commonMain/kotlin/streams/DefaultStreams.kt b/voice/src/commonMain/kotlin/streams/DefaultStreams.kt index 41998813de3..da72c18f7ea 100644 --- a/voice/src/commonMain/kotlin/streams/DefaultStreams.kt +++ b/voice/src/commonMain/kotlin/streams/DefaultStreams.kt @@ -8,11 +8,11 @@ import dev.kord.voice.gateway.Speaking import dev.kord.voice.gateway.VoiceGateway import dev.kord.voice.io.ByteArrayView import dev.kord.voice.io.readableCursor +import dev.kord.voice.udp.SocketAddress import dev.kord.voice.udp.PayloadType import dev.kord.voice.udp.RTPPacket import dev.kord.voice.udp.VoiceUdpSocket import io.github.oshai.kotlinlogging.KotlinLogging -import io.ktor.network.sockets.* import kotlinx.atomicfu.AtomicRef import kotlinx.atomicfu.atomic import kotlinx.atomicfu.update @@ -30,9 +30,8 @@ public class DefaultStreams( private val nonceStrategy: NonceStrategy ) : Streams { private fun CoroutineScope.listenForIncoming(key: ByteArray, server: SocketAddress) { - udp.incoming - .filter { it.address == server } - .mapNotNull { RTPPacket.fromPacket(it.packet) } + udp.all(server) + .mapNotNull { RTPPacket.fromPacket(it) } .filter { it.payloadType == PayloadType.Audio.raw } .decrypt(nonceStrategy, key) .clean() diff --git a/voice/src/commonMain/kotlin/streams/NOPStreams.kt b/voice/src/commonMain/kotlin/streams/NOPStreams.kt index 3b914f6095a..d2f2db1a942 100644 --- a/voice/src/commonMain/kotlin/streams/NOPStreams.kt +++ b/voice/src/commonMain/kotlin/streams/NOPStreams.kt @@ -3,8 +3,8 @@ package dev.kord.voice.streams import dev.kord.common.annotation.KordVoice import dev.kord.common.entity.Snowflake import dev.kord.voice.AudioFrame +import dev.kord.voice.udp.SocketAddress import dev.kord.voice.udp.RTPPacket -import io.ktor.network.sockets.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow diff --git a/voice/src/commonMain/kotlin/streams/Streams.kt b/voice/src/commonMain/kotlin/streams/Streams.kt index 12ac383f11a..e7e917caa9f 100644 --- a/voice/src/commonMain/kotlin/streams/Streams.kt +++ b/voice/src/commonMain/kotlin/streams/Streams.kt @@ -4,7 +4,7 @@ import dev.kord.common.annotation.KordVoice import dev.kord.common.entity.Snowflake import dev.kord.voice.AudioFrame import dev.kord.voice.udp.RTPPacket -import io.ktor.network.sockets.* +import dev.kord.voice.udp.SocketAddress import kotlinx.coroutines.flow.Flow /** diff --git a/voice/src/commonMain/kotlin/udp/AudioFrameSender.kt b/voice/src/commonMain/kotlin/udp/AudioFrameSender.kt index ebb5e79be68..53e924e0ca1 100644 --- a/voice/src/commonMain/kotlin/udp/AudioFrameSender.kt +++ b/voice/src/commonMain/kotlin/udp/AudioFrameSender.kt @@ -4,7 +4,6 @@ package dev.kord.voice.udp import dev.kord.common.annotation.KordVoice import dev.kord.voice.FrameInterceptorConfiguration -import io.ktor.network.sockets.* @KordVoice public data class AudioFrameSenderConfiguration( diff --git a/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt b/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt index 3edeb832c77..c1d835eac5a 100644 --- a/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt +++ b/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt @@ -6,7 +6,6 @@ import dev.kord.voice.AudioProvider import dev.kord.voice.FrameInterceptor import dev.kord.voice.encryption.strategies.NonceStrategy import io.github.oshai.kotlinlogging.KotlinLogging -import io.ktor.network.sockets.* import io.ktor.utils.io.core.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.coroutineScope @@ -44,8 +43,7 @@ public class DefaultAudioFrameSender( .intercept(configuration.interceptorConfiguration) .filterNotNull() .map { packetProvider.provide(sequence, sequence * 960u, configuration.ssrc, it.data) } - .map { Datagram(ByteReadPacket(it.data, it.dataStart, it.viewSize), configuration.server) } - .onEach(data.udp::send) + .map { data.udp.send(configuration.server, it) } .onEach { sequence++ } .collect() } diff --git a/voice/src/commonMain/kotlin/udp/GlobalVoiceUdpSocket.kt b/voice/src/commonMain/kotlin/udp/GlobalVoiceUdpSocket.kt deleted file mode 100644 index f81f5c64b12..00000000000 --- a/voice/src/commonMain/kotlin/udp/GlobalVoiceUdpSocket.kt +++ /dev/null @@ -1,77 +0,0 @@ -package dev.kord.voice.udp - -import dev.kord.common.annotation.KordVoice -import io.github.oshai.kotlinlogging.KotlinLogging -import io.ktor.network.selector.* -import io.ktor.network.sockets.* -import io.ktor.utils.io.core.* -import kotlinx.coroutines.CoroutineName -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.flow.* - -private val globalVoiceSocketLogger = KotlinLogging.logger { } - -private const val MESSAGE_LENGTH: Short = 70 -private const val DISCOVERY_DATA_SIZE: Int = 66 - -private const val REQUEST: Short = 0x01 -private const val RESPONSE: Short = 0x02 - -/** - * A global [VoiceUdpSocket] for all [dev.kord.voice.VoiceConnection]s, unless specified otherwise. - * Initiated once and kept open for the lifetime of this process. - */ -@KordVoice -public object GlobalVoiceUdpSocket : VoiceUdpSocket { - private val socketScope = - CoroutineScope(Dispatchers.Default + SupervisorJob() + CoroutineName("kord-voice-global-socket")) - - private val _incoming: MutableSharedFlow = MutableSharedFlow() - override val incoming: SharedFlow = _incoming - - private val socket = aSocket(SelectorManager(socketScope.coroutineContext)).udp().bind() - - private val EMPTY_DATA = ByteArray(DISCOVERY_DATA_SIZE) - - init { - socket.incoming - .consumeAsFlow() - .onEach { _incoming.emit(it) } - .launchIn(socketScope) - } - - @OptIn(ExperimentalUnsignedTypes::class) - override suspend fun discoverIp(address: InetSocketAddress, ssrc: Int): InetSocketAddress { - globalVoiceSocketLogger.trace { "discovering ip" } - - send(packet(address) { - writeShort(REQUEST) - writeShort(MESSAGE_LENGTH) - writeInt(ssrc) - writeFully(EMPTY_DATA) - }) - - return with(receiveFrom(address).packet) { - require(readShort() == RESPONSE) { "did not receive a response." } - require(readShort() == MESSAGE_LENGTH) { "expected $MESSAGE_LENGTH bytes of data."} - discardExact(4) // ssrc - - val ip = String(readBytes(64)).trimEnd(0.toChar()) - val port = readUShort().toInt() - - InetSocketAddress(ip, port) - } - } - - override suspend fun send(packet: Datagram) { - socket.send(packet) - } - - override suspend fun stop() { /* this doesn't stop until the end of the process */ } - - private fun packet(address: SocketAddress, builder: BytePacketBuilder.() -> Unit): Datagram { - return Datagram(buildPacket(block = builder), address) - } -} diff --git a/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt b/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt index 609e5941aa9..af13af28f32 100644 --- a/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt +++ b/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt @@ -1,31 +1,37 @@ package dev.kord.voice.udp import dev.kord.common.annotation.KordVoice -import io.ktor.network.sockets.* -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.first +import dev.kord.voice.io.ByteArrayView +import io.ktor.utils.io.core.* +import kotlinx.coroutines.flow.* @KordVoice -public interface VoiceUdpSocket { - public val incoming: SharedFlow +public expect class SocketAddress(hostname: String, port: Int) { + public val hostname: String - public suspend fun discoverIp(address: InetSocketAddress, ssrc: Int): InetSocketAddress + public val port: Int +} - public suspend fun send(packet: Datagram) +/** + * A global [VoiceUdpSocket] for all [dev.kord.voice.VoiceConnection]s, unless specified otherwise. + * Initiated once and kept open for the lifetime of this process. + */ +@KordVoice +public expect val GlobalVoiceUdpSocket: VoiceUdpSocket + +@KordVoice +public interface VoiceUdpSocket { + public fun all(address: SocketAddress): Flow + + public suspend fun send(address: SocketAddress, packet: ByteArrayView): Unit public suspend fun stop() public companion object { private object None : VoiceUdpSocket { - override val incoming: SharedFlow = MutableSharedFlow() + override fun all(address: SocketAddress): Flow = emptyFlow() - override suspend fun discoverIp(address: InetSocketAddress, ssrc: Int): InetSocketAddress { - return address - } - - override suspend fun send(packet: Datagram) {} + override suspend fun send(address: SocketAddress, packet: ByteArrayView) {} override suspend fun stop() {} } @@ -34,6 +40,4 @@ public interface VoiceUdpSocket { } } -@KordVoice -public suspend fun VoiceUdpSocket.receiveFrom(address: InetSocketAddress): Datagram = - incoming.filter { it.address == address }.first() +public suspend fun VoiceUdpSocket.recv(address: SocketAddress): ByteReadPacket = all(address).first() diff --git a/voice/src/commonMain/kotlin/udp/ipDiscovery.kt b/voice/src/commonMain/kotlin/udp/ipDiscovery.kt new file mode 100644 index 00000000000..6b791bd5524 --- /dev/null +++ b/voice/src/commonMain/kotlin/udp/ipDiscovery.kt @@ -0,0 +1,41 @@ +package dev.kord.voice.udp + +import dev.kord.voice.io.mutableCursor +import dev.kord.voice.io.view +import io.github.oshai.kotlinlogging.KotlinLogging +import io.ktor.utils.io.core.* + +private val ipDiscoveryLogger = KotlinLogging.logger { } + +private const val MESSAGE_LENGTH: Short = 70 +private const val DISCOVERY_HEADER_SIZE = 8 +private const val DISCOVERY_DATA_SIZE: Int = 66 +private const val DISCOVERY_MESSAGE_SIZE = DISCOVERY_HEADER_SIZE + DISCOVERY_DATA_SIZE + +private const val REQUEST: Short = 0x01 +private const val RESPONSE: Short = 0x02 + +@OptIn(ExperimentalUnsignedTypes::class) +public suspend fun VoiceUdpSocket.discoverIP(address: SocketAddress, ssrc: Int): SocketAddress { + ipDiscoveryLogger.trace { "discovering ip" } + + val data = ByteArray(DISCOVERY_MESSAGE_SIZE ) + with (data.mutableCursor()) { + writeShort(REQUEST) + writeShort(MESSAGE_LENGTH) + writeInt(ssrc) + } + + send(address, data.view()) + + return with(recv(address)) { + require(readShort() == RESPONSE) { "did not receive a response." } + require(readShort() == MESSAGE_LENGTH) { "expected $MESSAGE_LENGTH bytes of data."} + discardExact(4) // ssrc + + val ip = String(readBytes(64)).trimEnd(0.toChar()) + val port = readUShort().toInt() + + SocketAddress(ip, port) + } +} \ No newline at end of file diff --git a/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt b/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt new file mode 100644 index 00000000000..cb37e81a1fb --- /dev/null +++ b/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt @@ -0,0 +1,66 @@ +package dev.kord.voice.udp + +import dev.kord.common.annotation.KordVoice +import dev.kord.voice.io.ByteArrayView +import io.ktor.utils.io.core.* +import js.typedarrays.toUint8Array +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map +import node.dgram.SocketEvent +import node.dgram.SocketType +import node.dgram.createSocket +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException +import kotlin.coroutines.suspendCoroutine + +@KordVoice +public actual data class SocketAddress actual constructor( + public actual val hostname: String, + public actual val port: Int, +) + +public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket { + private val socketScope = + CoroutineScope(Dispatchers.Default + SupervisorJob() + CoroutineName("kord-voice-global-socket")) + + private val incoming = MutableSharedFlow>() + + private val socket = createSocket(SocketType.udp4) + + init { + socket.on(SocketEvent.MESSAGE) { message, info -> + // + socketScope.launch { + incoming.emit(SocketAddress(info.address, info.port.toInt()) to message.toByteArray()) + } + } + } + + override fun all(address: SocketAddress): Flow = incoming + .filter { it.first == address } + .map { ByteReadPacket(it.second) } + + override suspend fun send(address: SocketAddress, packet: ByteArrayView) { + suspendCoroutine { cont -> + socket.send( + packet.data.toUint8Array(), + packet.dataStart, + packet.viewSize, + address.port, + address.hostname + ) { error, _ -> + if (error != null) { + cont.resumeWithException(error) + } else { + cont.resume(Unit) + } + } + } + } + + override suspend fun stop() { + } +} diff --git a/voice/src/nonJsMain/kotlin/udp/VoiceUdpSocket.nonJs.kt b/voice/src/nonJsMain/kotlin/udp/VoiceUdpSocket.nonJs.kt new file mode 100644 index 00000000000..8289998c890 --- /dev/null +++ b/voice/src/nonJsMain/kotlin/udp/VoiceUdpSocket.nonJs.kt @@ -0,0 +1,46 @@ +package dev.kord.voice.udp + +import dev.kord.common.annotation.KordVoice +import dev.kord.voice.io.ByteArrayView +import io.ktor.network.sockets.* +import io.ktor.network.selector.* +import io.ktor.network.sockets.Datagram +import io.ktor.utils.io.core.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import io.ktor.network.sockets.Datagram as KtorDatagram + +@KordVoice +public actual typealias SocketAddress = InetSocketAddress + +@KordVoice +public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket { + private val socketScope = + CoroutineScope(Dispatchers.Default + SupervisorJob() + CoroutineName("kord-voice-global-socket")) + + private val socket = aSocket(SelectorManager(socketScope.coroutineContext)).udp().bind() + + private val incoming: MutableSharedFlow = MutableSharedFlow() + + init { + socket.incoming + .consumeAsFlow() + .onEach { incoming.emit(it) } + .launchIn(socketScope) + } + + override fun all(address: SocketAddress): Flow { + return incoming + .filter { it.address == address } + .map { it.packet } + } + + override suspend fun send(address: SocketAddress, packet: ByteArrayView) { + val brp = ByteReadPacket(packet.data, packet.dataStart, packet.viewSize) + socket.send(KtorDatagram(brp, address)) + } + + override suspend fun stop() { + } +} + diff --git a/voice/src/nonJvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt b/voice/src/nonJvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt index 6225c38a54f..51df4c37d3e 100644 --- a/voice/src/nonJvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt +++ b/voice/src/nonJvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt @@ -9,6 +9,7 @@ import dev.kord.voice.udp.RTPPacket import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.mapNotNull +@OptIn(ExperimentalUnsignedTypes::class) internal actual fun Flow.decrypt(nonceStrategy: NonceStrategy, key: ByteArray): Flow { val nonceBuffer = ByteArray(crypto_secretbox_NONCEBYTES).mutableCursor() val uKey = key.asUByteArray() diff --git a/voice/src/nonJvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt b/voice/src/nonJvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt index de7fa8d3c65..2b5766b912e 100644 --- a/voice/src/nonJvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt +++ b/voice/src/nonJvmMain/kotlin/dev/kord/voice/udp/DefaultAudioPacketProvider.kt @@ -1,6 +1,7 @@ package dev.kord.voice.udp import com.ionspin.kotlin.crypto.secretbox.SecretBox +import com.ionspin.kotlin.crypto.secretbox.crypto_secretbox_NONCEBYTES import dev.kord.voice.encryption.strategies.NonceStrategy import dev.kord.voice.io.ByteArrayView import dev.kord.voice.io.MutableByteArrayCursor @@ -22,10 +23,11 @@ public class DefaultNativeAudioPacketProvider(key: ByteArray, nonceStrategy: Non private val rtpHeaderView: ByteArrayView = packetBuffer.view(0, RTP_HEADER_LENGTH)!! - private val nonceBuffer: MutableByteArrayCursor = ByteArray(4).mutableCursor() + private val nonceBuffer: MutableByteArrayCursor = ByteArray(crypto_secretbox_NONCEBYTES).mutableCursor() private val lock = SynchronizedObject() + @OptIn(ExperimentalUnsignedTypes::class) override fun provide(sequence: UShort, timestamp: UInt, ssrc: UInt, data: ByteArray): ByteArrayView = synchronized(lock) { with(packetBufferCursor) { From dc42c76ae7f0495a52a739980a15fb252f0346d0 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 13 Apr 2024 01:02:36 +0200 Subject: [PATCH 58/83] Add stubs for Windows Relates-to: #929 --- .../kotlin/VoiceConnectionBuilder.kt | 10 ++++ .../kotlin/VoiceConnectionBuilder.js.kt | 3 ++ .../kotlin/VoiceConnectionBuilder.ktor.kt | 3 ++ .../kotlin/udp/VoiceUdpSocket.ktor.kt | 46 +++++++++++++++++++ .../kotlin/VoiceConnectionBuilder.mingw.kt | 3 ++ .../kotlin/udp/VoiceUdpSocket.nonJs.kt | 18 ++++++++ .../nonKtorMain/kotlin/VoiceUdpSocket.js.kt | 9 ++++ 7 files changed, 92 insertions(+) create mode 100644 voice/src/jsMain/kotlin/VoiceConnectionBuilder.js.kt create mode 100644 voice/src/ktorMain/kotlin/VoiceConnectionBuilder.ktor.kt create mode 100644 voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt create mode 100644 voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt create mode 100644 voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.nonJs.kt create mode 100644 voice/src/nonKtorMain/kotlin/VoiceUdpSocket.js.kt diff --git a/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt b/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt index f9aa30990d7..c0fd221612c 100644 --- a/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt +++ b/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt @@ -25,6 +25,8 @@ import kotlinx.coroutines.flow.first import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds +internal expect val isSupported: Boolean + @KordVoice public class VoiceConnectionBuilder( public var gateway: Gateway, @@ -32,6 +34,14 @@ public class VoiceConnectionBuilder( public var channelId: Snowflake, public var guildId: Snowflake ) { + init { + if(!isSupported) { + throw UnsupportedOperationException(""" + Voice is currently not supported on Windows, if you're developing on Windows we recommend using + WSL: https://aka.ms/wsl + """.trimIndent()) + } + } /** * The amount in milliseconds to wait for the events required to create a [VoiceConnection]. Default is 5000, or 5 seconds. */ diff --git a/voice/src/jsMain/kotlin/VoiceConnectionBuilder.js.kt b/voice/src/jsMain/kotlin/VoiceConnectionBuilder.js.kt new file mode 100644 index 00000000000..df8eacf9fe9 --- /dev/null +++ b/voice/src/jsMain/kotlin/VoiceConnectionBuilder.js.kt @@ -0,0 +1,3 @@ +package dev.kord.voice + +internal actual val isSupported: Boolean = true diff --git a/voice/src/ktorMain/kotlin/VoiceConnectionBuilder.ktor.kt b/voice/src/ktorMain/kotlin/VoiceConnectionBuilder.ktor.kt new file mode 100644 index 00000000000..df8eacf9fe9 --- /dev/null +++ b/voice/src/ktorMain/kotlin/VoiceConnectionBuilder.ktor.kt @@ -0,0 +1,3 @@ +package dev.kord.voice + +internal actual val isSupported: Boolean = true diff --git a/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt b/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt new file mode 100644 index 00000000000..8289998c890 --- /dev/null +++ b/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt @@ -0,0 +1,46 @@ +package dev.kord.voice.udp + +import dev.kord.common.annotation.KordVoice +import dev.kord.voice.io.ByteArrayView +import io.ktor.network.sockets.* +import io.ktor.network.selector.* +import io.ktor.network.sockets.Datagram +import io.ktor.utils.io.core.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import io.ktor.network.sockets.Datagram as KtorDatagram + +@KordVoice +public actual typealias SocketAddress = InetSocketAddress + +@KordVoice +public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket { + private val socketScope = + CoroutineScope(Dispatchers.Default + SupervisorJob() + CoroutineName("kord-voice-global-socket")) + + private val socket = aSocket(SelectorManager(socketScope.coroutineContext)).udp().bind() + + private val incoming: MutableSharedFlow = MutableSharedFlow() + + init { + socket.incoming + .consumeAsFlow() + .onEach { incoming.emit(it) } + .launchIn(socketScope) + } + + override fun all(address: SocketAddress): Flow { + return incoming + .filter { it.address == address } + .map { it.packet } + } + + override suspend fun send(address: SocketAddress, packet: ByteArrayView) { + val brp = ByteReadPacket(packet.data, packet.dataStart, packet.viewSize) + socket.send(KtorDatagram(brp, address)) + } + + override suspend fun stop() { + } +} + diff --git a/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt b/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt new file mode 100644 index 00000000000..b6b6d633f6f --- /dev/null +++ b/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt @@ -0,0 +1,3 @@ +package dev.kord.voice + +internal actual val isSupported: Boolean = false \ No newline at end of file diff --git a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.nonJs.kt b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.nonJs.kt new file mode 100644 index 00000000000..39d77fa9110 --- /dev/null +++ b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.nonJs.kt @@ -0,0 +1,18 @@ +package dev.kord.voice.udp + +import dev.kord.common.annotation.KordVoice +import dev.kord.voice.io.ByteArrayView +import io.ktor.utils.io.core.* +import kotlinx.coroutines.flow.Flow + +@KordVoice +public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket { + override fun all(address: SocketAddress): Flow = unsupported() + + override suspend fun send(address: SocketAddress, packet: ByteArrayView) = unsupported() + + override suspend fun stop() = unsupported() +} + +private fun unsupported(): Nothing = TODO("Voice is not supported on windows") + diff --git a/voice/src/nonKtorMain/kotlin/VoiceUdpSocket.js.kt b/voice/src/nonKtorMain/kotlin/VoiceUdpSocket.js.kt new file mode 100644 index 00000000000..3c5972f6720 --- /dev/null +++ b/voice/src/nonKtorMain/kotlin/VoiceUdpSocket.js.kt @@ -0,0 +1,9 @@ +package dev.kord.voice.udp + +import dev.kord.common.annotation.KordVoice + +@KordVoice +public actual data class SocketAddress actual constructor( + public actual val hostname: String, + public actual val port: Int, +) From 078dce7dee2c55e73ee03fce6d7d73ffd6b4ba48 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 13 Apr 2024 01:11:48 +0200 Subject: [PATCH 59/83] Minor cleanup --- .../kotlin/VoiceConnectionBuilder.mingw.kt | 2 +- ...ocket.nonJs.kt => VoiceUdpSocket.mingw.kt} | 1 - .../kotlin/udp/VoiceUdpSocket.nonJs.kt | 46 ------------------- 3 files changed, 1 insertion(+), 48 deletions(-) rename voice/src/mingwMain/kotlin/udp/{VoiceUdpSocket.nonJs.kt => VoiceUdpSocket.mingw.kt} (99%) delete mode 100644 voice/src/nonJsMain/kotlin/udp/VoiceUdpSocket.nonJs.kt diff --git a/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt b/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt index b6b6d633f6f..fe2534fcf53 100644 --- a/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt +++ b/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt @@ -1,3 +1,3 @@ package dev.kord.voice -internal actual val isSupported: Boolean = false \ No newline at end of file +internal actual val isSupported: Boolean = false diff --git a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.nonJs.kt b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt similarity index 99% rename from voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.nonJs.kt rename to voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt index 39d77fa9110..1251a8c86ba 100644 --- a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.nonJs.kt +++ b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt @@ -15,4 +15,3 @@ public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket } private fun unsupported(): Nothing = TODO("Voice is not supported on windows") - diff --git a/voice/src/nonJsMain/kotlin/udp/VoiceUdpSocket.nonJs.kt b/voice/src/nonJsMain/kotlin/udp/VoiceUdpSocket.nonJs.kt deleted file mode 100644 index 8289998c890..00000000000 --- a/voice/src/nonJsMain/kotlin/udp/VoiceUdpSocket.nonJs.kt +++ /dev/null @@ -1,46 +0,0 @@ -package dev.kord.voice.udp - -import dev.kord.common.annotation.KordVoice -import dev.kord.voice.io.ByteArrayView -import io.ktor.network.sockets.* -import io.ktor.network.selector.* -import io.ktor.network.sockets.Datagram -import io.ktor.utils.io.core.* -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* -import io.ktor.network.sockets.Datagram as KtorDatagram - -@KordVoice -public actual typealias SocketAddress = InetSocketAddress - -@KordVoice -public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket { - private val socketScope = - CoroutineScope(Dispatchers.Default + SupervisorJob() + CoroutineName("kord-voice-global-socket")) - - private val socket = aSocket(SelectorManager(socketScope.coroutineContext)).udp().bind() - - private val incoming: MutableSharedFlow = MutableSharedFlow() - - init { - socket.incoming - .consumeAsFlow() - .onEach { incoming.emit(it) } - .launchIn(socketScope) - } - - override fun all(address: SocketAddress): Flow { - return incoming - .filter { it.address == address } - .map { it.packet } - } - - override suspend fun send(address: SocketAddress, packet: ByteArrayView) { - val brp = ByteReadPacket(packet.data, packet.dataStart, packet.viewSize) - socket.send(KtorDatagram(brp, address)) - } - - override suspend fun stop() { - } -} - From 6c49fbd96f8950dfa048633730ddf9d55f5172b5 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 13 Apr 2024 01:15:33 +0200 Subject: [PATCH 60/83] Update target chart --- README.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 01d68716b00..089195ce829 100644 --- a/README.md +++ b/README.md @@ -37,18 +37,17 @@ mapping of the Voice API on Kotlin/JVM ## Modules -| Module | Docs | Artifact | JVM | JS | Native² | -|--------------------------|---------------------------------------------------------|-------------------|-----|----|---------| -| [common](common) | [common](https://kordlib.github.io/kord/common) | `kord-common`¹ | ✅ | ✅ | ❌ | -| [rest](rest) | [rest](https://kordlib.github.io/kord/rest) | `kord-rest`¹ | ✅ | ✅ | ❌ | -| [gateway](gateway) | [gateway](https://kordlib.github.io/kord/gateway) | `kord-gateway`¹ | ✅ | ✅ | ❌ | -| [core](core) | [core](https://kordlib.github.io/kord/core) | `kord-core`¹ | ✅ | ✅ | ❌ | -| [voice](voice) | [voice](https://kordlib.github.io/kord/voice) | `kord-voice` | ✅ | ❌³ | ❌ | -| [core-voice](core-voice) | [core-voice](https://kordlib.github.io/kord/core-voice) | `kord-core-voice` | ✅ | ❌ | ❌ | +| Module | Docs | Artifact | JVM | JS (NodeJS) | Native | +|--------------------------|---------------------------------------------------------|--------------------|-----|-------------|--------| +| [common](common) | [common](https://kordlib.github.io/kord/common) | `kord-common`¹ | ✅ | ✅ | ✅ | +| [rest](rest) | [rest](https://kordlib.github.io/kord/rest) | `kord-rest`¹ | ✅ | ✅ | ✅ | +| [gateway](gateway) | [gateway](https://kordlib.github.io/kord/gateway) | `kord-gateway`¹ | ✅ | ✅ | ✅ | +| [core](core) | [core](https://kordlib.github.io/kord/core) | `kord-core`¹ | ✅ | ✅ | ✅ | +| [voice](voice) | [voice](https://kordlib.github.io/kord/voice) | `kord-voice`¹ | ✅ | ✅ | ✅² | +| [core-voice](core-voice) | [core-voice](https://kordlib.github.io/kord/core-voice) | `kord-core-voice`¹ | ✅ | ✅ | ✅² | ¹ These artifacts only supports Gradle Version 5.3 or higher, for older Gradle versions and Maven please append `-jvm` -² For Native Support please see #69 -³ For Voice JS please see #69 +² Currently not on Windows(MinGW) targets, see #69 ## Installation From 644f5a7ba4210841925da7af17ee1ae7b0698223 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 13 Apr 2024 01:38:12 +0200 Subject: [PATCH 61/83] Fix compilation --- voice/build.gradle.kts | 19 ++++++++++++++++++- .../jsMain/kotlin/udp/VoiceUdpSocket.js.kt | 6 ------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/voice/build.gradle.kts b/voice/build.gradle.kts index fb30ec969ab..6cdda52ccf9 100644 --- a/voice/build.gradle.kts +++ b/voice/build.gradle.kts @@ -1,9 +1,26 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi + plugins { `kord-multiplatform-module` `kord-publishing` } +@OptIn(ExperimentalKotlinGradlePluginApi::class) kotlin { + applyDefaultHierarchyTemplate { + common { + group("ktor") { + withJvm() + withApple() + withLinux() + } + + group("nonKtor") { + withJs() + withMingw() + } + } + } jvm { withJava() } @@ -18,7 +35,7 @@ kotlin { compileOnly(projects.kspAnnotations) } - nonJsMain.dependencies { + named("ktorMain").dependencies { api(libs.ktor.network) } diff --git a/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt b/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt index cb37e81a1fb..c411dbc582a 100644 --- a/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt +++ b/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt @@ -16,12 +16,6 @@ import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine -@KordVoice -public actual data class SocketAddress actual constructor( - public actual val hostname: String, - public actual val port: Int, -) - public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket { private val socketScope = CoroutineScope(Dispatchers.Default + SupervisorJob() + CoroutineName("kord-voice-global-socket")) From 6ba4d9be233c6e389f506bc7b3e875ab37dcb170 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Sat, 13 Apr 2024 01:38:35 +0200 Subject: [PATCH 62/83] API dump --- common/api/common.klib.api | 2 +- core-voice/api/core-voice.klib.api | 9 + core/api/core.klib.api | 4 +- gateway/api/gateway.klib.api | 5 +- rest/api/rest.klib.api | 4 +- voice/api/voice.api | 2 +- voice/api/voice.klib.api | 978 +++++++++++++++++++++++++++++ 7 files changed, 993 insertions(+), 11 deletions(-) create mode 100644 core-voice/api/core-voice.klib.api create mode 100644 voice/api/voice.klib.api diff --git a/common/api/common.klib.api b/common/api/common.klib.api index bda19192188..e6a0c34c1ab 100644 --- a/common/api/common.klib.api +++ b/common/api/common.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/core-voice/api/core-voice.klib.api b/core-voice/api/core-voice.klib.api new file mode 100644 index 00000000000..022e4cd6a41 --- /dev/null +++ b/core-voice/api/core-voice.klib.api @@ -0,0 +1,9 @@ +// Klib ABI Dump +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Rendering settings: +// - Signature version: 2 +// - Show manifest properties: true +// - Show declarations: true + +// Library unique name: +final suspend fun (dev.kord.core.behavior.channel/BaseVoiceChannelBehavior).dev.kord.core.behavior.channel/connect(kotlin/Function1): dev.kord.voice/VoiceConnection // dev.kord.core.behavior.channel/connect|connect@dev.kord.core.behavior.channel.BaseVoiceChannelBehavior(kotlin.Function1){}[0] diff --git a/core/api/core.klib.api b/core/api/core.klib.api index 7b6d1421759..67c81c3d68f 100644 --- a/core/api/core.klib.api +++ b/core/api/core.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true @@ -9632,8 +9632,6 @@ final val dev.kord.core.cache.data/id // dev.kord.core.cache.data/id|@dev.kord.c final fun (dev.kord.core.cache.data/VoiceStateData).(): kotlin/String // dev.kord.core.cache.data/id.|@dev.kord.core.cache.data.VoiceStateData(){}[0] final val dev.kord.core.entity/effectiveName // dev.kord.core.entity/effectiveName|@dev.kord.core.entity.User{}effectiveName[0] final fun (dev.kord.core.entity/User).(): kotlin/String // dev.kord.core.entity/effectiveName.|@dev.kord.core.entity.User(){}[0] -final val dev.kord.core/kordLogger // dev.kord.core/kordLogger|{}kordLogger[0] - final fun (): mu/KLogger // dev.kord.core/kordLogger.|(){}[0] open class dev.kord.core.entity.interaction/UserOptionValue : dev.kord.core.entity.interaction/ResolvableOptionValue { // dev.kord.core.entity.interaction/UserOptionValue|null[0] constructor (dev.kord.common.entity/Snowflake, kotlin/Boolean, dev.kord.core.entity/User?) // dev.kord.core.entity.interaction/UserOptionValue.|(dev.kord.common.entity.Snowflake;kotlin.Boolean;dev.kord.core.entity.User?){}[0] open fun toString(): kotlin/String // dev.kord.core.entity.interaction/UserOptionValue.toString|toString(){}[0] diff --git a/gateway/api/gateway.klib.api b/gateway/api/gateway.klib.api index d900ce6e455..0c463ab1ea3 100644 --- a/gateway/api/gateway.klib.api +++ b/gateway/api/gateway.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true @@ -1740,7 +1740,6 @@ final enum class dev.kord.gateway/OpCode : kotlin/Enum } final fun (dev.kord.gateway/Gateway).dev.kord.gateway/requestGuildMembers(dev.kord.common.entity/Snowflake, kotlin/Function1 =...): kotlinx.coroutines.flow/Flow // dev.kord.gateway/requestGuildMembers|requestGuildMembers@dev.kord.gateway.Gateway(dev.kord.common.entity.Snowflake;kotlin.Function1){}[0] final fun (dev.kord.gateway/Gateway).dev.kord.gateway/requestGuildMembers(dev.kord.gateway/RequestGuildMembers): kotlinx.coroutines.flow/Flow // dev.kord.gateway/requestGuildMembers|requestGuildMembers@dev.kord.gateway.Gateway(dev.kord.gateway.RequestGuildMembers){}[0] -final fun (mu/KLogger).dev.kord.gateway/error(kotlin/Throwable) // dev.kord.gateway/error|error@mu.KLogger(kotlin.Throwable){}[0] final fun dev.kord.gateway.ratelimit/IdentifyRateLimiter(kotlin/Int, kotlinx.coroutines/CoroutineDispatcher =...): dev.kord.gateway.ratelimit/IdentifyRateLimiter // dev.kord.gateway.ratelimit/IdentifyRateLimiter|IdentifyRateLimiter(kotlin.Int;kotlinx.coroutines.CoroutineDispatcher){}[0] final fun dev.kord.gateway/Intents(kotlin.collections/Iterable): dev.kord.gateway/Intents // dev.kord.gateway/Intents|Intents(kotlin.collections.Iterable){}[0] final fun dev.kord.gateway/Intents(kotlin.collections/Iterable): dev.kord.gateway/Intents // dev.kord.gateway/Intents|Intents(kotlin.collections.Iterable){}[0] @@ -1763,8 +1762,6 @@ final val dev.kord.gateway/NON_PRIVILEGED // dev.kord.gateway/NON_PRIVILEGED|@de final fun (dev.kord.gateway/Intents.Companion).(): dev.kord.gateway/Intents // dev.kord.gateway/NON_PRIVILEGED.|@dev.kord.gateway.Intents.Companion(){}[0] final val dev.kord.gateway/PRIVILEGED // dev.kord.gateway/PRIVILEGED|@dev.kord.gateway.Intents.Companion(){}[0] final fun (dev.kord.gateway/Intents.Companion).(): dev.kord.gateway/Intents // dev.kord.gateway/PRIVILEGED.|@dev.kord.gateway.Intents.Companion(){}[0] -final val dev.kord.gateway/gatewayOnLogger // dev.kord.gateway/gatewayOnLogger|{}gatewayOnLogger[0] - final fun (): mu/KLogger // dev.kord.gateway/gatewayOnLogger.|(){}[0] open annotation class dev.kord.gateway/PrivilegedIntent : kotlin/Annotation { // dev.kord.gateway/PrivilegedIntent|null[0] constructor () // dev.kord.gateway/PrivilegedIntent.|(){}[0] } diff --git a/rest/api/rest.klib.api b/rest/api/rest.klib.api index 02e5dc47250..bcc2f50bad7 100644 --- a/rest/api/rest.klib.api +++ b/rest/api/rest.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true @@ -769,8 +769,8 @@ final class dev.kord.rest.builder.channel/MediaChannelCreateBuilder : dev.kord.r } final class dev.kord.rest.builder.channel/MediaChannelModifyBuilder : dev.kord.rest.builder.channel/PermissionOverwritesModifyBuilder, dev.kord.rest.builder/AuditRequestBuilder { // dev.kord.rest.builder.channel/MediaChannelModifyBuilder|null[0] constructor () // dev.kord.rest.builder.channel/MediaChannelModifyBuilder.|(){}[0] - final fun tag(kotlin/String, kotlin/Function1 =...) // dev.kord.rest.builder.channel/MediaChannelModifyBuilder.tag|tag(kotlin.String;kotlin.Function1){}[0] final fun toRequest(): dev.kord.rest.json.request/ChannelModifyPatchRequest // dev.kord.rest.builder.channel/MediaChannelModifyBuilder.toRequest|toRequest(){}[0] + final inline fun tag(kotlin/String, kotlin/Function1 =...) // dev.kord.rest.builder.channel/MediaChannelModifyBuilder.tag|tag(kotlin.String;kotlin.Function1){}[0] final var availableTags // dev.kord.rest.builder.channel/MediaChannelModifyBuilder.availableTags|{}availableTags[0] final fun (): kotlin.collections/MutableList? // dev.kord.rest.builder.channel/MediaChannelModifyBuilder.availableTags.|(){}[0] final fun (kotlin.collections/MutableList?) // dev.kord.rest.builder.channel/MediaChannelModifyBuilder.availableTags.|(kotlin.collections.MutableList?){}[0] diff --git a/voice/api/voice.api b/voice/api/voice.api index d261de8b3fe..92dfbd52728 100644 --- a/voice/api/voice.api +++ b/voice/api/voice.api @@ -1257,7 +1257,7 @@ public final class dev/kord/voice/udp/VoiceUdpSocketKt { public static final fun recv (Ldev/kord/voice/udp/VoiceUdpSocket;Lio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class dev/kord/voice/udp/VoiceUdpSocket_nonJsKt { +public final class dev/kord/voice/udp/VoiceUdpSocket_ktorKt { public static final fun getGlobalVoiceUdpSocket ()Ldev/kord/voice/udp/VoiceUdpSocket; } diff --git a/voice/api/voice.klib.api b/voice/api/voice.klib.api new file mode 100644 index 00000000000..3f367707eaf --- /dev/null +++ b/voice/api/voice.klib.api @@ -0,0 +1,978 @@ +// Klib ABI Dump +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Rendering settings: +// - Signature version: 2 +// - Show manifest properties: true +// - Show declarations: true + +// Library unique name: +abstract class dev.kord.voice.udp/AudioPacketProvider { // dev.kord.voice.udp/AudioPacketProvider|null[0] + abstract fun provide(kotlin/UShort, kotlin/UInt, kotlin/UInt, kotlin/ByteArray): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/AudioPacketProvider.provide|provide(kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.ByteArray){}[0] + constructor (kotlin/ByteArray, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.udp/AudioPacketProvider.|(kotlin.ByteArray;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] + final val key // dev.kord.voice.udp/AudioPacketProvider.key|{}key[0] + final fun (): kotlin/ByteArray // dev.kord.voice.udp/AudioPacketProvider.key.|(){}[0] + final val nonceStrategy // dev.kord.voice.udp/AudioPacketProvider.nonceStrategy|{}nonceStrategy[0] + final fun (): dev.kord.voice.encryption.strategies/NonceStrategy // dev.kord.voice.udp/AudioPacketProvider.nonceStrategy.|(){}[0] +} +abstract fun interface dev.kord.voice/AudioProvider { // dev.kord.voice/AudioProvider|null[0] + abstract suspend fun provide(): dev.kord.voice/AudioFrame? // dev.kord.voice/AudioProvider.provide|provide(){}[0] + open suspend fun (kotlinx.coroutines/CoroutineScope).provideFrames(kotlinx.coroutines.channels/SendChannel) // dev.kord.voice/AudioProvider.provideFrames|provideFrames@kotlinx.coroutines.CoroutineScope(kotlinx.coroutines.channels.SendChannel){}[0] +} +abstract fun interface dev.kord.voice/FrameInterceptor { // dev.kord.voice/FrameInterceptor|null[0] + abstract fun (kotlinx.coroutines.flow/Flow).intercept(dev.kord.voice/FrameInterceptorConfiguration): kotlinx.coroutines.flow/Flow // dev.kord.voice/FrameInterceptor.intercept|intercept@kotlinx.coroutines.flow.Flow(dev.kord.voice.FrameInterceptorConfiguration){}[0] +} +abstract interface dev.kord.voice.gateway/VoiceGateway { // dev.kord.voice.gateway/VoiceGateway|null[0] + abstract suspend fun detach() // dev.kord.voice.gateway/VoiceGateway.detach|detach(){}[0] + abstract suspend fun send(dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/VoiceGateway.send|send(dev.kord.voice.gateway.Command){}[0] + abstract suspend fun start(dev.kord.voice.gateway/VoiceGatewayConfiguration) // dev.kord.voice.gateway/VoiceGateway.start|start(dev.kord.voice.gateway.VoiceGatewayConfiguration){}[0] + abstract suspend fun stop() // dev.kord.voice.gateway/VoiceGateway.stop|stop(){}[0] + abstract val events // dev.kord.voice.gateway/VoiceGateway.events|{}events[0] + abstract fun (): kotlinx.coroutines.flow/SharedFlow // dev.kord.voice.gateway/VoiceGateway.events.|(){}[0] + abstract val ping // dev.kord.voice.gateway/VoiceGateway.ping|{}ping[0] + abstract fun (): kotlinx.coroutines.flow/StateFlow // dev.kord.voice.gateway/VoiceGateway.ping.|(){}[0] + abstract val scope // dev.kord.voice.gateway/VoiceGateway.scope|{}scope[0] + abstract fun (): kotlinx.coroutines/CoroutineScope // dev.kord.voice.gateway/VoiceGateway.scope.|(){}[0] + final object Companion { // dev.kord.voice.gateway/VoiceGateway.Companion|null[0] + final fun none(): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice.gateway/VoiceGateway.Companion.none|none(){}[0] + } +} +abstract interface dev.kord.voice.streams/Streams { // dev.kord.voice.streams/Streams|null[0] + abstract suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/Streams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] + abstract val incomingAudioFrames // dev.kord.voice.streams/Streams.incomingAudioFrames|{}incomingAudioFrames[0] + abstract fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/Streams.incomingAudioFrames.|(){}[0] + abstract val incomingAudioPackets // dev.kord.voice.streams/Streams.incomingAudioPackets|{}incomingAudioPackets[0] + abstract fun (): kotlinx.coroutines.flow/Flow // dev.kord.voice.streams/Streams.incomingAudioPackets.|(){}[0] + abstract val incomingUserStreams // dev.kord.voice.streams/Streams.incomingUserStreams|{}incomingUserStreams[0] + abstract fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/Streams.incomingUserStreams.|(){}[0] + abstract val ssrcToUser // dev.kord.voice.streams/Streams.ssrcToUser|{}ssrcToUser[0] + abstract fun (): kotlin.collections/Map // dev.kord.voice.streams/Streams.ssrcToUser.|(){}[0] +} +abstract interface dev.kord.voice.udp/AudioFrameSender { // dev.kord.voice.udp/AudioFrameSender|null[0] + abstract suspend fun start(dev.kord.voice.udp/AudioFrameSenderConfiguration) // dev.kord.voice.udp/AudioFrameSender.start|start(dev.kord.voice.udp.AudioFrameSenderConfiguration){}[0] +} +abstract interface dev.kord.voice.udp/VoiceUdpSocket { // dev.kord.voice.udp/VoiceUdpSocket|null[0] + abstract fun all(dev.kord.voice.udp/SocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(dev.kord.voice.udp.SocketAddress){}[0] + abstract suspend fun send(dev.kord.voice.udp/SocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(dev.kord.voice.udp.SocketAddress;dev.kord.voice.io.ByteArrayView){}[0] + abstract suspend fun stop() // dev.kord.voice.udp/VoiceUdpSocket.stop|stop(){}[0] + final object Companion { // dev.kord.voice.udp/VoiceUdpSocket.Companion|null[0] + final fun none(): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/VoiceUdpSocket.Companion.none|none(){}[0] + } +} +final class dev.kord.voice.encryption.strategies/LiteNonceStrategy : dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/LiteNonceStrategy|null[0] + constructor () // dev.kord.voice.encryption.strategies/LiteNonceStrategy.|(){}[0] + final fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/LiteNonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] + final fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/LiteNonceStrategy.generate|generate(kotlin.Function0){}[0] + final fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/LiteNonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] + final val nonceLength // dev.kord.voice.encryption.strategies/LiteNonceStrategy.nonceLength|{}nonceLength[0] + final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/LiteNonceStrategy.nonceLength.|(){}[0] +} +final class dev.kord.voice.encryption.strategies/NormalNonceStrategy : dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/NormalNonceStrategy|null[0] + constructor () // dev.kord.voice.encryption.strategies/NormalNonceStrategy.|(){}[0] + final fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/NormalNonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] + final fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NormalNonceStrategy.generate|generate(kotlin.Function0){}[0] + final fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NormalNonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] + final val nonceLength // dev.kord.voice.encryption.strategies/NormalNonceStrategy.nonceLength|{}nonceLength[0] + final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/NormalNonceStrategy.nonceLength.|(){}[0] +} +final class dev.kord.voice.encryption.strategies/SuffixNonceStrategy : dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/SuffixNonceStrategy|null[0] + constructor () // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.|(){}[0] + final fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] + final fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.generate|generate(kotlin.Function0){}[0] + final fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] + final val nonceLength // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.nonceLength|{}nonceLength[0] + final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.nonceLength.|(){}[0] +} +final class dev.kord.voice.exception/VoiceConnectionInitializationException : kotlin/Exception { // dev.kord.voice.exception/VoiceConnectionInitializationException|null[0] + constructor (kotlin/String) // dev.kord.voice.exception/VoiceConnectionInitializationException.|(kotlin.String){}[0] + constructor (kotlin/String, kotlin/Throwable) // dev.kord.voice.exception/VoiceConnectionInitializationException.|(kotlin.String;kotlin.Throwable){}[0] + constructor (kotlin/Throwable) // dev.kord.voice.exception/VoiceConnectionInitializationException.|(kotlin.Throwable){}[0] +} +final class dev.kord.voice.gateway/DefaultVoiceGateway : dev.kord.voice.gateway/VoiceGateway { // dev.kord.voice.gateway/DefaultVoiceGateway|null[0] + constructor (dev.kord.voice.gateway/DefaultVoiceGatewayData) // dev.kord.voice.gateway/DefaultVoiceGateway.|(dev.kord.voice.gateway.DefaultVoiceGatewayData){}[0] + final suspend fun detach() // dev.kord.voice.gateway/DefaultVoiceGateway.detach|detach(){}[0] + final suspend fun send(dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/DefaultVoiceGateway.send|send(dev.kord.voice.gateway.Command){}[0] + final suspend fun start(dev.kord.voice.gateway/VoiceGatewayConfiguration) // dev.kord.voice.gateway/DefaultVoiceGateway.start|start(dev.kord.voice.gateway.VoiceGatewayConfiguration){}[0] + final suspend fun stop() // dev.kord.voice.gateway/DefaultVoiceGateway.stop|stop(){}[0] + final val events // dev.kord.voice.gateway/DefaultVoiceGateway.events|{}events[0] + final fun (): kotlinx.coroutines.flow/SharedFlow // dev.kord.voice.gateway/DefaultVoiceGateway.events.|(){}[0] + final val ping // dev.kord.voice.gateway/DefaultVoiceGateway.ping|{}ping[0] + final fun (): kotlinx.coroutines.flow/StateFlow // dev.kord.voice.gateway/DefaultVoiceGateway.ping.|(){}[0] + final val scope // dev.kord.voice.gateway/DefaultVoiceGateway.scope|{}scope[0] + final fun (): kotlinx.coroutines/CoroutineScope // dev.kord.voice.gateway/DefaultVoiceGateway.scope.|(){}[0] +} +final class dev.kord.voice.gateway/DefaultVoiceGatewayBuilder { // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder|null[0] + constructor (dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/String) // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.|(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String){}[0] + final fun build(): dev.kord.voice.gateway/DefaultVoiceGateway // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.build|build(){}[0] + final val guildId // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.guildId|{}guildId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.guildId.|(){}[0] + final val selfId // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.selfId|{}selfId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.selfId.|(){}[0] + final val sessionId // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.sessionId|{}sessionId[0] + final fun (): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.sessionId.|(){}[0] + final var client // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.client|{}client[0] + final fun (): io.ktor.client/HttpClient? // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.client.|(){}[0] + final fun (io.ktor.client/HttpClient?) // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.client.|(io.ktor.client.HttpClient?){}[0] + final var eventFlow // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.eventFlow|{}eventFlow[0] + final fun (): kotlinx.coroutines.flow/MutableSharedFlow // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.eventFlow.|(){}[0] + final fun (kotlinx.coroutines.flow/MutableSharedFlow) // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.eventFlow.|(kotlinx.coroutines.flow.MutableSharedFlow){}[0] + final var reconnectRetry // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.reconnectRetry|{}reconnectRetry[0] + final fun (): dev.kord.gateway.retry/Retry? // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.reconnectRetry.|(){}[0] + final fun (dev.kord.gateway.retry/Retry?) // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.reconnectRetry.|(dev.kord.gateway.retry.Retry?){}[0] +} +final class dev.kord.voice.gateway/DefaultVoiceGatewayData { // dev.kord.voice.gateway/DefaultVoiceGatewayData|null[0] + constructor (dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/String, io.ktor.client/HttpClient, dev.kord.gateway.retry/Retry, kotlinx.coroutines.flow/MutableSharedFlow) // dev.kord.voice.gateway/DefaultVoiceGatewayData.|(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;kotlinx.coroutines.flow.MutableSharedFlow){}[0] + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.component1|component1(){}[0] + final fun component2(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.component2|component2(){}[0] + final fun component3(): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayData.component3|component3(){}[0] + final fun component4(): io.ktor.client/HttpClient // dev.kord.voice.gateway/DefaultVoiceGatewayData.component4|component4(){}[0] + final fun component5(): dev.kord.gateway.retry/Retry // dev.kord.voice.gateway/DefaultVoiceGatewayData.component5|component5(){}[0] + final fun component6(): kotlinx.coroutines.flow/MutableSharedFlow // dev.kord.voice.gateway/DefaultVoiceGatewayData.component6|component6(){}[0] + final fun copy(dev.kord.common.entity/Snowflake =..., dev.kord.common.entity/Snowflake =..., kotlin/String =..., io.ktor.client/HttpClient =..., dev.kord.gateway.retry/Retry =..., kotlinx.coroutines.flow/MutableSharedFlow =...): dev.kord.voice.gateway/DefaultVoiceGatewayData // dev.kord.voice.gateway/DefaultVoiceGatewayData.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;kotlinx.coroutines.flow.MutableSharedFlow){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/DefaultVoiceGatewayData.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/DefaultVoiceGatewayData.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayData.toString|toString(){}[0] + final val client // dev.kord.voice.gateway/DefaultVoiceGatewayData.client|{}client[0] + final fun (): io.ktor.client/HttpClient // dev.kord.voice.gateway/DefaultVoiceGatewayData.client.|(){}[0] + final val eventFlow // dev.kord.voice.gateway/DefaultVoiceGatewayData.eventFlow|{}eventFlow[0] + final fun (): kotlinx.coroutines.flow/MutableSharedFlow // dev.kord.voice.gateway/DefaultVoiceGatewayData.eventFlow.|(){}[0] + final val guildId // dev.kord.voice.gateway/DefaultVoiceGatewayData.guildId|{}guildId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.guildId.|(){}[0] + final val reconnectRetry // dev.kord.voice.gateway/DefaultVoiceGatewayData.reconnectRetry|{}reconnectRetry[0] + final fun (): dev.kord.gateway.retry/Retry // dev.kord.voice.gateway/DefaultVoiceGatewayData.reconnectRetry.|(){}[0] + final val selfId // dev.kord.voice.gateway/DefaultVoiceGatewayData.selfId|{}selfId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.selfId.|(){}[0] + final val sessionId // dev.kord.voice.gateway/DefaultVoiceGatewayData.sessionId|{}sessionId[0] + final fun (): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayData.sessionId.|(){}[0] +} +final class dev.kord.voice.gateway/Heartbeat : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Heartbeat|null[0] + constructor (kotlin/Long) // dev.kord.voice.gateway/Heartbeat.|(kotlin.Long){}[0] + final fun component1(): kotlin/Long // dev.kord.voice.gateway/Heartbeat.component1|component1(){}[0] + final fun copy(kotlin/Long =...): dev.kord.voice.gateway/Heartbeat // dev.kord.voice.gateway/Heartbeat.copy|copy(kotlin.Long){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Heartbeat.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Heartbeat.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/Heartbeat.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Heartbeat.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Heartbeat.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Heartbeat // dev.kord.voice.gateway/Heartbeat.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Heartbeat) // dev.kord.voice.gateway/Heartbeat.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Heartbeat){}[0] + final val descriptor // dev.kord.voice.gateway/Heartbeat.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Heartbeat.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/Heartbeat.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Heartbeat.Companion.serializer|serializer(){}[0] + } + final val nonce // dev.kord.voice.gateway/Heartbeat.nonce|(){}[0] + final fun (): kotlin/Long // dev.kord.voice.gateway/Heartbeat.nonce.|(){}[0] +} +final class dev.kord.voice.gateway/HeartbeatAck : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/HeartbeatAck|null[0] + constructor (kotlin/Long) // dev.kord.voice.gateway/HeartbeatAck.|(kotlin.Long){}[0] + final fun component1(): kotlin/Long // dev.kord.voice.gateway/HeartbeatAck.component1|component1(){}[0] + final fun copy(kotlin/Long =...): dev.kord.voice.gateway/HeartbeatAck // dev.kord.voice.gateway/HeartbeatAck.copy|copy(kotlin.Long){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/HeartbeatAck.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/HeartbeatAck.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/HeartbeatAck.toString|toString(){}[0] + final object Companion { // dev.kord.voice.gateway/HeartbeatAck.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/HeartbeatAck.Companion.serializer|serializer(){}[0] + } + final val nonce // dev.kord.voice.gateway/HeartbeatAck.nonce|{}nonce[0] + final fun (): kotlin/Long // dev.kord.voice.gateway/HeartbeatAck.nonce.|(){}[0] +} +final class dev.kord.voice.gateway/Hello : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Hello|null[0] + constructor (kotlin/Short, kotlin/Double) // dev.kord.voice.gateway/Hello.|(kotlin.Short;kotlin.Double){}[0] + final fun component1(): kotlin/Short // dev.kord.voice.gateway/Hello.component1|component1(){}[0] + final fun component2(): kotlin/Double // dev.kord.voice.gateway/Hello.component2|component2(){}[0] + final fun copy(kotlin/Short =..., kotlin/Double =...): dev.kord.voice.gateway/Hello // dev.kord.voice.gateway/Hello.copy|copy(kotlin.Short;kotlin.Double){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Hello.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Hello.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/Hello.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Hello.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Hello.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Hello // dev.kord.voice.gateway/Hello.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Hello) // dev.kord.voice.gateway/Hello.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Hello){}[0] + final val descriptor // dev.kord.voice.gateway/Hello.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Hello.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/Hello.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Hello.Companion.serializer|serializer(){}[0] + } + final val heartbeatInterval // dev.kord.voice.gateway/Hello.heartbeatInterval|{}heartbeatInterval[0] + final fun (): kotlin/Double // dev.kord.voice.gateway/Hello.heartbeatInterval.|(){}[0] + final val version // dev.kord.voice.gateway/Hello.version|{}version[0] + final fun (): kotlin/Short // dev.kord.voice.gateway/Hello.version.|(){}[0] +} +final class dev.kord.voice.gateway/Identify : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Identify|null[0] + constructor (dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/String, kotlin/String) // dev.kord.voice.gateway/Identify.|(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.component1|component1(){}[0] + final fun component2(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.component2|component2(){}[0] + final fun component3(): kotlin/String // dev.kord.voice.gateway/Identify.component3|component3(){}[0] + final fun component4(): kotlin/String // dev.kord.voice.gateway/Identify.component4|component4(){}[0] + final fun copy(dev.kord.common.entity/Snowflake =..., dev.kord.common.entity/Snowflake =..., kotlin/String =..., kotlin/String =...): dev.kord.voice.gateway/Identify // dev.kord.voice.gateway/Identify.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Identify.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Identify.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/Identify.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Identify.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Identify.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Identify // dev.kord.voice.gateway/Identify.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Identify) // dev.kord.voice.gateway/Identify.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Identify){}[0] + final val descriptor // dev.kord.voice.gateway/Identify.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Identify.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/Identify.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Identify.Companion.serializer|serializer(){}[0] + } + final val serverId // dev.kord.voice.gateway/Identify.serverId|{}serverId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.serverId.|(){}[0] + final val sessionId // dev.kord.voice.gateway/Identify.sessionId|{}sessionId[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Identify.sessionId.|(){}[0] + final val token // dev.kord.voice.gateway/Identify.token|{}token[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Identify.token.|(){}[0] + final val userId // dev.kord.voice.gateway/Identify.userId|{}userId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.userId.|(){}[0] +} +final class dev.kord.voice.gateway/Ready : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Ready|null[0] + constructor (kotlin/UInt, kotlin/String, kotlin/Int, kotlin.collections/List) // dev.kord.voice.gateway/Ready.|(kotlin.UInt;kotlin.String;kotlin.Int;kotlin.collections.List){}[0] + final fun component1(): kotlin/UInt // dev.kord.voice.gateway/Ready.component1|component1(){}[0] + final fun component2(): kotlin/String // dev.kord.voice.gateway/Ready.component2|component2(){}[0] + final fun component3(): kotlin/Int // dev.kord.voice.gateway/Ready.component3|component3(){}[0] + final fun component4(): kotlin.collections/List // dev.kord.voice.gateway/Ready.component4|component4(){}[0] + final fun copy(kotlin/UInt =..., kotlin/String =..., kotlin/Int =..., kotlin.collections/List =...): dev.kord.voice.gateway/Ready // dev.kord.voice.gateway/Ready.copy|copy(kotlin.UInt;kotlin.String;kotlin.Int;kotlin.collections.List){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Ready.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Ready.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/Ready.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Ready.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Ready.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Ready // dev.kord.voice.gateway/Ready.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Ready) // dev.kord.voice.gateway/Ready.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Ready){}[0] + final val descriptor // dev.kord.voice.gateway/Ready.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Ready.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/Ready.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Ready.Companion.serializer|serializer(){}[0] + final val $childSerializers // dev.kord.voice.gateway/Ready.Companion.$childSerializers|{}$childSerializers[0] + } + final val ip // dev.kord.voice.gateway/Ready.ip|{}ip[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Ready.ip.|(){}[0] + final val modes // dev.kord.voice.gateway/Ready.modes|{}modes[0] + final fun (): kotlin.collections/List // dev.kord.voice.gateway/Ready.modes.|(){}[0] + final val port // dev.kord.voice.gateway/Ready.port|{}port[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/Ready.port.|(){}[0] + final val ssrc // dev.kord.voice.gateway/Ready.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.gateway/Ready.ssrc.|(){}[0] +} +final class dev.kord.voice.gateway/Resume : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Resume|null[0] + constructor (dev.kord.common.entity/Snowflake, kotlin/String, kotlin/String) // dev.kord.voice.gateway/Resume.|(dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Resume.component1|component1(){}[0] + final fun component2(): kotlin/String // dev.kord.voice.gateway/Resume.component2|component2(){}[0] + final fun component3(): kotlin/String // dev.kord.voice.gateway/Resume.component3|component3(){}[0] + final fun copy(dev.kord.common.entity/Snowflake =..., kotlin/String =..., kotlin/String =...): dev.kord.voice.gateway/Resume // dev.kord.voice.gateway/Resume.copy|copy(dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Resume.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Resume.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/Resume.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Resume.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Resume.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Resume // dev.kord.voice.gateway/Resume.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Resume) // dev.kord.voice.gateway/Resume.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Resume){}[0] + final val descriptor // dev.kord.voice.gateway/Resume.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Resume.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/Resume.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Resume.Companion.serializer|serializer(){}[0] + } + final val serverId // dev.kord.voice.gateway/Resume.serverId|{}serverId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Resume.serverId.|(){}[0] + final val sessionId // dev.kord.voice.gateway/Resume.sessionId|{}sessionId[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Resume.sessionId.|(){}[0] + final val token // dev.kord.voice.gateway/Resume.token|{}token[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Resume.token.|(){}[0] +} +final class dev.kord.voice.gateway/SelectProtocol : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/SelectProtocol|null[0] + constructor (kotlin/String, dev.kord.voice.gateway/SelectProtocol.Data) // dev.kord.voice.gateway/SelectProtocol.|(kotlin.String;dev.kord.voice.gateway.SelectProtocol.Data){}[0] + final class Data { // dev.kord.voice.gateway/SelectProtocol.Data|null[0] + constructor (kotlin/String, kotlin/Int, dev.kord.voice/EncryptionMode) // dev.kord.voice.gateway/SelectProtocol.Data.|(kotlin.String;kotlin.Int;dev.kord.voice.EncryptionMode){}[0] + final fun component1(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.Data.component1|component1(){}[0] + final fun component2(): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.Data.component2|component2(){}[0] + final fun component3(): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SelectProtocol.Data.component3|component3(){}[0] + final fun copy(kotlin/String =..., kotlin/Int =..., dev.kord.voice/EncryptionMode =...): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.Data.copy|copy(kotlin.String;kotlin.Int;dev.kord.voice.EncryptionMode){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SelectProtocol.Data.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.Data.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.Data.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/SelectProtocol.Data.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/SelectProtocol.Data) // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.SelectProtocol.Data){}[0] + final val descriptor // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/SelectProtocol.Data.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SelectProtocol.Data.Companion.serializer|serializer(){}[0] + } + final val address // dev.kord.voice.gateway/SelectProtocol.Data.address|{}address[0] + final fun (): kotlin/String // dev.kord.voice.gateway/SelectProtocol.Data.address.|(){}[0] + final val mode // dev.kord.voice.gateway/SelectProtocol.Data.mode|{}mode[0] + final fun (): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SelectProtocol.Data.mode.|(){}[0] + final val port // dev.kord.voice.gateway/SelectProtocol.Data.port|{}port[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.Data.port.|(){}[0] + } + final fun component1(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.component1|component1(){}[0] + final fun component2(): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.component2|component2(){}[0] + final fun copy(kotlin/String =..., dev.kord.voice.gateway/SelectProtocol.Data =...): dev.kord.voice.gateway/SelectProtocol // dev.kord.voice.gateway/SelectProtocol.copy|copy(kotlin.String;dev.kord.voice.gateway.SelectProtocol.Data){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SelectProtocol.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/SelectProtocol.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/SelectProtocol.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/SelectProtocol // dev.kord.voice.gateway/SelectProtocol.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/SelectProtocol) // dev.kord.voice.gateway/SelectProtocol.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.SelectProtocol){}[0] + final val descriptor // dev.kord.voice.gateway/SelectProtocol.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SelectProtocol.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/SelectProtocol.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SelectProtocol.Companion.serializer|serializer(){}[0] + } + final val data // dev.kord.voice.gateway/SelectProtocol.data|{}data[0] + final fun (): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.data.|(){}[0] + final val protocol // dev.kord.voice.gateway/SelectProtocol.protocol|{}protocol[0] + final fun (): kotlin/String // dev.kord.voice.gateway/SelectProtocol.protocol.|(){}[0] +} +final class dev.kord.voice.gateway/SendSpeaking : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/SendSpeaking|null[0] + constructor (dev.kord.voice/SpeakingFlags, kotlin/Int, kotlin/UInt) // dev.kord.voice.gateway/SendSpeaking.|(dev.kord.voice.SpeakingFlags;kotlin.Int;kotlin.UInt){}[0] + final fun component1(): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/SendSpeaking.component1|component1(){}[0] + final fun component2(): kotlin/Int // dev.kord.voice.gateway/SendSpeaking.component2|component2(){}[0] + final fun component3(): kotlin/UInt // dev.kord.voice.gateway/SendSpeaking.component3|component3(){}[0] + final fun copy(dev.kord.voice/SpeakingFlags =..., kotlin/Int =..., kotlin/UInt =...): dev.kord.voice.gateway/SendSpeaking // dev.kord.voice.gateway/SendSpeaking.copy|copy(dev.kord.voice.SpeakingFlags;kotlin.Int;kotlin.UInt){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SendSpeaking.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SendSpeaking.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/SendSpeaking.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/SendSpeaking.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/SendSpeaking.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/SendSpeaking // dev.kord.voice.gateway/SendSpeaking.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/SendSpeaking) // dev.kord.voice.gateway/SendSpeaking.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.SendSpeaking){}[0] + final val descriptor // dev.kord.voice.gateway/SendSpeaking.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SendSpeaking.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/SendSpeaking.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SendSpeaking.Companion.serializer|serializer(){}[0] + } + final val delay // dev.kord.voice.gateway/SendSpeaking.delay|{}delay[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/SendSpeaking.delay.|(){}[0] + final val speaking // dev.kord.voice.gateway/SendSpeaking.speaking|{}speaking[0] + final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/SendSpeaking.speaking.|(){}[0] + final val ssrc // dev.kord.voice.gateway/SendSpeaking.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.gateway/SendSpeaking.ssrc.|(){}[0] +} +final class dev.kord.voice.gateway/SessionDescription : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/SessionDescription|null[0] + constructor (dev.kord.voice/EncryptionMode, kotlin.collections/List) // dev.kord.voice.gateway/SessionDescription.|(dev.kord.voice.EncryptionMode;kotlin.collections.List){}[0] + final fun component1(): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SessionDescription.component1|component1(){}[0] + final fun component2(): kotlin.collections/List // dev.kord.voice.gateway/SessionDescription.component2|component2(){}[0] + final fun copy(dev.kord.voice/EncryptionMode =..., kotlin.collections/List =...): dev.kord.voice.gateway/SessionDescription // dev.kord.voice.gateway/SessionDescription.copy|copy(dev.kord.voice.EncryptionMode;kotlin.collections.List){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SessionDescription.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SessionDescription.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/SessionDescription.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/SessionDescription.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/SessionDescription.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/SessionDescription // dev.kord.voice.gateway/SessionDescription.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/SessionDescription) // dev.kord.voice.gateway/SessionDescription.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.SessionDescription){}[0] + final val descriptor // dev.kord.voice.gateway/SessionDescription.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SessionDescription.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/SessionDescription.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SessionDescription.Companion.serializer|serializer(){}[0] + final val $childSerializers // dev.kord.voice.gateway/SessionDescription.Companion.$childSerializers|{}$childSerializers[0] + } + final val mode // dev.kord.voice.gateway/SessionDescription.mode|{}mode[0] + final fun (): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SessionDescription.mode.|(){}[0] + final val secretKey // dev.kord.voice.gateway/SessionDescription.secretKey|{}secretKey[0] + final fun (): kotlin.collections/List // dev.kord.voice.gateway/SessionDescription.secretKey.|(){}[0] +} +final class dev.kord.voice.gateway/Speaking : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Speaking|null[0] + constructor (dev.kord.common.entity/Snowflake, kotlin/UInt, dev.kord.voice/SpeakingFlags) // dev.kord.voice.gateway/Speaking.|(dev.kord.common.entity.Snowflake;kotlin.UInt;dev.kord.voice.SpeakingFlags){}[0] + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Speaking.component1|component1(){}[0] + final fun component2(): kotlin/UInt // dev.kord.voice.gateway/Speaking.component2|component2(){}[0] + final fun component3(): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/Speaking.component3|component3(){}[0] + final fun copy(dev.kord.common.entity/Snowflake =..., kotlin/UInt =..., dev.kord.voice/SpeakingFlags =...): dev.kord.voice.gateway/Speaking // dev.kord.voice.gateway/Speaking.copy|copy(dev.kord.common.entity.Snowflake;kotlin.UInt;dev.kord.voice.SpeakingFlags){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Speaking.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Speaking.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/Speaking.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Speaking.$serializer|null[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Speaking.$serializer.childSerializers|childSerializers(){}[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Speaking // dev.kord.voice.gateway/Speaking.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Speaking) // dev.kord.voice.gateway/Speaking.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Speaking){}[0] + final val descriptor // dev.kord.voice.gateway/Speaking.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Speaking.$serializer.descriptor.|(){}[0] + } + final object Companion { // dev.kord.voice.gateway/Speaking.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Speaking.Companion.serializer|serializer(){}[0] + } + final val speaking // dev.kord.voice.gateway/Speaking.speaking|{}speaking[0] + final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/Speaking.speaking.|(){}[0] + final val ssrc // dev.kord.voice.gateway/Speaking.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.gateway/Speaking.ssrc.|(){}[0] + final val userId // dev.kord.voice.gateway/Speaking.userId|{}userId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Speaking.userId.|(){}[0] +} +final class dev.kord.voice.gateway/VoiceGatewayConfiguration { // dev.kord.voice.gateway/VoiceGatewayConfiguration|null[0] + constructor (kotlin/String, kotlin/String) // dev.kord.voice.gateway/VoiceGatewayConfiguration.|(kotlin.String;kotlin.String){}[0] + final fun component1(): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.component1|component1(){}[0] + final fun component2(): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.component2|component2(){}[0] + final fun copy(kotlin/String =..., kotlin/String =...): dev.kord.voice.gateway/VoiceGatewayConfiguration // dev.kord.voice.gateway/VoiceGatewayConfiguration.copy|copy(kotlin.String;kotlin.String){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/VoiceGatewayConfiguration.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/VoiceGatewayConfiguration.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.toString|toString(){}[0] + final val endpoint // dev.kord.voice.gateway/VoiceGatewayConfiguration.endpoint|{}endpoint[0] + final fun (): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.endpoint.|(){}[0] + final val token // dev.kord.voice.gateway/VoiceGatewayConfiguration.token|{}token[0] + final fun (): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.token.|(){}[0] +} +final class dev.kord.voice.io/ByteArrayView : kotlin.collections/Iterable { // dev.kord.voice.io/ByteArrayView|null[0] + final fun asInt(): kotlin/Int // dev.kord.voice.io/ByteArrayView.asInt|asInt(){}[0] + final fun asShort(): kotlin/Short // dev.kord.voice.io/ByteArrayView.asShort|asShort(){}[0] + final fun clone(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ByteArrayView.clone|clone(){}[0] + final fun get(kotlin/Int): kotlin/Byte // dev.kord.voice.io/ByteArrayView.get|get(kotlin.Int){}[0] + final fun iterator(): kotlin.collections/Iterator // dev.kord.voice.io/ByteArrayView.iterator|iterator(){}[0] + final fun resize(kotlin/Int =..., kotlin/Int =...): kotlin/Boolean // dev.kord.voice.io/ByteArrayView.resize|resize(kotlin.Int;kotlin.Int){}[0] + final fun toByteArray(): kotlin/ByteArray // dev.kord.voice.io/ByteArrayView.toByteArray|toByteArray(){}[0] + final fun view(kotlin/Int =..., kotlin/Int =...): dev.kord.voice.io/ByteArrayView? // dev.kord.voice.io/ByteArrayView.view|view(kotlin.Int;kotlin.Int){}[0] + final object Companion { // dev.kord.voice.io/ByteArrayView.Companion|null[0] + final fun from(kotlin/ByteArray, kotlin/Int, kotlin/Int): dev.kord.voice.io/ByteArrayView? // dev.kord.voice.io/ByteArrayView.Companion.from|from(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0] + } + final val data // dev.kord.voice.io/ByteArrayView.data|{}data[0] + final fun (): kotlin/ByteArray // dev.kord.voice.io/ByteArrayView.data.|(){}[0] + final val viewSize // dev.kord.voice.io/ByteArrayView.viewSize|{}viewSize[0] + final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.viewSize.|(){}[0] + final var dataEnd // dev.kord.voice.io/ByteArrayView.dataEnd|{}dataEnd[0] + final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.dataEnd.|(){}[0] + final var dataStart // dev.kord.voice.io/ByteArrayView.dataStart|{}dataStart[0] + final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.dataStart.|(){}[0] +} +final class dev.kord.voice.io/MutableByteArrayCursor { // dev.kord.voice.io/MutableByteArrayCursor|null[0] + constructor (kotlin/ByteArray) // dev.kord.voice.io/MutableByteArrayCursor.|(kotlin.ByteArray){}[0] + final fun reset() // dev.kord.voice.io/MutableByteArrayCursor.reset|reset(){}[0] + final fun resize(kotlin/Int, kotlin/Boolean =...): kotlin/Boolean // dev.kord.voice.io/MutableByteArrayCursor.resize|resize(kotlin.Int;kotlin.Boolean){}[0] + final fun writeByte(kotlin/Byte) // dev.kord.voice.io/MutableByteArrayCursor.writeByte|writeByte(kotlin.Byte){}[0] + final fun writeByteArray(kotlin/ByteArray, kotlin/Int =..., kotlin/Int =...) // dev.kord.voice.io/MutableByteArrayCursor.writeByteArray|writeByteArray(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0] + final fun writeByteView(dev.kord.voice.io/ByteArrayView) // dev.kord.voice.io/MutableByteArrayCursor.writeByteView|writeByteView(dev.kord.voice.io.ByteArrayView){}[0] + final fun writeInt(kotlin/Int) // dev.kord.voice.io/MutableByteArrayCursor.writeInt|writeInt(kotlin.Int){}[0] + final fun writeShort(kotlin/Short) // dev.kord.voice.io/MutableByteArrayCursor.writeShort|writeShort(kotlin.Short){}[0] + final val isExhausted // dev.kord.voice.io/MutableByteArrayCursor.isExhausted|{}isExhausted[0] + final fun (): kotlin/Boolean // dev.kord.voice.io/MutableByteArrayCursor.isExhausted.|(){}[0] + final val remaining // dev.kord.voice.io/MutableByteArrayCursor.remaining|{}remaining[0] + final fun (): kotlin/Int // dev.kord.voice.io/MutableByteArrayCursor.remaining.|(){}[0] + final var cursor // dev.kord.voice.io/MutableByteArrayCursor.cursor|{}cursor[0] + final fun (): kotlin/Int // dev.kord.voice.io/MutableByteArrayCursor.cursor.|(){}[0] + final fun (kotlin/Int) // dev.kord.voice.io/MutableByteArrayCursor.cursor.|(kotlin.Int){}[0] + final var data // dev.kord.voice.io/MutableByteArrayCursor.data|{}data[0] + final fun (): kotlin/ByteArray // dev.kord.voice.io/MutableByteArrayCursor.data.|(){}[0] +} +final class dev.kord.voice.io/ReadableByteArrayCursor { // dev.kord.voice.io/ReadableByteArrayCursor|null[0] + constructor (dev.kord.voice.io/ByteArrayView) // dev.kord.voice.io/ReadableByteArrayCursor.|(dev.kord.voice.io.ByteArrayView){}[0] + final fun consume(kotlin/Int) // dev.kord.voice.io/ReadableByteArrayCursor.consume|consume(kotlin.Int){}[0] + final fun readByte(): kotlin/Byte // dev.kord.voice.io/ReadableByteArrayCursor.readByte|readByte(){}[0] + final fun readBytes(kotlin/Int): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ReadableByteArrayCursor.readBytes|readBytes(kotlin.Int){}[0] + final fun readInt(): kotlin/Int // dev.kord.voice.io/ReadableByteArrayCursor.readInt|readInt(){}[0] + final fun readRemaining(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ReadableByteArrayCursor.readRemaining|readRemaining(){}[0] + final fun readShort(): kotlin/Short // dev.kord.voice.io/ReadableByteArrayCursor.readShort|readShort(){}[0] + final val remaining // dev.kord.voice.io/ReadableByteArrayCursor.remaining|{}remaining[0] + final fun (): kotlin/Int // dev.kord.voice.io/ReadableByteArrayCursor.remaining.|(){}[0] + final val view // dev.kord.voice.io/ReadableByteArrayCursor.view|{}view[0] + final fun (): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ReadableByteArrayCursor.view.|(){}[0] + final var cursor // dev.kord.voice.io/ReadableByteArrayCursor.cursor|{}cursor[0] + final fun (): kotlin/Int // dev.kord.voice.io/ReadableByteArrayCursor.cursor.|(){}[0] + final fun (kotlin/Int) // dev.kord.voice.io/ReadableByteArrayCursor.cursor.|(kotlin.Int){}[0] +} +final class dev.kord.voice.streams/DefaultStreams : dev.kord.voice.streams/Streams { // dev.kord.voice.streams/DefaultStreams|null[0] + constructor (dev.kord.voice.gateway/VoiceGateway, dev.kord.voice.udp/VoiceUdpSocket, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.streams/DefaultStreams.|(dev.kord.voice.gateway.VoiceGateway;dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] + final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/DefaultStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] + final val incomingAudioFrames // dev.kord.voice.streams/DefaultStreams.incomingAudioFrames|(){}[0] + final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/DefaultStreams.incomingAudioFrames.|(){}[0] + final val incomingAudioPackets // dev.kord.voice.streams/DefaultStreams.incomingAudioPackets|{}incomingAudioPackets[0] + final fun (): kotlinx.coroutines.flow/SharedFlow // dev.kord.voice.streams/DefaultStreams.incomingAudioPackets.|(){}[0] + final val incomingUserStreams // dev.kord.voice.streams/DefaultStreams.incomingUserStreams|{}incomingUserStreams[0] + final fun (): kotlinx.coroutines.flow/SharedFlow> // dev.kord.voice.streams/DefaultStreams.incomingUserStreams.|(){}[0] + final val ssrcToUser // dev.kord.voice.streams/DefaultStreams.ssrcToUser|{}ssrcToUser[0] + final fun (): kotlin.collections/Map // dev.kord.voice.streams/DefaultStreams.ssrcToUser.|(){}[0] +} +final class dev.kord.voice.udp/AudioFrameSenderConfiguration { // dev.kord.voice.udp/AudioFrameSenderConfiguration|null[0] + constructor (dev.kord.voice.udp/SocketAddress, kotlin/UInt, kotlin/ByteArray, dev.kord.voice/FrameInterceptorConfiguration) // dev.kord.voice.udp/AudioFrameSenderConfiguration.|(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + final fun component1(): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.component1|component1(){}[0] + final fun component2(): kotlin/UInt // dev.kord.voice.udp/AudioFrameSenderConfiguration.component2|component2(){}[0] + final fun component3(): kotlin/ByteArray // dev.kord.voice.udp/AudioFrameSenderConfiguration.component3|component3(){}[0] + final fun component4(): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.component4|component4(){}[0] + final fun copy(dev.kord.voice.udp/SocketAddress =..., kotlin/UInt =..., kotlin/ByteArray =..., dev.kord.voice/FrameInterceptorConfiguration =...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/AudioFrameSenderConfiguration.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.udp/AudioFrameSenderConfiguration.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/AudioFrameSenderConfiguration.toString|toString(){}[0] + final val interceptorConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.interceptorConfiguration|{}interceptorConfiguration[0] + final fun (): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.interceptorConfiguration.|(){}[0] + final val key // dev.kord.voice.udp/AudioFrameSenderConfiguration.key|{}key[0] + final fun (): kotlin/ByteArray // dev.kord.voice.udp/AudioFrameSenderConfiguration.key.|(){}[0] + final val server // dev.kord.voice.udp/AudioFrameSenderConfiguration.server|{}server[0] + final fun (): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.server.|(){}[0] + final val ssrc // dev.kord.voice.udp/AudioFrameSenderConfiguration.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.udp/AudioFrameSenderConfiguration.ssrc.|(){}[0] +} +final class dev.kord.voice.udp/DefaultAudioFrameSender : dev.kord.voice.udp/AudioFrameSender { // dev.kord.voice.udp/DefaultAudioFrameSender|null[0] + constructor (dev.kord.voice.udp/DefaultAudioFrameSenderData) // dev.kord.voice.udp/DefaultAudioFrameSender.|(dev.kord.voice.udp.DefaultAudioFrameSenderData){}[0] + final suspend fun start(dev.kord.voice.udp/AudioFrameSenderConfiguration) // dev.kord.voice.udp/DefaultAudioFrameSender.start|start(dev.kord.voice.udp.AudioFrameSenderConfiguration){}[0] + final val data // dev.kord.voice.udp/DefaultAudioFrameSender.data|{}data[0] + final fun (): dev.kord.voice.udp/DefaultAudioFrameSenderData // dev.kord.voice.udp/DefaultAudioFrameSender.data.|(){}[0] +} +final class dev.kord.voice.udp/DefaultAudioFrameSenderData { // dev.kord.voice.udp/DefaultAudioFrameSenderData|null[0] + constructor (dev.kord.voice.udp/VoiceUdpSocket, dev.kord.voice/FrameInterceptor, dev.kord.voice/AudioProvider, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.udp/DefaultAudioFrameSenderData.|(dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.FrameInterceptor;dev.kord.voice.AudioProvider;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] + final fun component1(): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/DefaultAudioFrameSenderData.component1|component1(){}[0] + final fun component2(): dev.kord.voice/FrameInterceptor // dev.kord.voice.udp/DefaultAudioFrameSenderData.component2|component2(){}[0] + final fun component3(): dev.kord.voice/AudioProvider // dev.kord.voice.udp/DefaultAudioFrameSenderData.component3|component3(){}[0] + final fun component4(): dev.kord.voice.encryption.strategies/NonceStrategy // dev.kord.voice.udp/DefaultAudioFrameSenderData.component4|component4(){}[0] + final fun copy(dev.kord.voice.udp/VoiceUdpSocket =..., dev.kord.voice/FrameInterceptor =..., dev.kord.voice/AudioProvider =..., dev.kord.voice.encryption.strategies/NonceStrategy =...): dev.kord.voice.udp/DefaultAudioFrameSenderData // dev.kord.voice.udp/DefaultAudioFrameSenderData.copy|copy(dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.FrameInterceptor;dev.kord.voice.AudioProvider;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/DefaultAudioFrameSenderData.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.udp/DefaultAudioFrameSenderData.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/DefaultAudioFrameSenderData.toString|toString(){}[0] + final val interceptor // dev.kord.voice.udp/DefaultAudioFrameSenderData.interceptor|{}interceptor[0] + final fun (): dev.kord.voice/FrameInterceptor // dev.kord.voice.udp/DefaultAudioFrameSenderData.interceptor.|(){}[0] + final val nonceStrategy // dev.kord.voice.udp/DefaultAudioFrameSenderData.nonceStrategy|{}nonceStrategy[0] + final fun (): dev.kord.voice.encryption.strategies/NonceStrategy // dev.kord.voice.udp/DefaultAudioFrameSenderData.nonceStrategy.|(){}[0] + final val provider // dev.kord.voice.udp/DefaultAudioFrameSenderData.provider|{}provider[0] + final fun (): dev.kord.voice/AudioProvider // dev.kord.voice.udp/DefaultAudioFrameSenderData.provider.|(){}[0] + final val udp // dev.kord.voice.udp/DefaultAudioFrameSenderData.udp|{}udp[0] + final fun (): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/DefaultAudioFrameSenderData.udp.|(){}[0] +} +final class dev.kord.voice.udp/DefaultNativeAudioPacketProvider : dev.kord.voice.udp/AudioPacketProvider { // dev.kord.voice.udp/DefaultNativeAudioPacketProvider|null[0] + constructor (kotlin/ByteArray, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.udp/DefaultNativeAudioPacketProvider.|(kotlin.ByteArray;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] + final fun provide(kotlin/UShort, kotlin/UInt, kotlin/UInt, kotlin/ByteArray): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/DefaultNativeAudioPacketProvider.provide|provide(kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.ByteArray){}[0] +} +final class dev.kord.voice.udp/RTPPacket { // dev.kord.voice.udp/RTPPacket|null[0] + constructor (kotlin/UByte, kotlin/Byte, kotlin/UShort, kotlin/UInt, kotlin/UInt, kotlin/UIntArray, kotlin/Boolean, kotlin/Boolean, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/RTPPacket.|(kotlin.UByte;kotlin.Byte;kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.UIntArray;kotlin.Boolean;kotlin.Boolean;dev.kord.voice.io.ByteArrayView){}[0] + final class Builder { // dev.kord.voice.udp/RTPPacket.Builder|null[0] + constructor (kotlin/UInt, kotlin/UInt, kotlin/UShort, kotlin/Byte, kotlin/ByteArray) // dev.kord.voice.udp/RTPPacket.Builder.|(kotlin.UInt;kotlin.UInt;kotlin.UShort;kotlin.Byte;kotlin.ByteArray){}[0] + final fun build(): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.Builder.build|build(){}[0] + final var csrcIdentifiers // dev.kord.voice.udp/RTPPacket.Builder.csrcIdentifiers|{}csrcIdentifiers[0] + final fun (): kotlin/UIntArray // dev.kord.voice.udp/RTPPacket.Builder.csrcIdentifiers.|(){}[0] + final fun (kotlin/UIntArray) // dev.kord.voice.udp/RTPPacket.Builder.csrcIdentifiers.|(kotlin.UIntArray){}[0] + final var hasExtension // dev.kord.voice.udp/RTPPacket.Builder.hasExtension|{}hasExtension[0] + final fun (): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.Builder.hasExtension.|(){}[0] + final fun (kotlin/Boolean) // dev.kord.voice.udp/RTPPacket.Builder.hasExtension.|(kotlin.Boolean){}[0] + final var marker // dev.kord.voice.udp/RTPPacket.Builder.marker|{}marker[0] + final fun (): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.Builder.marker.|(){}[0] + final fun (kotlin/Boolean) // dev.kord.voice.udp/RTPPacket.Builder.marker.|(kotlin.Boolean){}[0] + final var paddingBytes // dev.kord.voice.udp/RTPPacket.Builder.paddingBytes|{}paddingBytes[0] + final fun (): kotlin/UByte // dev.kord.voice.udp/RTPPacket.Builder.paddingBytes.|(){}[0] + final fun (kotlin/UByte) // dev.kord.voice.udp/RTPPacket.Builder.paddingBytes.|(kotlin.UByte){}[0] + final var payload // dev.kord.voice.udp/RTPPacket.Builder.payload|{}payload[0] + final fun (): kotlin/ByteArray // dev.kord.voice.udp/RTPPacket.Builder.payload.|(){}[0] + final fun (kotlin/ByteArray) // dev.kord.voice.udp/RTPPacket.Builder.payload.|(kotlin.ByteArray){}[0] + final var payloadType // dev.kord.voice.udp/RTPPacket.Builder.payloadType|{}payloadType[0] + final fun (): kotlin/Byte // dev.kord.voice.udp/RTPPacket.Builder.payloadType.|(){}[0] + final fun (kotlin/Byte) // dev.kord.voice.udp/RTPPacket.Builder.payloadType.|(kotlin.Byte){}[0] + final var sequence // dev.kord.voice.udp/RTPPacket.Builder.sequence|{}sequence[0] + final fun (): kotlin/UShort // dev.kord.voice.udp/RTPPacket.Builder.sequence.|(){}[0] + final fun (kotlin/UShort) // dev.kord.voice.udp/RTPPacket.Builder.sequence.|(kotlin.UShort){}[0] + final var ssrc // dev.kord.voice.udp/RTPPacket.Builder.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.Builder.ssrc.|(){}[0] + final fun (kotlin/UInt) // dev.kord.voice.udp/RTPPacket.Builder.ssrc.|(kotlin.UInt){}[0] + final var timestamp // dev.kord.voice.udp/RTPPacket.Builder.timestamp|{}timestamp[0] + final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.Builder.timestamp.|(){}[0] + final fun (kotlin/UInt) // dev.kord.voice.udp/RTPPacket.Builder.timestamp.|(kotlin.UInt){}[0] + } + final fun asByteArray(): kotlin/ByteArray // dev.kord.voice.udp/RTPPacket.asByteArray|asByteArray(){}[0] + final fun asByteArrayView(dev.kord.voice.io/MutableByteArrayCursor): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.asByteArrayView|asByteArrayView(dev.kord.voice.io.MutableByteArrayCursor){}[0] + final fun clone(): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.clone|clone(){}[0] + final fun component1(): kotlin/UByte // dev.kord.voice.udp/RTPPacket.component1|component1(){}[0] + final fun component2(): kotlin/Byte // dev.kord.voice.udp/RTPPacket.component2|component2(){}[0] + final fun component3(): kotlin/UShort // dev.kord.voice.udp/RTPPacket.component3|component3(){}[0] + final fun component4(): kotlin/UInt // dev.kord.voice.udp/RTPPacket.component4|component4(){}[0] + final fun component5(): kotlin/UInt // dev.kord.voice.udp/RTPPacket.component5|component5(){}[0] + final fun component6(): kotlin/UIntArray // dev.kord.voice.udp/RTPPacket.component6|component6(){}[0] + final fun component7(): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.component7|component7(){}[0] + final fun component8(): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.component8|component8(){}[0] + final fun component9(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.component9|component9(){}[0] + final fun copy(kotlin/UByte =..., kotlin/Byte =..., kotlin/UShort =..., kotlin/UInt =..., kotlin/UInt =..., kotlin/UIntArray =..., kotlin/Boolean =..., kotlin/Boolean =..., dev.kord.voice.io/ByteArrayView =...): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.copy|copy(kotlin.UByte;kotlin.Byte;kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.UIntArray;kotlin.Boolean;kotlin.Boolean;dev.kord.voice.io.ByteArrayView){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.udp/RTPPacket.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/RTPPacket.toString|toString(){}[0] + final fun writeHeader(): kotlin/ByteArray // dev.kord.voice.udp/RTPPacket.writeHeader|writeHeader(){}[0] + final fun writeHeader(dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.udp/RTPPacket.writeHeader|writeHeader(dev.kord.voice.io.MutableByteArrayCursor){}[0] + final object Companion { // dev.kord.voice.udp/RTPPacket.Companion|null[0] + final fun fromPacket(io.ktor.utils.io.core/ByteReadPacket): dev.kord.voice.udp/RTPPacket? // dev.kord.voice.udp/RTPPacket.Companion.fromPacket|fromPacket(io.ktor.utils.io.core.ByteReadPacket){}[0] + } + final val csrcIdentifiers // dev.kord.voice.udp/RTPPacket.csrcIdentifiers|{}csrcIdentifiers[0] + final fun (): kotlin/UIntArray // dev.kord.voice.udp/RTPPacket.csrcIdentifiers.|(){}[0] + final val hasExtension // dev.kord.voice.udp/RTPPacket.hasExtension|{}hasExtension[0] + final fun (): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.hasExtension.|(){}[0] + final val hasMarker // dev.kord.voice.udp/RTPPacket.hasMarker|{}hasMarker[0] + final fun (): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.hasMarker.|(){}[0] + final val paddingBytes // dev.kord.voice.udp/RTPPacket.paddingBytes|{}paddingBytes[0] + final fun (): kotlin/UByte // dev.kord.voice.udp/RTPPacket.paddingBytes.|(){}[0] + final val payload // dev.kord.voice.udp/RTPPacket.payload|{}payload[0] + final fun (): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.payload.|(){}[0] + final val payloadType // dev.kord.voice.udp/RTPPacket.payloadType|{}payloadType[0] + final fun (): kotlin/Byte // dev.kord.voice.udp/RTPPacket.payloadType.|(){}[0] + final val sequence // dev.kord.voice.udp/RTPPacket.sequence|{}sequence[0] + final fun (): kotlin/UShort // dev.kord.voice.udp/RTPPacket.sequence.|(){}[0] + final val ssrc // dev.kord.voice.udp/RTPPacket.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.ssrc.|(){}[0] + final val timestamp // dev.kord.voice.udp/RTPPacket.timestamp|{}timestamp[0] + final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.timestamp.|(){}[0] +} +final class dev.kord.voice.udp/SocketAddress { // dev.kord.voice.udp/SocketAddress|null[0] + constructor (kotlin/String, kotlin/Int) // dev.kord.voice.udp/SocketAddress.|(kotlin.String;kotlin.Int){}[0] + final fun component1(): kotlin/String // dev.kord.voice.udp/SocketAddress.component1|component1(){}[0] + final fun component2(): kotlin/Int // dev.kord.voice.udp/SocketAddress.component2|component2(){}[0] + final fun copy(kotlin/String =..., kotlin/Int =...): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/SocketAddress.copy|copy(kotlin.String;kotlin.Int){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/SocketAddress.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.udp/SocketAddress.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/SocketAddress.toString|toString(){}[0] + final val hostname // dev.kord.voice.udp/SocketAddress.hostname|{}hostname[0] + final fun (): kotlin/String // dev.kord.voice.udp/SocketAddress.hostname.|(){}[0] + final val port // dev.kord.voice.udp/SocketAddress.port|{}port[0] + final fun (): kotlin/Int // dev.kord.voice.udp/SocketAddress.port.|(){}[0] +} +final class dev.kord.voice/DefaultFrameInterceptor : dev.kord.voice/FrameInterceptor { // dev.kord.voice/DefaultFrameInterceptor|null[0] + constructor (dev.kord.voice/DefaultFrameInterceptorData =...) // dev.kord.voice/DefaultFrameInterceptor.|(dev.kord.voice.DefaultFrameInterceptorData){}[0] + final fun (kotlinx.coroutines.flow/Flow).intercept(dev.kord.voice/FrameInterceptorConfiguration): kotlinx.coroutines.flow/Flow // dev.kord.voice/DefaultFrameInterceptor.intercept|intercept@kotlinx.coroutines.flow.Flow(dev.kord.voice.FrameInterceptorConfiguration){}[0] +} +final class dev.kord.voice/DefaultFrameInterceptorData { // dev.kord.voice/DefaultFrameInterceptorData|null[0] + constructor (dev.kord.voice/SpeakingFlags =...) // dev.kord.voice/DefaultFrameInterceptorData.|(dev.kord.voice.SpeakingFlags){}[0] + final fun component1(): dev.kord.voice/SpeakingFlags // dev.kord.voice/DefaultFrameInterceptorData.component1|component1(){}[0] + final fun copy(dev.kord.voice/SpeakingFlags =...): dev.kord.voice/DefaultFrameInterceptorData // dev.kord.voice/DefaultFrameInterceptorData.copy|copy(dev.kord.voice.SpeakingFlags){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/DefaultFrameInterceptorData.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/DefaultFrameInterceptorData.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice/DefaultFrameInterceptorData.toString|toString(){}[0] + final val speakingState // dev.kord.voice/DefaultFrameInterceptorData.speakingState|{}speakingState[0] + final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice/DefaultFrameInterceptorData.speakingState.|(){}[0] +} +final class dev.kord.voice/FrameInterceptorConfiguration { // dev.kord.voice/FrameInterceptorConfiguration|null[0] + constructor (dev.kord.gateway/Gateway, dev.kord.voice.gateway/VoiceGateway, kotlin/UInt) // dev.kord.voice/FrameInterceptorConfiguration.|(dev.kord.gateway.Gateway;dev.kord.voice.gateway.VoiceGateway;kotlin.UInt){}[0] + final fun component1(): dev.kord.gateway/Gateway // dev.kord.voice/FrameInterceptorConfiguration.component1|component1(){}[0] + final fun component2(): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice/FrameInterceptorConfiguration.component2|component2(){}[0] + final fun component3(): kotlin/UInt // dev.kord.voice/FrameInterceptorConfiguration.component3|component3(){}[0] + final fun copy(dev.kord.gateway/Gateway =..., dev.kord.voice.gateway/VoiceGateway =..., kotlin/UInt =...): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice/FrameInterceptorConfiguration.copy|copy(dev.kord.gateway.Gateway;dev.kord.voice.gateway.VoiceGateway;kotlin.UInt){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/FrameInterceptorConfiguration.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/FrameInterceptorConfiguration.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice/FrameInterceptorConfiguration.toString|toString(){}[0] + final val gateway // dev.kord.voice/FrameInterceptorConfiguration.gateway|{}gateway[0] + final fun (): dev.kord.gateway/Gateway // dev.kord.voice/FrameInterceptorConfiguration.gateway.|(){}[0] + final val ssrc // dev.kord.voice/FrameInterceptorConfiguration.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice/FrameInterceptorConfiguration.ssrc.|(){}[0] + final val voiceGateway // dev.kord.voice/FrameInterceptorConfiguration.voiceGateway|{}voiceGateway[0] + final fun (): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice/FrameInterceptorConfiguration.voiceGateway.|(){}[0] +} +final class dev.kord.voice/SpeakingFlags { // dev.kord.voice/SpeakingFlags|null[0] + final class Builder { // dev.kord.voice/SpeakingFlags.Builder|null[0] + constructor (kotlin/Int =...) // dev.kord.voice/SpeakingFlags.Builder.|(kotlin.Int){}[0] + final fun (dev.kord.voice/SpeakingFlag).unaryMinus() // dev.kord.voice/SpeakingFlags.Builder.unaryMinus|unaryMinus@dev.kord.voice.SpeakingFlag(){}[0] + final fun (dev.kord.voice/SpeakingFlag).unaryPlus() // dev.kord.voice/SpeakingFlags.Builder.unaryPlus|unaryPlus@dev.kord.voice.SpeakingFlag(){}[0] + final fun (dev.kord.voice/SpeakingFlags).unaryMinus() // dev.kord.voice/SpeakingFlags.Builder.unaryMinus|unaryMinus@dev.kord.voice.SpeakingFlags(){}[0] + final fun (dev.kord.voice/SpeakingFlags).unaryPlus() // dev.kord.voice/SpeakingFlags.Builder.unaryPlus|unaryPlus@dev.kord.voice.SpeakingFlags(){}[0] + final fun build(): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.Builder.build|build(){}[0] + } + final fun contains(dev.kord.voice/SpeakingFlag): kotlin/Boolean // dev.kord.voice/SpeakingFlags.contains|contains(dev.kord.voice.SpeakingFlag){}[0] + final fun contains(dev.kord.voice/SpeakingFlags): kotlin/Boolean // dev.kord.voice/SpeakingFlags.contains|contains(dev.kord.voice.SpeakingFlags){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/SpeakingFlags.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/SpeakingFlags.hashCode|hashCode(){}[0] + final fun minus(dev.kord.voice/SpeakingFlag): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.minus|minus(dev.kord.voice.SpeakingFlag){}[0] + final fun minus(dev.kord.voice/SpeakingFlags): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.minus|minus(dev.kord.voice.SpeakingFlags){}[0] + final fun plus(dev.kord.voice/SpeakingFlag): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.plus|plus(dev.kord.voice.SpeakingFlag){}[0] + final fun plus(dev.kord.voice/SpeakingFlags): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.plus|plus(dev.kord.voice.SpeakingFlags){}[0] + final fun toString(): kotlin/String // dev.kord.voice/SpeakingFlags.toString|toString(){}[0] + final inline fun copy(kotlin/Function1): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.copy|copy(kotlin.Function1){}[0] + final object Companion { // dev.kord.voice/SpeakingFlags.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice/SpeakingFlags.Companion.serializer|serializer(){}[0] + } + final val code // dev.kord.voice/SpeakingFlags.code|(){}[0] + final fun (): kotlin/Int // dev.kord.voice/SpeakingFlags.code.|(){}[0] + final val values // dev.kord.voice/SpeakingFlags.values|{}values[0] + final fun (): kotlin.collections/Set // dev.kord.voice/SpeakingFlags.values.|(){}[0] +} +final class dev.kord.voice/VoiceConnection { // dev.kord.voice/VoiceConnection|null[0] + constructor (kotlinx.coroutines/CoroutineScope, dev.kord.voice/VoiceConnectionData, dev.kord.gateway/Gateway, dev.kord.voice.gateway/VoiceGateway, dev.kord.voice.udp/VoiceUdpSocket, dev.kord.voice.gateway/VoiceGatewayConfiguration, dev.kord.voice.streams/Streams, dev.kord.voice/AudioProvider, dev.kord.voice/FrameInterceptor, dev.kord.voice.udp/AudioFrameSender, dev.kord.voice.encryption.strategies/NonceStrategy, kotlin.time/Duration) // dev.kord.voice/VoiceConnection.|(kotlinx.coroutines.CoroutineScope;dev.kord.voice.VoiceConnectionData;dev.kord.gateway.Gateway;dev.kord.voice.gateway.VoiceGateway;dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.gateway.VoiceGatewayConfiguration;dev.kord.voice.streams.Streams;dev.kord.voice.AudioProvider;dev.kord.voice.FrameInterceptor;dev.kord.voice.udp.AudioFrameSender;dev.kord.voice.encryption.strategies.NonceStrategy;kotlin.time.Duration){}[0] + final suspend fun connect(kotlinx.coroutines/CoroutineScope =...) // dev.kord.voice/VoiceConnection.connect|connect(kotlinx.coroutines.CoroutineScope){}[0] + final suspend fun disconnect() // dev.kord.voice/VoiceConnection.disconnect|disconnect(){}[0] + final suspend fun leave() // dev.kord.voice/VoiceConnection.leave|leave(){}[0] + final suspend fun move(dev.kord.common.entity/Snowflake, kotlin/Boolean =..., kotlin/Boolean =...) // dev.kord.voice/VoiceConnection.move|move(dev.kord.common.entity.Snowflake;kotlin.Boolean;kotlin.Boolean){}[0] + final suspend fun shutdown() // dev.kord.voice/VoiceConnection.shutdown|shutdown(){}[0] + final val audioProvider // dev.kord.voice/VoiceConnection.audioProvider|{}audioProvider[0] + final fun (): dev.kord.voice/AudioProvider // dev.kord.voice/VoiceConnection.audioProvider.|(){}[0] + final val data // dev.kord.voice/VoiceConnection.data|{}data[0] + final fun (): dev.kord.voice/VoiceConnectionData // dev.kord.voice/VoiceConnection.data.|(){}[0] + final val frameInterceptor // dev.kord.voice/VoiceConnection.frameInterceptor|{}frameInterceptor[0] + final fun (): dev.kord.voice/FrameInterceptor // dev.kord.voice/VoiceConnection.frameInterceptor.|(){}[0] + final val frameSender // dev.kord.voice/VoiceConnection.frameSender|{}frameSender[0] + final fun (): dev.kord.voice.udp/AudioFrameSender // dev.kord.voice/VoiceConnection.frameSender.|(){}[0] + final val gateway // dev.kord.voice/VoiceConnection.gateway|{}gateway[0] + final fun (): dev.kord.gateway/Gateway // dev.kord.voice/VoiceConnection.gateway.|(){}[0] + final val nonceStrategy // dev.kord.voice/VoiceConnection.nonceStrategy|{}nonceStrategy[0] + final fun (): dev.kord.voice.encryption.strategies/NonceStrategy // dev.kord.voice/VoiceConnection.nonceStrategy.|(){}[0] + final val scope // dev.kord.voice/VoiceConnection.scope|{}scope[0] + final fun (): kotlinx.coroutines/CoroutineScope // dev.kord.voice/VoiceConnection.scope.|(){}[0] + final val socket // dev.kord.voice/VoiceConnection.socket|{}socket[0] + final fun (): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice/VoiceConnection.socket.|(){}[0] + final val streams // dev.kord.voice/VoiceConnection.streams|{}streams[0] + final fun (): dev.kord.voice.streams/Streams // dev.kord.voice/VoiceConnection.streams.|(){}[0] + final val voiceGateway // dev.kord.voice/VoiceConnection.voiceGateway|{}voiceGateway[0] + final fun (): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice/VoiceConnection.voiceGateway.|(){}[0] + final var voiceGatewayConfiguration // dev.kord.voice/VoiceConnection.voiceGatewayConfiguration|{}voiceGatewayConfiguration[0] + final fun (): dev.kord.voice.gateway/VoiceGatewayConfiguration // dev.kord.voice/VoiceConnection.voiceGatewayConfiguration.|(){}[0] + final fun (dev.kord.voice.gateway/VoiceGatewayConfiguration) // dev.kord.voice/VoiceConnection.voiceGatewayConfiguration.|(dev.kord.voice.gateway.VoiceGatewayConfiguration){}[0] +} +final class dev.kord.voice/VoiceConnectionBuilder { // dev.kord.voice/VoiceConnectionBuilder|null[0] + constructor (dev.kord.gateway/Gateway, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake) // dev.kord.voice/VoiceConnectionBuilder.|(dev.kord.gateway.Gateway;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake){}[0] + final fun audioProvider(dev.kord.voice/AudioProvider) // dev.kord.voice/VoiceConnectionBuilder.audioProvider|audioProvider(dev.kord.voice.AudioProvider){}[0] + final fun frameInterceptor(dev.kord.voice/FrameInterceptor) // dev.kord.voice/VoiceConnectionBuilder.frameInterceptor|frameInterceptor(dev.kord.voice.FrameInterceptor){}[0] + final fun voiceGateway(kotlin/Function1) // dev.kord.voice/VoiceConnectionBuilder.voiceGateway|voiceGateway(kotlin.Function1){}[0] + final suspend fun build(): dev.kord.voice/VoiceConnection // dev.kord.voice/VoiceConnectionBuilder.build|build(){}[0] + final var audioProvider // dev.kord.voice/VoiceConnectionBuilder.audioProvider|{}audioProvider[0] + final fun (): dev.kord.voice/AudioProvider? // dev.kord.voice/VoiceConnectionBuilder.audioProvider.|(){}[0] + final fun (dev.kord.voice/AudioProvider?) // dev.kord.voice/VoiceConnectionBuilder.audioProvider.|(dev.kord.voice.AudioProvider?){}[0] + final var audioSender // dev.kord.voice/VoiceConnectionBuilder.audioSender|{}audioSender[0] + final fun (): dev.kord.voice.udp/AudioFrameSender? // dev.kord.voice/VoiceConnectionBuilder.audioSender.|(){}[0] + final fun (dev.kord.voice.udp/AudioFrameSender?) // dev.kord.voice/VoiceConnectionBuilder.audioSender.|(dev.kord.voice.udp.AudioFrameSender?){}[0] + final var channelId // dev.kord.voice/VoiceConnectionBuilder.channelId|{}channelId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionBuilder.channelId.|(){}[0] + final fun (dev.kord.common.entity/Snowflake) // dev.kord.voice/VoiceConnectionBuilder.channelId.|(dev.kord.common.entity.Snowflake){}[0] + final var connectionDetachDuration // dev.kord.voice/VoiceConnectionBuilder.connectionDetachDuration|{}connectionDetachDuration[0] + final fun (): kotlin.time/Duration // dev.kord.voice/VoiceConnectionBuilder.connectionDetachDuration.|(){}[0] + final fun (kotlin.time/Duration) // dev.kord.voice/VoiceConnectionBuilder.connectionDetachDuration.|(kotlin.time.Duration){}[0] + final var dispatcher // dev.kord.voice/VoiceConnectionBuilder.dispatcher|{}dispatcher[0] + final fun (): kotlinx.coroutines/CoroutineDispatcher // dev.kord.voice/VoiceConnectionBuilder.dispatcher.|(){}[0] + final fun (kotlinx.coroutines/CoroutineDispatcher) // dev.kord.voice/VoiceConnectionBuilder.dispatcher.|(kotlinx.coroutines.CoroutineDispatcher){}[0] + final var frameInterceptor // dev.kord.voice/VoiceConnectionBuilder.frameInterceptor|{}frameInterceptor[0] + final fun (): dev.kord.voice/FrameInterceptor? // dev.kord.voice/VoiceConnectionBuilder.frameInterceptor.|(){}[0] + final fun (dev.kord.voice/FrameInterceptor?) // dev.kord.voice/VoiceConnectionBuilder.frameInterceptor.|(dev.kord.voice.FrameInterceptor?){}[0] + final var gateway // dev.kord.voice/VoiceConnectionBuilder.gateway|{}gateway[0] + final fun (): dev.kord.gateway/Gateway // dev.kord.voice/VoiceConnectionBuilder.gateway.|(){}[0] + final fun (dev.kord.gateway/Gateway) // dev.kord.voice/VoiceConnectionBuilder.gateway.|(dev.kord.gateway.Gateway){}[0] + final var guildId // dev.kord.voice/VoiceConnectionBuilder.guildId|{}guildId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionBuilder.guildId.|(){}[0] + final fun (dev.kord.common.entity/Snowflake) // dev.kord.voice/VoiceConnectionBuilder.guildId.|(dev.kord.common.entity.Snowflake){}[0] + final var nonceStrategy // dev.kord.voice/VoiceConnectionBuilder.nonceStrategy|{}nonceStrategy[0] + final fun (): dev.kord.voice.encryption.strategies/NonceStrategy? // dev.kord.voice/VoiceConnectionBuilder.nonceStrategy.|(){}[0] + final fun (dev.kord.voice.encryption.strategies/NonceStrategy?) // dev.kord.voice/VoiceConnectionBuilder.nonceStrategy.|(dev.kord.voice.encryption.strategies.NonceStrategy?){}[0] + final var receiveVoice // dev.kord.voice/VoiceConnectionBuilder.receiveVoice|{}receiveVoice[0] + final fun (): kotlin/Boolean // dev.kord.voice/VoiceConnectionBuilder.receiveVoice.|(){}[0] + final fun (kotlin/Boolean) // dev.kord.voice/VoiceConnectionBuilder.receiveVoice.|(kotlin.Boolean){}[0] + final var selfDeaf // dev.kord.voice/VoiceConnectionBuilder.selfDeaf|{}selfDeaf[0] + final fun (): kotlin/Boolean // dev.kord.voice/VoiceConnectionBuilder.selfDeaf.|(){}[0] + final fun (kotlin/Boolean) // dev.kord.voice/VoiceConnectionBuilder.selfDeaf.|(kotlin.Boolean){}[0] + final var selfId // dev.kord.voice/VoiceConnectionBuilder.selfId|{}selfId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionBuilder.selfId.|(){}[0] + final fun (dev.kord.common.entity/Snowflake) // dev.kord.voice/VoiceConnectionBuilder.selfId.|(dev.kord.common.entity.Snowflake){}[0] + final var selfMute // dev.kord.voice/VoiceConnectionBuilder.selfMute|{}selfMute[0] + final fun (): kotlin/Boolean // dev.kord.voice/VoiceConnectionBuilder.selfMute.|(){}[0] + final fun (kotlin/Boolean) // dev.kord.voice/VoiceConnectionBuilder.selfMute.|(kotlin.Boolean){}[0] + final var streams // dev.kord.voice/VoiceConnectionBuilder.streams|{}streams[0] + final fun (): dev.kord.voice.streams/Streams? // dev.kord.voice/VoiceConnectionBuilder.streams.|(){}[0] + final fun (dev.kord.voice.streams/Streams?) // dev.kord.voice/VoiceConnectionBuilder.streams.|(dev.kord.voice.streams.Streams?){}[0] + final var timeout // dev.kord.voice/VoiceConnectionBuilder.timeout|{}timeout[0] + final fun (): kotlin/Long // dev.kord.voice/VoiceConnectionBuilder.timeout.|(){}[0] + final fun (kotlin/Long) // dev.kord.voice/VoiceConnectionBuilder.timeout.|(kotlin.Long){}[0] + final var udpSocket // dev.kord.voice/VoiceConnectionBuilder.udpSocket|{}udpSocket[0] + final fun (): dev.kord.voice.udp/VoiceUdpSocket? // dev.kord.voice/VoiceConnectionBuilder.udpSocket.|(){}[0] + final fun (dev.kord.voice.udp/VoiceUdpSocket?) // dev.kord.voice/VoiceConnectionBuilder.udpSocket.|(dev.kord.voice.udp.VoiceUdpSocket?){}[0] +} +final class dev.kord.voice/VoiceConnectionData { // dev.kord.voice/VoiceConnectionData|null[0] + constructor (dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/String) // dev.kord.voice/VoiceConnectionData.|(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String){}[0] + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.component1|component1(){}[0] + final fun component2(): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.component2|component2(){}[0] + final fun component3(): kotlin/String // dev.kord.voice/VoiceConnectionData.component3|component3(){}[0] + final fun copy(dev.kord.common.entity/Snowflake =..., dev.kord.common.entity/Snowflake =..., kotlin/String =...): dev.kord.voice/VoiceConnectionData // dev.kord.voice/VoiceConnectionData.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/VoiceConnectionData.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/VoiceConnectionData.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice/VoiceConnectionData.toString|toString(){}[0] + final val guildId // dev.kord.voice/VoiceConnectionData.guildId|{}guildId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.guildId.|(){}[0] + final val selfId // dev.kord.voice/VoiceConnectionData.selfId|{}selfId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.selfId.|(){}[0] + final val sessionId // dev.kord.voice/VoiceConnectionData.sessionId|{}sessionId[0] + final fun (): kotlin/String // dev.kord.voice/VoiceConnectionData.sessionId.|(){}[0] +} +final enum class dev.kord.voice.gateway/OpCode : kotlin/Enum { // dev.kord.voice.gateway/OpCode|null[0] + enum entry ClientDisconnect // dev.kord.voice.gateway/OpCode.ClientDisconnect|null[0] + enum entry Heartbeat // dev.kord.voice.gateway/OpCode.Heartbeat|null[0] + enum entry HeartbeatAck // dev.kord.voice.gateway/OpCode.HeartbeatAck|null[0] + enum entry Hello // dev.kord.voice.gateway/OpCode.Hello|null[0] + enum entry Identify // dev.kord.voice.gateway/OpCode.Identify|null[0] + enum entry Ready // dev.kord.voice.gateway/OpCode.Ready|null[0] + enum entry Resume // dev.kord.voice.gateway/OpCode.Resume|null[0] + enum entry Resumed // dev.kord.voice.gateway/OpCode.Resumed|null[0] + enum entry SelectProtocol // dev.kord.voice.gateway/OpCode.SelectProtocol|null[0] + enum entry SessionDescription // dev.kord.voice.gateway/OpCode.SessionDescription|null[0] + enum entry Speaking // dev.kord.voice.gateway/OpCode.Speaking|null[0] + enum entry Unknown // dev.kord.voice.gateway/OpCode.Unknown|null[0] + final fun valueOf(kotlin/String): dev.kord.voice.gateway/OpCode // dev.kord.voice.gateway/OpCode.valueOf|valueOf#static(kotlin.String){}[0] + final fun values(): kotlin/Array // dev.kord.voice.gateway/OpCode.values|values#static(){}[0] + final object Companion : kotlinx.serialization.internal/SerializerFactory { // dev.kord.voice.gateway/OpCode.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/OpCode.Companion.serializer|serializer(){}[0] + final fun serializer(kotlin/Array>...): kotlinx.serialization/KSerializer<*> // dev.kord.voice.gateway/OpCode.Companion.serializer|serializer(kotlin.Array>...){}[0] + } + final val code // dev.kord.voice.gateway/OpCode.code|{}code[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/OpCode.code.|(){}[0] + final val entries // dev.kord.voice.gateway/OpCode.entries|#static(){}[0] + final fun (): kotlin.enums/EnumEntries // dev.kord.voice.gateway/OpCode.entries.|#static(){}[0] +} +final fun (dev.kord.voice.io/ByteArrayView).dev.kord.voice.io/mutableCursor(): dev.kord.voice.io/MutableByteArrayCursor // dev.kord.voice.io/mutableCursor|mutableCursor@dev.kord.voice.io.ByteArrayView(){}[0] +final fun (dev.kord.voice.io/ByteArrayView).dev.kord.voice.io/readableCursor(): dev.kord.voice.io/ReadableByteArrayCursor // dev.kord.voice.io/readableCursor|readableCursor@dev.kord.voice.io.ByteArrayView(){}[0] +final fun (dev.kord.voice.io/MutableByteArrayCursor).dev.kord.voice.io/writeByteArrayOrResize(kotlin/ByteArray) // dev.kord.voice.io/writeByteArrayOrResize|writeByteArrayOrResize@dev.kord.voice.io.MutableByteArrayCursor(kotlin.ByteArray){}[0] +final fun (dev.kord.voice.io/MutableByteArrayCursor).dev.kord.voice.io/writeByteViewOrResize(dev.kord.voice.io/ByteArrayView) // dev.kord.voice.io/writeByteViewOrResize|writeByteViewOrResize@dev.kord.voice.io.MutableByteArrayCursor(dev.kord.voice.io.ByteArrayView){}[0] +final fun (kotlin/ByteArray).dev.kord.voice.io/mutableCursor(): dev.kord.voice.io/MutableByteArrayCursor // dev.kord.voice.io/mutableCursor|mutableCursor@kotlin.ByteArray(){}[0] +final fun (kotlin/ByteArray).dev.kord.voice.io/readableCursor(): dev.kord.voice.io/ReadableByteArrayCursor // dev.kord.voice.io/readableCursor|readableCursor@kotlin.ByteArray(){}[0] +final fun (kotlin/ByteArray).dev.kord.voice.io/view(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/view|view@kotlin.ByteArray(){}[0] +final fun (kotlin/ByteArray).dev.kord.voice.io/view(kotlin/Int, kotlin/Int): dev.kord.voice.io/ByteArrayView? // dev.kord.voice.io/view|view@kotlin.ByteArray(kotlin.Int;kotlin.Int){}[0] +final fun dev.kord.voice.gateway/logCaughtThrowable(kotlin/Throwable) // dev.kord.voice.gateway/logCaughtThrowable|logCaughtThrowable(kotlin.Throwable){}[0] +final fun dev.kord.voice.udp/DefaultAudioPacketProvider(kotlin/ByteArray, dev.kord.voice.encryption.strategies/NonceStrategy): dev.kord.voice.udp/AudioPacketProvider // dev.kord.voice.udp/DefaultAudioPacketProvider|DefaultAudioPacketProvider(kotlin.ByteArray;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] +final fun dev.kord.voice.udp/RTPPacket(kotlin/UInt, kotlin/UInt, kotlin/UShort, kotlin/Byte, kotlin/ByteArray, kotlin/Function1 =...): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket|RTPPacket(kotlin.UInt;kotlin.UInt;kotlin.UShort;kotlin.Byte;kotlin.ByteArray;kotlin.Function1){}[0] +final fun dev.kord.voice/SpeakingFlags(kotlin.collections/Iterable): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.collections.Iterable){}[0] +final fun dev.kord.voice/SpeakingFlags(kotlin.collections/Iterable): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.collections.Iterable){}[0] +final fun dev.kord.voice/SpeakingFlags(kotlin/Array...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Array...){}[0] +final fun dev.kord.voice/SpeakingFlags(kotlin/Array...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Array...){}[0] +final inline fun <#A: reified dev.kord.voice.gateway/VoiceEvent> (dev.kord.voice.gateway/VoiceGateway).dev.kord.voice.gateway/on(kotlinx.coroutines/CoroutineScope =..., crossinline kotlin.coroutines/SuspendFunction1<#A, kotlin/Unit>): kotlinx.coroutines/Job // dev.kord.voice.gateway/on|on@dev.kord.voice.gateway.VoiceGateway(kotlinx.coroutines.CoroutineScope;kotlin.coroutines.SuspendFunction1<0:0,kotlin.Unit>){0§}[0] +final inline fun dev.kord.voice/SpeakingFlags(kotlin/Function1 =...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Function1){}[0] +final object dev.kord.voice.gateway/Resumed : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Resumed|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Resumed.serializer|serializer(){}[0] +} +final object dev.kord.voice.streams/NOPStreams : dev.kord.voice.streams/Streams { // dev.kord.voice.streams/NOPStreams|null[0] + final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] + final val incomingAudioFrames // dev.kord.voice.streams/NOPStreams.incomingAudioFrames|{}incomingAudioFrames[0] + final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/NOPStreams.incomingAudioFrames.|(){}[0] + final val incomingAudioPackets // dev.kord.voice.streams/NOPStreams.incomingAudioPackets|{}incomingAudioPackets[0] + final fun (): kotlinx.coroutines.flow/Flow // dev.kord.voice.streams/NOPStreams.incomingAudioPackets.|(){}[0] + final val incomingUserStreams // dev.kord.voice.streams/NOPStreams.incomingUserStreams|{}incomingUserStreams[0] + final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/NOPStreams.incomingUserStreams.|(){}[0] + final val ssrcToUser // dev.kord.voice.streams/NOPStreams.ssrcToUser|{}ssrcToUser[0] + final fun (): kotlin.collections/Map // dev.kord.voice.streams/NOPStreams.ssrcToUser.|(){}[0] +} +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(dev.kord.voice.udp/SocketAddress, kotlin/Int): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress;kotlin.Int){}[0] +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(dev.kord.voice.udp/SocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress){}[0] +final suspend inline fun dev.kord.voice/VoiceConnection(dev.kord.gateway/Gateway, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/Function1 =...): dev.kord.voice/VoiceConnection // dev.kord.voice/VoiceConnection|VoiceConnection(dev.kord.gateway.Gateway;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.Function1){}[0] +final val dev.kord.voice.udp/GlobalVoiceUdpSocket // dev.kord.voice.udp/GlobalVoiceUdpSocket|{}GlobalVoiceUdpSocket[0] + final fun (): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/GlobalVoiceUdpSocket.|(){}[0] +final value class dev.kord.voice/AudioFrame { // dev.kord.voice/AudioFrame|null[0] + constructor (kotlin/ByteArray) // dev.kord.voice/AudioFrame.|(kotlin.ByteArray){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/AudioFrame.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/AudioFrame.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice/AudioFrame.toString|toString(){}[0] + final object Companion { // dev.kord.voice/AudioFrame.Companion|null[0] + final fun fromData(kotlin/ByteArray?): dev.kord.voice/AudioFrame? // dev.kord.voice/AudioFrame.Companion.fromData|fromData(kotlin.ByteArray?){}[0] + final val SILENCE // dev.kord.voice/AudioFrame.Companion.SILENCE|{}SILENCE[0] + final fun (): dev.kord.voice/AudioFrame // dev.kord.voice/AudioFrame.Companion.SILENCE.|(){}[0] + } + final val data // dev.kord.voice/AudioFrame.data|{}data[0] + final fun (): kotlin/ByteArray // dev.kord.voice/AudioFrame.data.|(){}[0] +} +sealed class dev.kord.voice.gateway/Close : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Close|null[0] + constructor () // dev.kord.voice.gateway/Close.|(){}[0] + final class DiscordClose : dev.kord.voice.gateway/Close { // dev.kord.voice.gateway/Close.DiscordClose|null[0] + constructor (dev.kord.voice.gateway/VoiceGatewayCloseCode, kotlin/Boolean) // dev.kord.voice.gateway/Close.DiscordClose.|(dev.kord.voice.gateway.VoiceGatewayCloseCode;kotlin.Boolean){}[0] + final fun component1(): dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/Close.DiscordClose.component1|component1(){}[0] + final fun component2(): kotlin/Boolean // dev.kord.voice.gateway/Close.DiscordClose.component2|component2(){}[0] + final fun copy(dev.kord.voice.gateway/VoiceGatewayCloseCode =..., kotlin/Boolean =...): dev.kord.voice.gateway/Close.DiscordClose // dev.kord.voice.gateway/Close.DiscordClose.copy|copy(dev.kord.voice.gateway.VoiceGatewayCloseCode;kotlin.Boolean){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Close.DiscordClose.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Close.DiscordClose.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/Close.DiscordClose.toString|toString(){}[0] + final val closeCode // dev.kord.voice.gateway/Close.DiscordClose.closeCode|{}closeCode[0] + final fun (): dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/Close.DiscordClose.closeCode.|(){}[0] + final val recoverable // dev.kord.voice.gateway/Close.DiscordClose.recoverable|{}recoverable[0] + final fun (): kotlin/Boolean // dev.kord.voice.gateway/Close.DiscordClose.recoverable.|(){}[0] + } + final object Reconnecting : dev.kord.voice.gateway/Close // dev.kord.voice.gateway/Close.Reconnecting|null[0] + final object RetryLimitReached : dev.kord.voice.gateway/Close // dev.kord.voice.gateway/Close.RetryLimitReached|null[0] + final object Timeout : dev.kord.voice.gateway/Close // dev.kord.voice.gateway/Close.Timeout|null[0] + final object UserClose : dev.kord.voice.gateway/Close // dev.kord.voice.gateway/Close.UserClose|null[0] +} +sealed class dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Command|null[0] + constructor () // dev.kord.voice.gateway/Command.|(){}[0] + final object SerializationStrategy : kotlinx.serialization/SerializationStrategy { // dev.kord.voice.gateway/Command.SerializationStrategy|null[0] + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/Command.SerializationStrategy.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Command){}[0] + final val descriptor // dev.kord.voice.gateway/Command.SerializationStrategy.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Command.SerializationStrategy.descriptor.|(){}[0] + } +} +sealed class dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/VoiceEvent|null[0] + constructor () // dev.kord.voice.gateway/VoiceEvent.|(){}[0] + final object DeserializationStrategy : kotlinx.serialization/DeserializationStrategy { // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy|null[0] + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/VoiceEvent? // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] + final val descriptor // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.descriptor.|(){}[0] + } +} +sealed class dev.kord.voice.gateway/VoiceGatewayCloseCode { // dev.kord.voice.gateway/VoiceGatewayCloseCode|null[0] + constructor (kotlin/Int) // dev.kord.voice.gateway/VoiceGatewayCloseCode.|(kotlin.Int){}[0] + final class Unknown : dev.kord.voice.gateway/VoiceGatewayCloseCode { // dev.kord.voice.gateway/VoiceGatewayCloseCode.Unknown|null[0] + constructor (kotlin/Int) // dev.kord.voice.gateway/VoiceGatewayCloseCode.Unknown.|(kotlin.Int){}[0] + } + final object AlreadyAuthenticated : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.AlreadyAuthenticated|null[0] + final object AuthenticationFailed : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.AuthenticationFailed|null[0] + final object Companion { // dev.kord.voice.gateway/VoiceGatewayCloseCode.Companion|null[0] + final fun of(kotlin/Int): dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.Companion.of|of(kotlin.Int){}[0] + } + final object Disconnect : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.Disconnect|null[0] + final object FailedToDecodePayload : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.FailedToDecodePayload|null[0] + final object NotAuthenticated : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.NotAuthenticated|null[0] + final object ServerNotFound : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.ServerNotFound|null[0] + final object SessionNoLongerValid : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.SessionNoLongerValid|null[0] + final object SessionTimeout : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.SessionTimeout|null[0] + final object UnknownEncryptionMode : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.UnknownEncryptionMode|null[0] + final object UnknownOpcode : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.UnknownOpcode|null[0] + final object UnknownProtocol : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.UnknownProtocol|null[0] + final object VoiceServerCrashed : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.VoiceServerCrashed|null[0] + final val code // dev.kord.voice.gateway/VoiceGatewayCloseCode.code|{}code[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/VoiceGatewayCloseCode.code.|(){}[0] +} +sealed class dev.kord.voice.udp/PayloadType { // dev.kord.voice.udp/PayloadType|null[0] + constructor (kotlin/Byte) // dev.kord.voice.udp/PayloadType.|(kotlin.Byte){}[0] + final class Unknown : dev.kord.voice.udp/PayloadType { // dev.kord.voice.udp/PayloadType.Unknown|null[0] + constructor (kotlin/Byte) // dev.kord.voice.udp/PayloadType.Unknown.|(kotlin.Byte){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/PayloadType.Unknown.toString|toString(){}[0] + } + final object Alive : dev.kord.voice.udp/PayloadType // dev.kord.voice.udp/PayloadType.Alive|null[0] + final object Audio : dev.kord.voice.udp/PayloadType // dev.kord.voice.udp/PayloadType.Audio|null[0] + final object Companion { // dev.kord.voice.udp/PayloadType.Companion|null[0] + final fun from(kotlin/Byte): dev.kord.voice.udp/PayloadType // dev.kord.voice.udp/PayloadType.Companion.from|from(kotlin.Byte){}[0] + } + final val raw // dev.kord.voice.udp/PayloadType.raw|{}raw[0] + final fun (): kotlin/Byte // dev.kord.voice.udp/PayloadType.raw.|(){}[0] +} +sealed class dev.kord.voice/EncryptionMode { // dev.kord.voice/EncryptionMode|null[0] + constructor (kotlin/String) // dev.kord.voice/EncryptionMode.|(kotlin.String){}[0] + final class Unknown : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.Unknown|null[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/EncryptionMode.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/EncryptionMode.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice/EncryptionMode.toString|toString(){}[0] + final object Companion { // dev.kord.voice/EncryptionMode.Companion|null[0] + final fun from(kotlin/String): dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.Companion.from|from(kotlin.String){}[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice/EncryptionMode.Companion.serializer|serializer(){}[0] + final val entries // dev.kord.voice/EncryptionMode.Companion.entries|{}entries[0] + final fun (): kotlin.collections/List // dev.kord.voice/EncryptionMode.Companion.entries.|(){}[0] + } + final object XSalsa20Poly1305 : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.XSalsa20Poly1305|null[0] + final object XSalsa20Poly1305Lite : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.XSalsa20Poly1305Lite|null[0] + final object XSalsa20Poly1305Suffix : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.XSalsa20Poly1305Suffix|null[0] + final val value // dev.kord.voice/EncryptionMode.value|{}value[0] + final fun (): kotlin/String // dev.kord.voice/EncryptionMode.value.|(){}[0] +} +sealed class dev.kord.voice/SpeakingFlag { // dev.kord.voice/SpeakingFlag|null[0] + constructor (kotlin/Int) // dev.kord.voice/SpeakingFlag.|(kotlin.Int){}[0] + final class Unknown : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Unknown|null[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/SpeakingFlag.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/SpeakingFlag.hashCode|hashCode(){}[0] + final fun plus(dev.kord.voice/SpeakingFlag): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlag.plus|plus(dev.kord.voice.SpeakingFlag){}[0] + final fun plus(dev.kord.voice/SpeakingFlags): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlag.plus|plus(dev.kord.voice.SpeakingFlags){}[0] + final fun toString(): kotlin/String // dev.kord.voice/SpeakingFlag.toString|toString(){}[0] + final object Companion { // dev.kord.voice/SpeakingFlag.Companion|null[0] + final fun fromShift(kotlin/Int): dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Companion.fromShift|fromShift(kotlin.Int){}[0] + final val entries // dev.kord.voice/SpeakingFlag.Companion.entries|{}entries[0] + final fun (): kotlin.collections/List // dev.kord.voice/SpeakingFlag.Companion.entries.|(){}[0] + } + final object Microphone : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Microphone|null[0] + final object Priority : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Priority|null[0] + final object Soundshare : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Soundshare|null[0] + final val code // dev.kord.voice/SpeakingFlag.code|{}code[0] + final fun (): kotlin/Int // dev.kord.voice/SpeakingFlag.code.|(){}[0] + final val shift // dev.kord.voice/SpeakingFlag.shift|{}shift[0] + final fun (): kotlin/Int // dev.kord.voice/SpeakingFlag.shift.|(){}[0] +} +sealed interface dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/NonceStrategy|null[0] + abstract fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/NonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] + abstract fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NonceStrategy.generate|generate(kotlin.Function0){}[0] + abstract fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] + abstract val nonceLength // dev.kord.voice.encryption.strategies/NonceStrategy.nonceLength|{}nonceLength[0] + abstract fun (): kotlin/Int // dev.kord.voice.encryption.strategies/NonceStrategy.nonceLength.|(){}[0] +} From 5e97756ee0a0e54aeec9d9546cf3efd7cb181e0e Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Wed, 17 Apr 2024 15:11:58 +0200 Subject: [PATCH 63/83] Ignore empty string returned by zError --- gateway/src/nativeMain/kotlin/Inflater.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index d61e15da5c3..9432b791a41 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -3,7 +3,12 @@ package dev.kord.gateway import kotlinx.cinterop.* import platform.zlib.* -private class ZlibException(message: String) : IllegalStateException(message) +@ExperimentalForeignApi +private class ZlibException(msg: CPointer?, ret: Int) : IllegalStateException( + message = msg?.toKString() + ?: zError(ret)?.toKString()?.ifEmpty { null } // zError returns empty string for unknown codes + ?: "unexpected return code: $ret" +) @OptIn(ExperimentalForeignApi::class) internal actual fun Inflater(): Inflater = object : Inflater { @@ -24,16 +29,13 @@ internal actual fun Inflater(): Inflater = object : Inflater { val ret = inflateInit(zStream.ptr) if (ret != Z_OK) { try { - throwZlibException(zStream.msg, ret) + throw ZlibException(zStream.msg, ret) } finally { nativeHeap.free(zStream) } } } - private fun throwZlibException(msg: CPointer?, ret: Int): Nothing = - throw ZlibException(msg?.toKString() ?: zError(ret)?.toKString() ?: ret.toString()) - override fun inflate(compressed: ByteArray, compressedLen: Int): String = compressed.asUByteArray().usePinned { compressedPinned -> zStream.next_in = compressedPinned.addressOf(0) @@ -46,7 +48,7 @@ internal actual fun Inflater(): Inflater = object : Inflater { inflate(zStream.ptr, Z_NO_FLUSH) } if (ret != Z_OK && ret != Z_STREAM_END) { - throwZlibException(zStream.msg, ret) + throw ZlibException(zStream.msg, ret) } if (zStream.avail_in == 0u || zStream.avail_out != 0u) break // grow decompressed buffer @@ -59,7 +61,7 @@ internal actual fun Inflater(): Inflater = object : Inflater { override fun close() { val ret = inflateEnd(zStream.ptr) try { - if (ret != Z_OK) throwZlibException(zStream.msg, ret) + if (ret != Z_OK) throw ZlibException(zStream.msg, ret) } finally { nativeHeap.free(zStream) } From b655c64e56c1e0cd38064855bc3641f08c7130fb Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Wed, 17 Apr 2024 15:40:35 +0200 Subject: [PATCH 64/83] Fix compilation --- samples/src/jsMain/kotlin/runMain.js.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/samples/src/jsMain/kotlin/runMain.js.kt b/samples/src/jsMain/kotlin/runMain.js.kt index 1a8d9a7a28c..a937c82a759 100644 --- a/samples/src/jsMain/kotlin/runMain.js.kt +++ b/samples/src/jsMain/kotlin/runMain.js.kt @@ -1,7 +1,9 @@ import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +@OptIn(DelicateCoroutinesApi::class) actual fun runMain(block: suspend CoroutineScope.() -> Unit) { GlobalScope.launch { block() } -} \ No newline at end of file +} From 6a139e3ce4112d69e784fae7a01ef172db4786c1 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Wed, 17 Apr 2024 17:07:27 +0200 Subject: [PATCH 65/83] Prevent use after free and double free --- gateway/src/nativeMain/kotlin/Inflater.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index 9432b791a41..a70da584530 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -16,6 +16,7 @@ internal actual fun Inflater(): Inflater = object : Inflater { private var decompressed = UByteArray(1024) // buffer only grows, is reused for every zlib inflate call private var decompressedLen = 0 + private var closed = false private val zStream = nativeHeap.alloc().also { zStream -> // next_in, avail_in, zalloc, zfree and opaque must be initialized before calling inflateInit @@ -36,7 +37,8 @@ internal actual fun Inflater(): Inflater = object : Inflater { } } - override fun inflate(compressed: ByteArray, compressedLen: Int): String = + override fun inflate(compressed: ByteArray, compressedLen: Int): String { + check(!closed) { "Inflater has already been closed." } compressed.asUByteArray().usePinned { compressedPinned -> zStream.next_in = compressedPinned.addressOf(0) zStream.avail_in = compressedLen.convert() @@ -55,10 +57,15 @@ internal actual fun Inflater(): Inflater = object : Inflater { decompressedLen = decompressed.size decompressed = decompressed.copyOf(decompressed.size * 2) } - decompressed.asByteArray().decodeToString(endIndex = decompressed.size - zStream.avail_out.convert()) } + return decompressed + .asByteArray() + .decodeToString(endIndex = decompressed.size - zStream.avail_out.convert()) + } override fun close() { + if (closed) return + closed = true val ret = inflateEnd(zStream.ptr) try { if (ret != Z_OK) throw ZlibException(zStream.msg, ret) From f5ce70af158c411955ce500f0f773e5e5e7b3951 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Wed, 17 Apr 2024 17:12:12 +0200 Subject: [PATCH 66/83] Pedantic exception handling in init and close --- gateway/src/nativeMain/kotlin/Inflater.kt | 42 ++++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index a70da584530..0e291ae2bb7 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -17,23 +17,27 @@ internal actual fun Inflater(): Inflater = object : Inflater { private var decompressed = UByteArray(1024) // buffer only grows, is reused for every zlib inflate call private var decompressedLen = 0 private var closed = false + private val zStream = nativeHeap.alloc() - private val zStream = nativeHeap.alloc().also { zStream -> - // next_in, avail_in, zalloc, zfree and opaque must be initialized before calling inflateInit - zStream.next_in = null - zStream.avail_in = 0u - zStream.zalloc = null - zStream.zfree = null - zStream.opaque = null - // initialize msg just in case, we use it for throwing exceptions - zStream.msg = null - val ret = inflateInit(zStream.ptr) - if (ret != Z_OK) { + init { + try { + // next_in, avail_in, zalloc, zfree and opaque must be initialized before calling inflateInit + zStream.next_in = null + zStream.avail_in = 0u + zStream.zalloc = null + zStream.zfree = null + zStream.opaque = null + // initialize msg to null in case inflateInit doesn't, we use it for throwing exceptions + zStream.msg = null + val ret = inflateInit(zStream.ptr) + if (ret != Z_OK) throw ZlibException(zStream.msg, ret) + } catch (e: Throwable) { try { - throw ZlibException(zStream.msg, ret) - } finally { nativeHeap.free(zStream) + } catch (freeException: Throwable) { + e.addSuppressed(freeException) } + throw e } } @@ -66,11 +70,17 @@ internal actual fun Inflater(): Inflater = object : Inflater { override fun close() { if (closed) return closed = true - val ret = inflateEnd(zStream.ptr) try { + val ret = inflateEnd(zStream.ptr) if (ret != Z_OK) throw ZlibException(zStream.msg, ret) - } finally { - nativeHeap.free(zStream) + } catch (e: Throwable) { + try { + nativeHeap.free(zStream) + } catch (freeException: Throwable) { + e.addSuppressed(freeException) + } + throw e } + nativeHeap.free(zStream) } } From 3500c534a8cf3474d4a927154cd67ee0a5e3edf0 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Wed, 17 Apr 2024 17:28:53 +0200 Subject: [PATCH 67/83] Fix warnings again that were fixed in #936 I accidentally reintroduced them in the most recent merge of main into feature/native. --- core/live-tests/build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/live-tests/build.gradle.kts b/core/live-tests/build.gradle.kts index 6ff2ebf0210..07a72173796 100644 --- a/core/live-tests/build.gradle.kts +++ b/core/live-tests/build.gradle.kts @@ -21,4 +21,7 @@ tasks { withType().configureEach { enabled = !System.getenv("KORD_TEST_TOKEN").isNullOrBlank() } + withType().configureEach { + useJUnitPlatform() + } } From 0796312170c777f28135136ebe8fe5adc30129e9 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Wed, 17 Apr 2024 23:53:12 +0200 Subject: [PATCH 68/83] Actually build voice on Windows and fix KLib dump --- buildSrc/src/main/kotlin/Targets.kt | 34 ++++---- .../kord-multiplatform-module.gradle.kts | 2 + common/api/common.klib.api | 2 +- core-voice/api/core-voice.klib.api | 2 +- core/api/core.klib.api | 2 +- core/live-tests/build.gradle.kts | 1 + gateway/api/gateway.klib.api | 2 +- rest/api/rest.klib.api | 2 +- samples/build.gradle.kts | 20 +++++ voice/api/voice.klib.api | 84 +++++++++++++------ .../kotlin/VoiceConnectionBuilder.mingw.kt | 1 + .../kotlin/udp/VoiceUdpSocket.mingw.kt | 1 + 12 files changed, 109 insertions(+), 44 deletions(-) diff --git a/buildSrc/src/main/kotlin/Targets.kt b/buildSrc/src/main/kotlin/Targets.kt index d1712a8d0ea..49765194b41 100644 --- a/buildSrc/src/main/kotlin/Targets.kt +++ b/buildSrc/src/main/kotlin/Targets.kt @@ -1,24 +1,10 @@ +import org.gradle.api.tasks.TaskContainer import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension -import org.jetbrains.kotlin.gradle.kpm.external.ExternalVariantApi -import org.jetbrains.kotlin.gradle.kpm.external.project import org.jetbrains.kotlin.konan.target.HostManager -@OptIn(ExternalVariantApi::class) fun KotlinMultiplatformExtension.targets() { - // There are issues with compiling the linux variant on windows - // Please use WSL if you need to work on the linux port - if (!HostManager.hostIsMingw) { - linuxX64() - linuxArm64() - } - jvm() - if (project.name != "voice" && project.name != "core-voice") { - // https://youtrack.jetbrains.com/issue/KTOR-4080 - mingwX64() - } - js { nodejs { testTask { @@ -32,6 +18,11 @@ fun KotlinMultiplatformExtension.targets() { useCommonJs() } + linuxX64() + linuxArm64() + + mingwX64() + macosArm64() macosX64() @@ -52,3 +43,16 @@ fun KotlinMultiplatformExtension.targets() { } } } + +// There are issues with linking the linux variant on windows. +// Please use WSL if you need to work on the linux port. +fun TaskContainer.disableLinuxLinkTestTasksOnWindows() { + if (HostManager.hostIsMingw) { + val linuxLinkTestTasks = listOf("linkDebugTestLinuxX64", "linkDebugTestLinuxArm64") + for (task in linuxLinkTestTasks) { + named(task) { + enabled = false + } + } + } +} diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 9a03abb9b6a..37329226ec0 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -97,4 +97,6 @@ tasks { applyKordDokkaOptions() dependsOn("kspCommonMainKotlinMetadata") } + + disableLinuxLinkTestTasksOnWindows() } diff --git a/common/api/common.klib.api b/common/api/common.klib.api index e6a0c34c1ab..4b5710421f6 100644 --- a/common/api/common.klib.api +++ b/common/api/common.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/core-voice/api/core-voice.klib.api b/core-voice/api/core-voice.klib.api index 022e4cd6a41..4caf54409c4 100644 --- a/core-voice/api/core-voice.klib.api +++ b/core-voice/api/core-voice.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/core/api/core.klib.api b/core/api/core.klib.api index 67c81c3d68f..06046099eb4 100644 --- a/core/api/core.klib.api +++ b/core/api/core.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/core/live-tests/build.gradle.kts b/core/live-tests/build.gradle.kts index 07a72173796..58946c25a5e 100644 --- a/core/live-tests/build.gradle.kts +++ b/core/live-tests/build.gradle.kts @@ -24,4 +24,5 @@ tasks { withType().configureEach { useJUnitPlatform() } + disableLinuxLinkTestTasksOnWindows() } diff --git a/gateway/api/gateway.klib.api b/gateway/api/gateway.klib.api index 0c463ab1ea3..dff0783a3cd 100644 --- a/gateway/api/gateway.klib.api +++ b/gateway/api/gateway.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/rest/api/rest.klib.api b/rest/api/rest.klib.api index bcc2f50bad7..987d6747bd8 100644 --- a/rest/api/rest.klib.api +++ b/rest/api/rest.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/samples/build.gradle.kts b/samples/build.gradle.kts index fd53f4585a6..6b612393dfd 100644 --- a/samples/build.gradle.kts +++ b/samples/build.gradle.kts @@ -1,6 +1,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.HostManager plugins { org.jetbrains.kotlin.multiplatform @@ -59,3 +60,22 @@ kotlin { } } } + +tasks { + // There are issues with linking the linux variant on windows. + // Please use WSL if you need to work on the linux port. + /** see [disableLinuxLinkTestTasksOnWindows] */ + if (HostManager.hostIsMingw) { + val linuxLinkExecutableTasks = listOf( + "linkDebugExecutableLinuxX64", + "linkDebugExecutableLinuxArm64", + "linkReleaseExecutableLinuxX64", + "linkReleaseExecutableLinuxArm64", + ) + for (task in linuxLinkExecutableTasks) { + named(task) { + enabled = false + } + } + } +} diff --git a/voice/api/voice.klib.api b/voice/api/voice.klib.api index 3f367707eaf..3c017fc30fc 100644 --- a/voice/api/voice.klib.api +++ b/voice/api/voice.klib.api @@ -1,5 +1,7 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Alias: apple => [iosArm64, iosSimulatorArm64, iosX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Alias: linux => [linuxArm64, linuxX64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true @@ -37,7 +39,6 @@ abstract interface dev.kord.voice.gateway/VoiceGateway { // dev.kord.voice.gatew } } abstract interface dev.kord.voice.streams/Streams { // dev.kord.voice.streams/Streams|null[0] - abstract suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/Streams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] abstract val incomingAudioFrames // dev.kord.voice.streams/Streams.incomingAudioFrames|{}incomingAudioFrames[0] abstract fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/Streams.incomingAudioFrames.|(){}[0] abstract val incomingAudioPackets // dev.kord.voice.streams/Streams.incomingAudioPackets|{}incomingAudioPackets[0] @@ -46,17 +47,27 @@ abstract interface dev.kord.voice.streams/Streams { // dev.kord.voice.streams/St abstract fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/Streams.incomingUserStreams.|(){}[0] abstract val ssrcToUser // dev.kord.voice.streams/Streams.ssrcToUser|{}ssrcToUser[0] abstract fun (): kotlin.collections/Map // dev.kord.voice.streams/Streams.ssrcToUser.|(){}[0] + // Targets: [apple, linux] + abstract suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/Streams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [js, mingwX64] + abstract suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/Streams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } abstract interface dev.kord.voice.udp/AudioFrameSender { // dev.kord.voice.udp/AudioFrameSender|null[0] abstract suspend fun start(dev.kord.voice.udp/AudioFrameSenderConfiguration) // dev.kord.voice.udp/AudioFrameSender.start|start(dev.kord.voice.udp.AudioFrameSenderConfiguration){}[0] } abstract interface dev.kord.voice.udp/VoiceUdpSocket { // dev.kord.voice.udp/VoiceUdpSocket|null[0] - abstract fun all(dev.kord.voice.udp/SocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(dev.kord.voice.udp.SocketAddress){}[0] - abstract suspend fun send(dev.kord.voice.udp/SocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(dev.kord.voice.udp.SocketAddress;dev.kord.voice.io.ByteArrayView){}[0] abstract suspend fun stop() // dev.kord.voice.udp/VoiceUdpSocket.stop|stop(){}[0] final object Companion { // dev.kord.voice.udp/VoiceUdpSocket.Companion|null[0] final fun none(): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/VoiceUdpSocket.Companion.none|none(){}[0] } + // Targets: [apple, linux] + abstract fun all(io.ktor.network.sockets/InetSocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [apple, linux] + abstract suspend fun send(io.ktor.network.sockets/InetSocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(io.ktor.network.sockets.InetSocketAddress;dev.kord.voice.io.ByteArrayView){}[0] + // Targets: [js, mingwX64] + abstract fun all(dev.kord.voice.udp/SocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(dev.kord.voice.udp.SocketAddress){}[0] + // Targets: [js, mingwX64] + abstract suspend fun send(dev.kord.voice.udp/SocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(dev.kord.voice.udp.SocketAddress;dev.kord.voice.io.ByteArrayView){}[0] } final class dev.kord.voice.encryption.strategies/LiteNonceStrategy : dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/LiteNonceStrategy|null[0] constructor () // dev.kord.voice.encryption.strategies/LiteNonceStrategy.|(){}[0] @@ -481,7 +492,6 @@ final class dev.kord.voice.io/ReadableByteArrayCursor { // dev.kord.voice.io/Rea } final class dev.kord.voice.streams/DefaultStreams : dev.kord.voice.streams/Streams { // dev.kord.voice.streams/DefaultStreams|null[0] constructor (dev.kord.voice.gateway/VoiceGateway, dev.kord.voice.udp/VoiceUdpSocket, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.streams/DefaultStreams.|(dev.kord.voice.gateway.VoiceGateway;dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] - final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/DefaultStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] final val incomingAudioFrames // dev.kord.voice.streams/DefaultStreams.incomingAudioFrames|(){}[0] final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/DefaultStreams.incomingAudioFrames.|(){}[0] final val incomingAudioPackets // dev.kord.voice.streams/DefaultStreams.incomingAudioPackets|{}incomingAudioPackets[0] @@ -490,14 +500,15 @@ final class dev.kord.voice.streams/DefaultStreams : dev.kord.voice.streams/Strea final fun (): kotlinx.coroutines.flow/SharedFlow> // dev.kord.voice.streams/DefaultStreams.incomingUserStreams.|(){}[0] final val ssrcToUser // dev.kord.voice.streams/DefaultStreams.ssrcToUser|{}ssrcToUser[0] final fun (): kotlin.collections/Map // dev.kord.voice.streams/DefaultStreams.ssrcToUser.|(){}[0] + // Targets: [apple, linux] + final suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/DefaultStreams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [js, mingwX64] + final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/DefaultStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } final class dev.kord.voice.udp/AudioFrameSenderConfiguration { // dev.kord.voice.udp/AudioFrameSenderConfiguration|null[0] - constructor (dev.kord.voice.udp/SocketAddress, kotlin/UInt, kotlin/ByteArray, dev.kord.voice/FrameInterceptorConfiguration) // dev.kord.voice.udp/AudioFrameSenderConfiguration.|(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] - final fun component1(): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.component1|component1(){}[0] final fun component2(): kotlin/UInt // dev.kord.voice.udp/AudioFrameSenderConfiguration.component2|component2(){}[0] final fun component3(): kotlin/ByteArray // dev.kord.voice.udp/AudioFrameSenderConfiguration.component3|component3(){}[0] final fun component4(): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.component4|component4(){}[0] - final fun copy(dev.kord.voice.udp/SocketAddress =..., kotlin/UInt =..., kotlin/ByteArray =..., dev.kord.voice/FrameInterceptorConfiguration =...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/AudioFrameSenderConfiguration.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.udp/AudioFrameSenderConfiguration.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.udp/AudioFrameSenderConfiguration.toString|toString(){}[0] @@ -506,9 +517,24 @@ final class dev.kord.voice.udp/AudioFrameSenderConfiguration { // dev.kord.voice final val key // dev.kord.voice.udp/AudioFrameSenderConfiguration.key|{}key[0] final fun (): kotlin/ByteArray // dev.kord.voice.udp/AudioFrameSenderConfiguration.key.|(){}[0] final val server // dev.kord.voice.udp/AudioFrameSenderConfiguration.server|{}server[0] + // Targets: [apple, linux] + final fun (): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.server.|(){}[0] + // Targets: [js, mingwX64] final fun (): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.server.|(){}[0] final val ssrc // dev.kord.voice.udp/AudioFrameSenderConfiguration.ssrc|{}ssrc[0] final fun (): kotlin/UInt // dev.kord.voice.udp/AudioFrameSenderConfiguration.ssrc.|(){}[0] + // Targets: [apple, linux] + constructor (io.ktor.network.sockets/InetSocketAddress, kotlin/UInt, kotlin/ByteArray, dev.kord.voice/FrameInterceptorConfiguration) // dev.kord.voice.udp/AudioFrameSenderConfiguration.|(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + // Targets: [apple, linux] + final fun component1(): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.component1|component1(){}[0] + // Targets: [apple, linux] + final fun copy(io.ktor.network.sockets/InetSocketAddress =..., kotlin/UInt =..., kotlin/ByteArray =..., dev.kord.voice/FrameInterceptorConfiguration =...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + // Targets: [js, mingwX64] + constructor (dev.kord.voice.udp/SocketAddress, kotlin/UInt, kotlin/ByteArray, dev.kord.voice/FrameInterceptorConfiguration) // dev.kord.voice.udp/AudioFrameSenderConfiguration.|(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + // Targets: [js, mingwX64] + final fun component1(): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.component1|component1(){}[0] + // Targets: [js, mingwX64] + final fun copy(dev.kord.voice.udp/SocketAddress =..., kotlin/UInt =..., kotlin/ByteArray =..., dev.kord.voice/FrameInterceptorConfiguration =...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] } final class dev.kord.voice.udp/DefaultAudioFrameSender : dev.kord.voice.udp/AudioFrameSender { // dev.kord.voice.udp/DefaultAudioFrameSender|null[0] constructor (dev.kord.voice.udp/DefaultAudioFrameSenderData) // dev.kord.voice.udp/DefaultAudioFrameSender.|(dev.kord.voice.udp.DefaultAudioFrameSenderData){}[0] @@ -612,19 +638,6 @@ final class dev.kord.voice.udp/RTPPacket { // dev.kord.voice.udp/RTPPacket|null[ final val timestamp // dev.kord.voice.udp/RTPPacket.timestamp|{}timestamp[0] final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.timestamp.|(){}[0] } -final class dev.kord.voice.udp/SocketAddress { // dev.kord.voice.udp/SocketAddress|null[0] - constructor (kotlin/String, kotlin/Int) // dev.kord.voice.udp/SocketAddress.|(kotlin.String;kotlin.Int){}[0] - final fun component1(): kotlin/String // dev.kord.voice.udp/SocketAddress.component1|component1(){}[0] - final fun component2(): kotlin/Int // dev.kord.voice.udp/SocketAddress.component2|component2(){}[0] - final fun copy(kotlin/String =..., kotlin/Int =...): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/SocketAddress.copy|copy(kotlin.String;kotlin.Int){}[0] - final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/SocketAddress.equals|equals(kotlin.Any?){}[0] - final fun hashCode(): kotlin/Int // dev.kord.voice.udp/SocketAddress.hashCode|hashCode(){}[0] - final fun toString(): kotlin/String // dev.kord.voice.udp/SocketAddress.toString|toString(){}[0] - final val hostname // dev.kord.voice.udp/SocketAddress.hostname|{}hostname[0] - final fun (): kotlin/String // dev.kord.voice.udp/SocketAddress.hostname.|(){}[0] - final val port // dev.kord.voice.udp/SocketAddress.port|{}port[0] - final fun (): kotlin/Int // dev.kord.voice.udp/SocketAddress.port.|(){}[0] -} final class dev.kord.voice/DefaultFrameInterceptor : dev.kord.voice/FrameInterceptor { // dev.kord.voice/DefaultFrameInterceptor|null[0] constructor (dev.kord.voice/DefaultFrameInterceptorData =...) // dev.kord.voice/DefaultFrameInterceptor.|(dev.kord.voice.DefaultFrameInterceptorData){}[0] final fun (kotlinx.coroutines.flow/Flow).intercept(dev.kord.voice/FrameInterceptorConfiguration): kotlinx.coroutines.flow/Flow // dev.kord.voice/DefaultFrameInterceptor.intercept|intercept@kotlinx.coroutines.flow.Flow(dev.kord.voice.FrameInterceptorConfiguration){}[0] @@ -829,7 +842,6 @@ final object dev.kord.voice.gateway/Resumed : dev.kord.voice.gateway/VoiceEvent final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Resumed.serializer|serializer(){}[0] } final object dev.kord.voice.streams/NOPStreams : dev.kord.voice.streams/Streams { // dev.kord.voice.streams/NOPStreams|null[0] - final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] final val incomingAudioFrames // dev.kord.voice.streams/NOPStreams.incomingAudioFrames|{}incomingAudioFrames[0] final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/NOPStreams.incomingAudioFrames.|(){}[0] final val incomingAudioPackets // dev.kord.voice.streams/NOPStreams.incomingAudioPackets|{}incomingAudioPackets[0] @@ -838,9 +850,11 @@ final object dev.kord.voice.streams/NOPStreams : dev.kord.voice.streams/Streams final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/NOPStreams.incomingUserStreams.|(){}[0] final val ssrcToUser // dev.kord.voice.streams/NOPStreams.ssrcToUser|{}ssrcToUser[0] final fun (): kotlin.collections/Map // dev.kord.voice.streams/NOPStreams.ssrcToUser.|(){}[0] + // Targets: [apple, linux] + final suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [js, mingwX64] + final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } -final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(dev.kord.voice.udp/SocketAddress, kotlin/Int): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress;kotlin.Int){}[0] -final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(dev.kord.voice.udp/SocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress){}[0] final suspend inline fun dev.kord.voice/VoiceConnection(dev.kord.gateway/Gateway, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/Function1 =...): dev.kord.voice/VoiceConnection // dev.kord.voice/VoiceConnection|VoiceConnection(dev.kord.gateway.Gateway;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.Function1){}[0] final val dev.kord.voice.udp/GlobalVoiceUdpSocket // dev.kord.voice.udp/GlobalVoiceUdpSocket|{}GlobalVoiceUdpSocket[0] final fun (): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/GlobalVoiceUdpSocket.|(){}[0] @@ -976,3 +990,25 @@ sealed interface dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kor abstract val nonceLength // dev.kord.voice.encryption.strategies/NonceStrategy.nonceLength|{}nonceLength[0] abstract fun (): kotlin/Int // dev.kord.voice.encryption.strategies/NonceStrategy.nonceLength.|(){}[0] } +// Targets: [apple, linux] +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(io.ktor.network.sockets/InetSocketAddress, kotlin/Int): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress;kotlin.Int){}[0] +// Targets: [apple, linux] +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(io.ktor.network.sockets/InetSocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress){}[0] +// Targets: [js, mingwX64] +final class dev.kord.voice.udp/SocketAddress { // dev.kord.voice.udp/SocketAddress|null[0] + constructor (kotlin/String, kotlin/Int) // dev.kord.voice.udp/SocketAddress.|(kotlin.String;kotlin.Int){}[0] + final fun component1(): kotlin/String // dev.kord.voice.udp/SocketAddress.component1|component1(){}[0] + final fun component2(): kotlin/Int // dev.kord.voice.udp/SocketAddress.component2|component2(){}[0] + final fun copy(kotlin/String =..., kotlin/Int =...): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/SocketAddress.copy|copy(kotlin.String;kotlin.Int){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/SocketAddress.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.udp/SocketAddress.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/SocketAddress.toString|toString(){}[0] + final val hostname // dev.kord.voice.udp/SocketAddress.hostname|{}hostname[0] + final fun (): kotlin/String // dev.kord.voice.udp/SocketAddress.hostname.|(){}[0] + final val port // dev.kord.voice.udp/SocketAddress.port|{}port[0] + final fun (): kotlin/Int // dev.kord.voice.udp/SocketAddress.port.|(){}[0] +} +// Targets: [js, mingwX64] +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(dev.kord.voice.udp/SocketAddress, kotlin/Int): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress;kotlin.Int){}[0] +// Targets: [js, mingwX64] +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(dev.kord.voice.udp/SocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress){}[0] diff --git a/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt b/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt index fe2534fcf53..6486443b453 100644 --- a/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt +++ b/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt @@ -1,3 +1,4 @@ package dev.kord.voice +// https://youtrack.jetbrains.com/issue/KTOR-4080 internal actual val isSupported: Boolean = false diff --git a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt index 1251a8c86ba..d2454f76b7f 100644 --- a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt +++ b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt @@ -14,4 +14,5 @@ public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket override suspend fun stop() = unsupported() } +// https://youtrack.jetbrains.com/issue/KTOR-4080 private fun unsupported(): Nothing = TODO("Voice is not supported on windows") From 379c7f6839ab549cff408ccba911a2b4c73fe2e6 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Thu, 18 Apr 2024 00:16:44 +0200 Subject: [PATCH 69/83] Fix file location warning --- rest/src/nativeMain/kotlin/{request => }/RecoveredStackTrace.kt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rest/src/nativeMain/kotlin/{request => }/RecoveredStackTrace.kt (100%) diff --git a/rest/src/nativeMain/kotlin/request/RecoveredStackTrace.kt b/rest/src/nativeMain/kotlin/RecoveredStackTrace.kt similarity index 100% rename from rest/src/nativeMain/kotlin/request/RecoveredStackTrace.kt rename to rest/src/nativeMain/kotlin/RecoveredStackTrace.kt From 26aa8db84fe3324b310510b7b4572c3b13622822 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Mon, 22 Apr 2024 20:46:40 +0200 Subject: [PATCH 70/83] =?UTF-8?q?Trailing=20,=20=E2=9D=A4=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8edd346bfa9..c2e549a2b0e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -121,7 +121,7 @@ pluginsForBuildSrc = [ "binary-compatibility-validator-plugin", "ksp-plugin", "kord-gradle-plugin", - "maven-publish-plugin" + "maven-publish-plugin", ] From 4dd54e77b160176e7f98edafe703cfef3abda14e Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Mon, 22 Apr 2024 20:47:19 +0200 Subject: [PATCH 71/83] decompressedLen can be a local variable --- gateway/src/nativeMain/kotlin/Inflater.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index 0e291ae2bb7..e4b6aad7d74 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -15,7 +15,6 @@ internal actual fun Inflater(): Inflater = object : Inflater { // see https://zlib.net/manual.html private var decompressed = UByteArray(1024) // buffer only grows, is reused for every zlib inflate call - private var decompressedLen = 0 private var closed = false private val zStream = nativeHeap.alloc() @@ -46,7 +45,7 @@ internal actual fun Inflater(): Inflater = object : Inflater { compressed.asUByteArray().usePinned { compressedPinned -> zStream.next_in = compressedPinned.addressOf(0) zStream.avail_in = compressedLen.convert() - decompressedLen = 0 + var decompressedLen = 0 while (true) { val ret = decompressed.usePinned { decompressedPinned -> zStream.next_out = decompressedPinned.addressOf(decompressedLen) From c598338ad2dd8b49d7ed8ee215d049596ed14ff4 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Mon, 22 Apr 2024 23:06:20 +0200 Subject: [PATCH 72/83] Tweaks to native Inflater I spent way too much time reading documentation... --- gateway/src/nativeMain/kotlin/Inflater.kt | 26 ++++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/gateway/src/nativeMain/kotlin/Inflater.kt b/gateway/src/nativeMain/kotlin/Inflater.kt index e4b6aad7d74..dc0e9cc72e4 100644 --- a/gateway/src/nativeMain/kotlin/Inflater.kt +++ b/gateway/src/nativeMain/kotlin/Inflater.kt @@ -14,7 +14,8 @@ private class ZlibException(msg: CPointer?, ret: Int) : IllegalStateExc internal actual fun Inflater(): Inflater = object : Inflater { // see https://zlib.net/manual.html - private var decompressed = UByteArray(1024) // buffer only grows, is reused for every zlib inflate call + // buffer for decompressed data, only grows, reused for every zlib inflate call + private var decompressed = UByteArray(1024) private var closed = false private val zStream = nativeHeap.alloc() @@ -50,15 +51,24 @@ internal actual fun Inflater(): Inflater = object : Inflater { val ret = decompressed.usePinned { decompressedPinned -> zStream.next_out = decompressedPinned.addressOf(decompressedLen) zStream.avail_out = (decompressed.size - decompressedLen).convert() - inflate(zStream.ptr, Z_NO_FLUSH) + inflate(zStream.ptr, Z_SYNC_FLUSH) } - if (ret != Z_OK && ret != Z_STREAM_END) { - throw ZlibException(zStream.msg, ret) + when { + ret == Z_OK && zStream.avail_out == 0u -> { + // grow decompressed buffer and call inflate again, there might be more output pending + decompressedLen = decompressed.size + decompressed = decompressed.copyOf(decompressed.size * 2) + } + // Z_BUF_ERROR is no real error after the first inflate call: + // It means the previous inflate call did exactly fill the decompressed buffer (avail_out == 0). + // Because of that, we grew the buffer and called inflate again. However, it couldn't make any + // progress this time (everything is already decompressed), so it returns Z_BUF_ERROR. + ret == Z_OK || ret == Z_STREAM_END || (decompressedLen != 0 && ret == Z_BUF_ERROR) -> { + check(zStream.avail_in == 0u) { "Inflater did not decompress all available data." } + break + } + else -> throw ZlibException(zStream.msg, ret) } - if (zStream.avail_in == 0u || zStream.avail_out != 0u) break - // grow decompressed buffer - decompressedLen = decompressed.size - decompressed = decompressed.copyOf(decompressed.size * 2) } } return decompressed From fa06f85e3985b68c5eee2e5a27037b1dd2e89857 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 2 Jul 2024 18:12:58 +0200 Subject: [PATCH 73/83] Remaining upgrades --- buildSrc/src/main/kotlin/Targets.kt | 8 +- .../kord-multiplatform-module.gradle.kts | 3 - core/api/core.api | 1 - core/api/core.klib.api | 4 +- gateway/api/gateway.api | 5 - gateway/api/gateway.klib.api | 5 +- gateway/src/commonMain/kotlin/Utils.kt | 8 - gradle/libs.versions.toml | 6 +- voice/api/voice.api | 47 +- voice/api/voice.klib.api | 955 +++++++++++------- .../commonMain/kotlin/gateway/VoiceGateway.kt | 6 - 11 files changed, 638 insertions(+), 410 deletions(-) delete mode 100644 gateway/src/commonMain/kotlin/Utils.kt diff --git a/buildSrc/src/main/kotlin/Targets.kt b/buildSrc/src/main/kotlin/Targets.kt index 49765194b41..8188fd9e02e 100644 --- a/buildSrc/src/main/kotlin/Targets.kt +++ b/buildSrc/src/main/kotlin/Targets.kt @@ -1,7 +1,9 @@ import org.gradle.api.tasks.TaskContainer +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.konan.target.HostManager +@OptIn(ExperimentalKotlinGradlePluginApi::class) fun KotlinMultiplatformExtension.targets() { jvm() @@ -37,10 +39,8 @@ fun KotlinMultiplatformExtension.targets() { tvosArm64() tvosSimulatorArm64() - targets.all { - compilations.all { - compilerOptions.options.applyKordCompilerOptions() - } + compilerOptions { + applyKordCompilerOptions() } } diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 9f5ab6bf9a9..df2404123d6 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -51,9 +51,6 @@ kotlin { } sourceSets { - all { - applyKordOptIns() - } commonMain { // mark ksp src dir kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin") diff --git a/core/api/core.api b/core/api/core.api index 19c163b67c2..f677cccc0a6 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -101,7 +101,6 @@ public final class dev/kord/core/Kord$Companion { public final class dev/kord/core/KordKt { public static final fun Kord (Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun Kord$default (Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final synthetic fun getKordLogger ()Lmu/KLogger; public static final fun logCaughtThrowable (Ljava/lang/Throwable;)V } diff --git a/core/api/core.klib.api b/core/api/core.klib.api index 2b551c5bb2a..820b66c4cbc 100644 --- a/core/api/core.klib.api +++ b/core/api/core.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true @@ -11962,8 +11962,6 @@ final val dev.kord.core.cache.data/id // dev.kord.core.cache.data/id|@dev.kord.c final fun (dev.kord.core.cache.data/VoiceStateData).(): kotlin/String // dev.kord.core.cache.data/id.|@dev.kord.core.cache.data.VoiceStateData(){}[0] final val dev.kord.core.entity/effectiveName // dev.kord.core.entity/effectiveName|@dev.kord.core.entity.User{}effectiveName[0] final fun (dev.kord.core.entity/User).(): kotlin/String // dev.kord.core.entity/effectiveName.|@dev.kord.core.entity.User(){}[0] -final val dev.kord.core/kordLogger // dev.kord.core/kordLogger|{}kordLogger[0] - final fun (): mu/KLogger // dev.kord.core/kordLogger.|(){}[0] final fun (dev.kord.cache.api/DataCache).dev.kord.core.cache/createView(): dev.kord.core.cache/DataCacheView // dev.kord.core.cache/createView|createView@dev.kord.cache.api.DataCache(){}[0] final fun (dev.kord.common.entity/DiscordChannel).dev.kord.core.cache.data/toData(): dev.kord.core.cache.data/ChannelData // dev.kord.core.cache.data/toData|toData@dev.kord.common.entity.DiscordChannel(){}[0] diff --git a/gateway/api/gateway.api b/gateway/api/gateway.api index 25ff7ab3bb0..dc8837f14cb 100644 --- a/gateway/api/gateway.api +++ b/gateway/api/gateway.api @@ -668,7 +668,6 @@ public final class dev/kord/gateway/GatewayConfigurationBuilder { public final class dev/kord/gateway/GatewayKt { public static final fun editPresence (Ldev/kord/gateway/Gateway;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final synthetic fun getGatewayOnLogger ()Lmu/KLogger; public static final fun logCaughtThrowable (Ljava/lang/Throwable;)V public static final fun requestGuildMembers (Ldev/kord/gateway/Gateway;Ldev/kord/common/entity/Snowflake;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/flow/Flow; public static final fun requestGuildMembers (Ldev/kord/gateway/Gateway;Ldev/kord/gateway/RequestGuildMembers;)Lkotlinx/coroutines/flow/Flow; @@ -1875,10 +1874,6 @@ public final class dev/kord/gateway/UserUpdate : dev/kord/gateway/DispatchEvent public fun toString ()Ljava/lang/String; } -public final class dev/kord/gateway/UtilsKt { - public static final synthetic fun error (Lmu/KLogger;Ljava/lang/Throwable;)V -} - public final class dev/kord/gateway/VoiceServerUpdate : dev/kord/gateway/DispatchEvent { public fun (Ldev/kord/common/entity/DiscordVoiceServerUpdateData;Ljava/lang/Integer;)V public final fun component1 ()Ldev/kord/common/entity/DiscordVoiceServerUpdateData; diff --git a/gateway/api/gateway.klib.api b/gateway/api/gateway.klib.api index 7b9f0fb7d31..e2f23910a6c 100644 --- a/gateway/api/gateway.klib.api +++ b/gateway/api/gateway.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [js] +// Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true @@ -2259,12 +2259,9 @@ final val dev.kord.gateway/NON_PRIVILEGED // dev.kord.gateway/NON_PRIVILEGED|@de final fun (dev.kord.gateway/Intents.Companion).(): dev.kord.gateway/Intents // dev.kord.gateway/NON_PRIVILEGED.|@dev.kord.gateway.Intents.Companion(){}[0] final val dev.kord.gateway/PRIVILEGED // dev.kord.gateway/PRIVILEGED|@dev.kord.gateway.Intents.Companion{}PRIVILEGED[0] final fun (dev.kord.gateway/Intents.Companion).(): dev.kord.gateway/Intents // dev.kord.gateway/PRIVILEGED.|@dev.kord.gateway.Intents.Companion(){}[0] -final val dev.kord.gateway/gatewayOnLogger // dev.kord.gateway/gatewayOnLogger|{}gatewayOnLogger[0] - final fun (): mu/KLogger // dev.kord.gateway/gatewayOnLogger.|(){}[0] final fun (dev.kord.gateway/Gateway).dev.kord.gateway/requestGuildMembers(dev.kord.common.entity/Snowflake, kotlin/Function1 = ...): kotlinx.coroutines.flow/Flow // dev.kord.gateway/requestGuildMembers|requestGuildMembers@dev.kord.gateway.Gateway(dev.kord.common.entity.Snowflake;kotlin.Function1){}[0] final fun (dev.kord.gateway/Gateway).dev.kord.gateway/requestGuildMembers(dev.kord.gateway/RequestGuildMembers): kotlinx.coroutines.flow/Flow // dev.kord.gateway/requestGuildMembers|requestGuildMembers@dev.kord.gateway.Gateway(dev.kord.gateway.RequestGuildMembers){}[0] -final fun (mu/KLogger).dev.kord.gateway/error(kotlin/Throwable) // dev.kord.gateway/error|error@mu.KLogger(kotlin.Throwable){}[0] final fun dev.kord.gateway.ratelimit/IdentifyRateLimiter(kotlin/Int, kotlinx.coroutines/CoroutineDispatcher = ...): dev.kord.gateway.ratelimit/IdentifyRateLimiter // dev.kord.gateway.ratelimit/IdentifyRateLimiter|IdentifyRateLimiter(kotlin.Int;kotlinx.coroutines.CoroutineDispatcher){}[0] final fun dev.kord.gateway/Intents(kotlin.collections/Iterable): dev.kord.gateway/Intents // dev.kord.gateway/Intents|Intents(kotlin.collections.Iterable){}[0] final fun dev.kord.gateway/Intents(kotlin.collections/Iterable): dev.kord.gateway/Intents // dev.kord.gateway/Intents|Intents(kotlin.collections.Iterable){}[0] diff --git a/gateway/src/commonMain/kotlin/Utils.kt b/gateway/src/commonMain/kotlin/Utils.kt deleted file mode 100644 index 18cca4075a0..00000000000 --- a/gateway/src/commonMain/kotlin/Utils.kt +++ /dev/null @@ -1,8 +0,0 @@ -package dev.kord.gateway - -import mu.KLogger - -@Suppress("DeprecatedCallableAddReplaceWith") -@Deprecated("Binary compatibility, remove after deprecation cycle.", level = DeprecationLevel.ERROR) -@PublishedApi -internal fun KLogger.error(throwable: Throwable): Unit = error(throwable) { "" } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bc1e92cb702..8863602633f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ kotlin-node = "20.11.30-pre.765" # https://github.com/JetBrains/kotlin-wrappers bignum = "0.3.9" # https://github.com/ionspin/kotlin-multiplatform-bignum stately = "2.0.7" # https://github.com/touchlab/Stately fastZlib = "2.0.1" # https://github.com/timotejroiko/fast-zlib -sodium = "0.9.1" # https://github.com/ionspin/kotlin-multiplatform-libsodium +sodium = "0.9.2" # https://github.com/ionspin/kotlin-multiplatform-libsodium # code generation ksp = "2.0.0-1.0.22" # https://github.com/google/ksp @@ -27,14 +27,14 @@ junit-platform = "1.10.3" mockk = "1.13.11" # https://github.com/mockk/mockk bson = "5.1.1" # https://github.com/mongodb/mongo-java-driver kbson = "0.5.0" # https://github.com/jershell/kbson -kotlinx-io = "0.3.0" # https://github.com/Kotlin/kotlinx-io +kotlinx-io = "0.4.0" # https://github.com/Kotlin/kotlinx-io # plugins dokka = "1.9.20" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.25.0" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.15.0-Beta.3" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "5.3.5" # https://github.com/gmazzo/gradle-buildconfig-plugin -kord-gradle-tools = "1.5.3" # https://github.com/kordlib/gradle-tools +kord-gradle-tools = "1.6.0" # https://github.com/kordlib/gradle-tools maven-publish-plugin = "0.27.0" # https://github.com/vanniktech/gradle-maven-publish-plugin [libraries] diff --git a/voice/api/voice.api b/voice/api/voice.api index 2bdd226cdc1..085c7a52ed8 100644 --- a/voice/api/voice.api +++ b/voice/api/voice.api @@ -317,7 +317,7 @@ public final class dev/kord/voice/SpeakingFlags$Companion { } public final class dev/kord/voice/VoiceConnection { - public synthetic fun (Ldev/kord/voice/VoiceConnectionData;Ldev/kord/gateway/Gateway;Ldev/kord/voice/gateway/VoiceGateway;Ldev/kord/voice/udp/VoiceUdpSocket;Ldev/kord/voice/gateway/VoiceGatewayConfiguration;Ldev/kord/voice/streams/Streams;Ldev/kord/voice/AudioProvider;Ldev/kord/voice/FrameInterceptor;Ldev/kord/voice/udp/AudioFrameSender;Ldev/kord/voice/encryption/strategies/NonceStrategy;JLkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Lkotlinx/coroutines/CoroutineScope;Ldev/kord/voice/VoiceConnectionData;Ldev/kord/gateway/Gateway;Ldev/kord/voice/gateway/VoiceGateway;Ldev/kord/voice/udp/VoiceUdpSocket;Ldev/kord/voice/gateway/VoiceGatewayConfiguration;Ldev/kord/voice/streams/Streams;Ldev/kord/voice/AudioProvider;Ldev/kord/voice/FrameInterceptor;Ldev/kord/voice/udp/AudioFrameSender;Ldev/kord/voice/encryption/strategies/NonceStrategy;JLkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun connect (Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun connect$default (Ldev/kord/voice/VoiceConnection;Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public final fun disconnect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -348,6 +348,7 @@ public final class dev/kord/voice/VoiceConnectionBuilder { public final fun getAudioSender ()Ldev/kord/voice/udp/AudioFrameSender; public final fun getChannelId ()Ldev/kord/common/entity/Snowflake; public final fun getConnectionDetachDuration-UwyO8pc ()J + public final fun getDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher; public final fun getFrameInterceptor ()Ldev/kord/voice/FrameInterceptor; public final fun getGateway ()Ldev/kord/gateway/Gateway; public final fun getGuildId ()Ldev/kord/common/entity/Snowflake; @@ -363,6 +364,7 @@ public final class dev/kord/voice/VoiceConnectionBuilder { public final fun setAudioSender (Ldev/kord/voice/udp/AudioFrameSender;)V public final fun setChannelId (Ldev/kord/common/entity/Snowflake;)V public final fun setConnectionDetachDuration-LRDsOJo (J)V + public final fun setDispatcher (Lkotlinx/coroutines/CoroutineDispatcher;)V public final fun setFrameInterceptor (Ldev/kord/voice/FrameInterceptor;)V public final fun setGateway (Ldev/kord/gateway/Gateway;)V public final fun setGuildId (Ldev/kord/common/entity/Snowflake;)V @@ -988,7 +990,6 @@ public final class dev/kord/voice/gateway/VoiceGatewayConfiguration { } public final class dev/kord/voice/gateway/VoiceGatewayKt { - public static final synthetic fun getVoiceGatewayOnLogger ()Lmu/KLogger; public static final fun logCaughtThrowable (Ljava/lang/Throwable;)V } @@ -1069,7 +1070,7 @@ public final class dev/kord/voice/streams/DefaultStreams : dev/kord/voice/stream public synthetic fun getIncomingUserStreams ()Lkotlinx/coroutines/flow/Flow; public fun getIncomingUserStreams ()Lkotlinx/coroutines/flow/SharedFlow; public fun getSsrcToUser ()Ljava/util/Map; - public fun listen ([BLio/ktor/network/sockets/SocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun listen ([BLio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class dev/kord/voice/streams/NOPStreams : dev/kord/voice/streams/Streams { @@ -1078,7 +1079,7 @@ public final class dev/kord/voice/streams/NOPStreams : dev/kord/voice/streams/St public fun getIncomingAudioPackets ()Lkotlinx/coroutines/flow/Flow; public fun getIncomingUserStreams ()Lkotlinx/coroutines/flow/Flow; public fun getSsrcToUser ()Ljava/util/Map; - public fun listen ([BLio/ktor/network/sockets/SocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun listen ([BLio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public abstract interface class dev/kord/voice/streams/Streams { @@ -1086,7 +1087,7 @@ public abstract interface class dev/kord/voice/streams/Streams { public abstract fun getIncomingAudioPackets ()Lkotlinx/coroutines/flow/Flow; public abstract fun getIncomingUserStreams ()Lkotlinx/coroutines/flow/Flow; public abstract fun getSsrcToUser ()Ljava/util/Map; - public abstract fun listen ([BLio/ktor/network/sockets/SocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun listen ([BLio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public abstract interface class dev/kord/voice/udp/AudioFrameSender { @@ -1094,17 +1095,17 @@ public abstract interface class dev/kord/voice/udp/AudioFrameSender { } public final class dev/kord/voice/udp/AudioFrameSenderConfiguration { - public synthetic fun (Lio/ktor/network/sockets/SocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Lio/ktor/network/sockets/SocketAddress; + public synthetic fun (Lio/ktor/network/sockets/InetSocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Lio/ktor/network/sockets/InetSocketAddress; public final fun component2-pVg5ArA ()I public final fun component3 ()[B public final fun component4 ()Ldev/kord/voice/FrameInterceptorConfiguration; - public final fun copy-Yuhug_o (Lio/ktor/network/sockets/SocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;)Ldev/kord/voice/udp/AudioFrameSenderConfiguration; - public static synthetic fun copy-Yuhug_o$default (Ldev/kord/voice/udp/AudioFrameSenderConfiguration;Lio/ktor/network/sockets/SocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;ILjava/lang/Object;)Ldev/kord/voice/udp/AudioFrameSenderConfiguration; + public final fun copy-Yuhug_o (Lio/ktor/network/sockets/InetSocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;)Ldev/kord/voice/udp/AudioFrameSenderConfiguration; + public static synthetic fun copy-Yuhug_o$default (Ldev/kord/voice/udp/AudioFrameSenderConfiguration;Lio/ktor/network/sockets/InetSocketAddress;I[BLdev/kord/voice/FrameInterceptorConfiguration;ILjava/lang/Object;)Ldev/kord/voice/udp/AudioFrameSenderConfiguration; public fun equals (Ljava/lang/Object;)Z public final fun getInterceptorConfiguration ()Ldev/kord/voice/FrameInterceptorConfiguration; public final fun getKey ()[B - public final fun getServer ()Lio/ktor/network/sockets/SocketAddress; + public final fun getServer ()Lio/ktor/network/sockets/InetSocketAddress; public final fun getSsrc-pVg5ArA ()I public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -1140,17 +1141,17 @@ public final class dev/kord/voice/udp/DefaultAudioFrameSenderData { public fun toString ()Ljava/lang/String; } -public final class dev/kord/voice/udp/DefaultAudioPacketProvider : dev/kord/voice/udp/AudioPacketProvider { +public final class dev/kord/voice/udp/DefaultAudioPacketProviderKt { + public static final fun DefaultAudioPacketProvider ([BLdev/kord/voice/encryption/strategies/NonceStrategy;)Ldev/kord/voice/udp/AudioPacketProvider; +} + +public final class dev/kord/voice/udp/DefaultJvmAudioPacketProvider : dev/kord/voice/udp/AudioPacketProvider { public fun ([BLdev/kord/voice/encryption/strategies/NonceStrategy;)V public fun provide-jfaDVJw (SII[B)Ldev/kord/voice/io/ByteArrayView; } -public final class dev/kord/voice/udp/GlobalVoiceUdpSocket : dev/kord/voice/udp/VoiceUdpSocket { - public static final field INSTANCE Ldev/kord/voice/udp/GlobalVoiceUdpSocket; - public fun discoverIp (Lio/ktor/network/sockets/InetSocketAddress;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun getIncoming ()Lkotlinx/coroutines/flow/SharedFlow; - public fun send (Lio/ktor/network/sockets/Datagram;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun stop (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +public final class dev/kord/voice/udp/IpDiscoveryKt { + public static final fun discoverIP (Ldev/kord/voice/udp/VoiceUdpSocket;Lio/ktor/network/sockets/InetSocketAddress;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; } public abstract class dev/kord/voice/udp/PayloadType { @@ -1173,6 +1174,7 @@ public final class dev/kord/voice/udp/PayloadType$Companion { public final class dev/kord/voice/udp/PayloadType$Unknown : dev/kord/voice/udp/PayloadType { public fun (B)V + public fun toString ()Ljava/lang/String; } public final class dev/kord/voice/udp/RTPPacket { @@ -1242,9 +1244,8 @@ public final class dev/kord/voice/udp/RTPPacketKt { public abstract interface class dev/kord/voice/udp/VoiceUdpSocket { public static final field Companion Ldev/kord/voice/udp/VoiceUdpSocket$Companion; - public abstract fun discoverIp (Lio/ktor/network/sockets/InetSocketAddress;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun getIncoming ()Lkotlinx/coroutines/flow/SharedFlow; - public abstract fun send (Lio/ktor/network/sockets/Datagram;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun all (Lio/ktor/network/sockets/InetSocketAddress;)Lkotlinx/coroutines/flow/Flow; + public abstract fun send (Lio/ktor/network/sockets/InetSocketAddress;Ldev/kord/voice/io/ByteArrayView;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun stop (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } @@ -1253,6 +1254,10 @@ public final class dev/kord/voice/udp/VoiceUdpSocket$Companion { } public final class dev/kord/voice/udp/VoiceUdpSocketKt { - public static final fun receiveFrom (Ldev/kord/voice/udp/VoiceUdpSocket;Lio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun recv (Ldev/kord/voice/udp/VoiceUdpSocket;Lio/ktor/network/sockets/InetSocketAddress;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class dev/kord/voice/udp/VoiceUdpSocket_ktorKt { + public static final fun getGlobalVoiceUdpSocket ()Ldev/kord/voice/udp/VoiceUdpSocket; } diff --git a/voice/api/voice.klib.api b/voice/api/voice.klib.api index 3c017fc30fc..4291e74d795 100644 --- a/voice/api/voice.klib.api +++ b/voice/api/voice.klib.api @@ -8,36 +8,61 @@ // - Show declarations: true // Library unique name: -abstract class dev.kord.voice.udp/AudioPacketProvider { // dev.kord.voice.udp/AudioPacketProvider|null[0] - abstract fun provide(kotlin/UShort, kotlin/UInt, kotlin/UInt, kotlin/ByteArray): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/AudioPacketProvider.provide|provide(kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.ByteArray){}[0] - constructor (kotlin/ByteArray, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.udp/AudioPacketProvider.|(kotlin.ByteArray;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] - final val key // dev.kord.voice.udp/AudioPacketProvider.key|{}key[0] - final fun (): kotlin/ByteArray // dev.kord.voice.udp/AudioPacketProvider.key.|(){}[0] - final val nonceStrategy // dev.kord.voice.udp/AudioPacketProvider.nonceStrategy|{}nonceStrategy[0] - final fun (): dev.kord.voice.encryption.strategies/NonceStrategy // dev.kord.voice.udp/AudioPacketProvider.nonceStrategy.|(){}[0] +final enum class dev.kord.voice.gateway/OpCode : kotlin/Enum { // dev.kord.voice.gateway/OpCode|null[0] + enum entry ClientDisconnect // dev.kord.voice.gateway/OpCode.ClientDisconnect|null[0] + enum entry Heartbeat // dev.kord.voice.gateway/OpCode.Heartbeat|null[0] + enum entry HeartbeatAck // dev.kord.voice.gateway/OpCode.HeartbeatAck|null[0] + enum entry Hello // dev.kord.voice.gateway/OpCode.Hello|null[0] + enum entry Identify // dev.kord.voice.gateway/OpCode.Identify|null[0] + enum entry Ready // dev.kord.voice.gateway/OpCode.Ready|null[0] + enum entry Resume // dev.kord.voice.gateway/OpCode.Resume|null[0] + enum entry Resumed // dev.kord.voice.gateway/OpCode.Resumed|null[0] + enum entry SelectProtocol // dev.kord.voice.gateway/OpCode.SelectProtocol|null[0] + enum entry SessionDescription // dev.kord.voice.gateway/OpCode.SessionDescription|null[0] + enum entry Speaking // dev.kord.voice.gateway/OpCode.Speaking|null[0] + enum entry Unknown // dev.kord.voice.gateway/OpCode.Unknown|null[0] + + final val code // dev.kord.voice.gateway/OpCode.code|{}code[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/OpCode.code.|(){}[0] + final val entries // dev.kord.voice.gateway/OpCode.entries|#static{}entries[0] + final fun (): kotlin.enums/EnumEntries // dev.kord.voice.gateway/OpCode.entries.|#static(){}[0] + + final fun valueOf(kotlin/String): dev.kord.voice.gateway/OpCode // dev.kord.voice.gateway/OpCode.valueOf|valueOf#static(kotlin.String){}[0] + final fun values(): kotlin/Array // dev.kord.voice.gateway/OpCode.values|values#static(){}[0] + + final object Companion : kotlinx.serialization.internal/SerializerFactory { // dev.kord.voice.gateway/OpCode.Companion|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/OpCode.Companion.serializer|serializer(){}[0] + final fun serializer(kotlin/Array>...): kotlinx.serialization/KSerializer<*> // dev.kord.voice.gateway/OpCode.Companion.serializer|serializer(kotlin.Array>...){}[0] + } } + abstract fun interface dev.kord.voice/AudioProvider { // dev.kord.voice/AudioProvider|null[0] abstract suspend fun provide(): dev.kord.voice/AudioFrame? // dev.kord.voice/AudioProvider.provide|provide(){}[0] open suspend fun (kotlinx.coroutines/CoroutineScope).provideFrames(kotlinx.coroutines.channels/SendChannel) // dev.kord.voice/AudioProvider.provideFrames|provideFrames@kotlinx.coroutines.CoroutineScope(kotlinx.coroutines.channels.SendChannel){}[0] } + abstract fun interface dev.kord.voice/FrameInterceptor { // dev.kord.voice/FrameInterceptor|null[0] abstract fun (kotlinx.coroutines.flow/Flow).intercept(dev.kord.voice/FrameInterceptorConfiguration): kotlinx.coroutines.flow/Flow // dev.kord.voice/FrameInterceptor.intercept|intercept@kotlinx.coroutines.flow.Flow(dev.kord.voice.FrameInterceptorConfiguration){}[0] } + abstract interface dev.kord.voice.gateway/VoiceGateway { // dev.kord.voice.gateway/VoiceGateway|null[0] - abstract suspend fun detach() // dev.kord.voice.gateway/VoiceGateway.detach|detach(){}[0] - abstract suspend fun send(dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/VoiceGateway.send|send(dev.kord.voice.gateway.Command){}[0] - abstract suspend fun start(dev.kord.voice.gateway/VoiceGatewayConfiguration) // dev.kord.voice.gateway/VoiceGateway.start|start(dev.kord.voice.gateway.VoiceGatewayConfiguration){}[0] - abstract suspend fun stop() // dev.kord.voice.gateway/VoiceGateway.stop|stop(){}[0] abstract val events // dev.kord.voice.gateway/VoiceGateway.events|{}events[0] abstract fun (): kotlinx.coroutines.flow/SharedFlow // dev.kord.voice.gateway/VoiceGateway.events.|(){}[0] abstract val ping // dev.kord.voice.gateway/VoiceGateway.ping|{}ping[0] abstract fun (): kotlinx.coroutines.flow/StateFlow // dev.kord.voice.gateway/VoiceGateway.ping.|(){}[0] abstract val scope // dev.kord.voice.gateway/VoiceGateway.scope|{}scope[0] abstract fun (): kotlinx.coroutines/CoroutineScope // dev.kord.voice.gateway/VoiceGateway.scope.|(){}[0] + + abstract suspend fun detach() // dev.kord.voice.gateway/VoiceGateway.detach|detach(){}[0] + abstract suspend fun send(dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/VoiceGateway.send|send(dev.kord.voice.gateway.Command){}[0] + abstract suspend fun start(dev.kord.voice.gateway/VoiceGatewayConfiguration) // dev.kord.voice.gateway/VoiceGateway.start|start(dev.kord.voice.gateway.VoiceGatewayConfiguration){}[0] + abstract suspend fun stop() // dev.kord.voice.gateway/VoiceGateway.stop|stop(){}[0] + final object Companion { // dev.kord.voice.gateway/VoiceGateway.Companion|null[0] final fun none(): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice.gateway/VoiceGateway.Companion.none|none(){}[0] } } + abstract interface dev.kord.voice.streams/Streams { // dev.kord.voice.streams/Streams|null[0] abstract val incomingAudioFrames // dev.kord.voice.streams/Streams.incomingAudioFrames|{}incomingAudioFrames[0] abstract fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/Streams.incomingAudioFrames.|(){}[0] @@ -47,79 +72,123 @@ abstract interface dev.kord.voice.streams/Streams { // dev.kord.voice.streams/St abstract fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/Streams.incomingUserStreams.|(){}[0] abstract val ssrcToUser // dev.kord.voice.streams/Streams.ssrcToUser|{}ssrcToUser[0] abstract fun (): kotlin.collections/Map // dev.kord.voice.streams/Streams.ssrcToUser.|(){}[0] + // Targets: [apple, linux] abstract suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/Streams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [js, mingwX64] abstract suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/Streams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } + abstract interface dev.kord.voice.udp/AudioFrameSender { // dev.kord.voice.udp/AudioFrameSender|null[0] abstract suspend fun start(dev.kord.voice.udp/AudioFrameSenderConfiguration) // dev.kord.voice.udp/AudioFrameSender.start|start(dev.kord.voice.udp.AudioFrameSenderConfiguration){}[0] } + abstract interface dev.kord.voice.udp/VoiceUdpSocket { // dev.kord.voice.udp/VoiceUdpSocket|null[0] abstract suspend fun stop() // dev.kord.voice.udp/VoiceUdpSocket.stop|stop(){}[0] + final object Companion { // dev.kord.voice.udp/VoiceUdpSocket.Companion|null[0] final fun none(): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/VoiceUdpSocket.Companion.none|none(){}[0] } + // Targets: [apple, linux] abstract fun all(io.ktor.network.sockets/InetSocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [apple, linux] abstract suspend fun send(io.ktor.network.sockets/InetSocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(io.ktor.network.sockets.InetSocketAddress;dev.kord.voice.io.ByteArrayView){}[0] + // Targets: [js, mingwX64] abstract fun all(dev.kord.voice.udp/SocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(dev.kord.voice.udp.SocketAddress){}[0] + // Targets: [js, mingwX64] abstract suspend fun send(dev.kord.voice.udp/SocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(dev.kord.voice.udp.SocketAddress;dev.kord.voice.io.ByteArrayView){}[0] } + +sealed interface dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/NonceStrategy|null[0] + abstract val nonceLength // dev.kord.voice.encryption.strategies/NonceStrategy.nonceLength|{}nonceLength[0] + abstract fun (): kotlin/Int // dev.kord.voice.encryption.strategies/NonceStrategy.nonceLength.|(){}[0] + + abstract fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/NonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] + abstract fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NonceStrategy.generate|generate(kotlin.Function0){}[0] + abstract fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] +} + +abstract class dev.kord.voice.udp/AudioPacketProvider { // dev.kord.voice.udp/AudioPacketProvider|null[0] + constructor (kotlin/ByteArray, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.udp/AudioPacketProvider.|(kotlin.ByteArray;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] + + final val key // dev.kord.voice.udp/AudioPacketProvider.key|{}key[0] + final fun (): kotlin/ByteArray // dev.kord.voice.udp/AudioPacketProvider.key.|(){}[0] + final val nonceStrategy // dev.kord.voice.udp/AudioPacketProvider.nonceStrategy|{}nonceStrategy[0] + final fun (): dev.kord.voice.encryption.strategies/NonceStrategy // dev.kord.voice.udp/AudioPacketProvider.nonceStrategy.|(){}[0] + + abstract fun provide(kotlin/UShort, kotlin/UInt, kotlin/UInt, kotlin/ByteArray): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/AudioPacketProvider.provide|provide(kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.ByteArray){}[0] +} + final class dev.kord.voice.encryption.strategies/LiteNonceStrategy : dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/LiteNonceStrategy|null[0] constructor () // dev.kord.voice.encryption.strategies/LiteNonceStrategy.|(){}[0] + + final val nonceLength // dev.kord.voice.encryption.strategies/LiteNonceStrategy.nonceLength|{}nonceLength[0] + final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/LiteNonceStrategy.nonceLength.|(){}[0] + final fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/LiteNonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] final fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/LiteNonceStrategy.generate|generate(kotlin.Function0){}[0] final fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/LiteNonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] - final val nonceLength // dev.kord.voice.encryption.strategies/LiteNonceStrategy.nonceLength|{}nonceLength[0] - final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/LiteNonceStrategy.nonceLength.|(){}[0] } + final class dev.kord.voice.encryption.strategies/NormalNonceStrategy : dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/NormalNonceStrategy|null[0] constructor () // dev.kord.voice.encryption.strategies/NormalNonceStrategy.|(){}[0] + + final val nonceLength // dev.kord.voice.encryption.strategies/NormalNonceStrategy.nonceLength|{}nonceLength[0] + final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/NormalNonceStrategy.nonceLength.|(){}[0] + final fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/NormalNonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] final fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NormalNonceStrategy.generate|generate(kotlin.Function0){}[0] final fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NormalNonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] - final val nonceLength // dev.kord.voice.encryption.strategies/NormalNonceStrategy.nonceLength|{}nonceLength[0] - final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/NormalNonceStrategy.nonceLength.|(){}[0] } + final class dev.kord.voice.encryption.strategies/SuffixNonceStrategy : dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/SuffixNonceStrategy|null[0] constructor () // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.|(){}[0] + + final val nonceLength // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.nonceLength|{}nonceLength[0] + final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.nonceLength.|(){}[0] + final fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] final fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.generate|generate(kotlin.Function0){}[0] final fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] - final val nonceLength // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.nonceLength|{}nonceLength[0] - final fun (): kotlin/Int // dev.kord.voice.encryption.strategies/SuffixNonceStrategy.nonceLength.|(){}[0] } + final class dev.kord.voice.exception/VoiceConnectionInitializationException : kotlin/Exception { // dev.kord.voice.exception/VoiceConnectionInitializationException|null[0] constructor (kotlin/String) // dev.kord.voice.exception/VoiceConnectionInitializationException.|(kotlin.String){}[0] constructor (kotlin/String, kotlin/Throwable) // dev.kord.voice.exception/VoiceConnectionInitializationException.|(kotlin.String;kotlin.Throwable){}[0] constructor (kotlin/Throwable) // dev.kord.voice.exception/VoiceConnectionInitializationException.|(kotlin.Throwable){}[0] } + final class dev.kord.voice.gateway/DefaultVoiceGateway : dev.kord.voice.gateway/VoiceGateway { // dev.kord.voice.gateway/DefaultVoiceGateway|null[0] constructor (dev.kord.voice.gateway/DefaultVoiceGatewayData) // dev.kord.voice.gateway/DefaultVoiceGateway.|(dev.kord.voice.gateway.DefaultVoiceGatewayData){}[0] - final suspend fun detach() // dev.kord.voice.gateway/DefaultVoiceGateway.detach|detach(){}[0] - final suspend fun send(dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/DefaultVoiceGateway.send|send(dev.kord.voice.gateway.Command){}[0] - final suspend fun start(dev.kord.voice.gateway/VoiceGatewayConfiguration) // dev.kord.voice.gateway/DefaultVoiceGateway.start|start(dev.kord.voice.gateway.VoiceGatewayConfiguration){}[0] - final suspend fun stop() // dev.kord.voice.gateway/DefaultVoiceGateway.stop|stop(){}[0] + final val events // dev.kord.voice.gateway/DefaultVoiceGateway.events|{}events[0] final fun (): kotlinx.coroutines.flow/SharedFlow // dev.kord.voice.gateway/DefaultVoiceGateway.events.|(){}[0] final val ping // dev.kord.voice.gateway/DefaultVoiceGateway.ping|{}ping[0] final fun (): kotlinx.coroutines.flow/StateFlow // dev.kord.voice.gateway/DefaultVoiceGateway.ping.|(){}[0] final val scope // dev.kord.voice.gateway/DefaultVoiceGateway.scope|{}scope[0] final fun (): kotlinx.coroutines/CoroutineScope // dev.kord.voice.gateway/DefaultVoiceGateway.scope.|(){}[0] + + final suspend fun detach() // dev.kord.voice.gateway/DefaultVoiceGateway.detach|detach(){}[0] + final suspend fun send(dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/DefaultVoiceGateway.send|send(dev.kord.voice.gateway.Command){}[0] + final suspend fun start(dev.kord.voice.gateway/VoiceGatewayConfiguration) // dev.kord.voice.gateway/DefaultVoiceGateway.start|start(dev.kord.voice.gateway.VoiceGatewayConfiguration){}[0] + final suspend fun stop() // dev.kord.voice.gateway/DefaultVoiceGateway.stop|stop(){}[0] } + final class dev.kord.voice.gateway/DefaultVoiceGatewayBuilder { // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder|null[0] constructor (dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/String) // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.|(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String){}[0] - final fun build(): dev.kord.voice.gateway/DefaultVoiceGateway // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.build|build(){}[0] + final val guildId // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.guildId|{}guildId[0] final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.guildId.|(){}[0] final val selfId // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.selfId|{}selfId[0] final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.selfId.|(){}[0] final val sessionId // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.sessionId|{}sessionId[0] final fun (): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.sessionId.|(){}[0] + final var client // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.client|{}client[0] final fun (): io.ktor.client/HttpClient? // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.client.|(){}[0] final fun (io.ktor.client/HttpClient?) // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.client.|(io.ktor.client.HttpClient?){}[0] @@ -129,19 +198,13 @@ final class dev.kord.voice.gateway/DefaultVoiceGatewayBuilder { // dev.kord.voic final var reconnectRetry // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.reconnectRetry|{}reconnectRetry[0] final fun (): dev.kord.gateway.retry/Retry? // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.reconnectRetry.|(){}[0] final fun (dev.kord.gateway.retry/Retry?) // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.reconnectRetry.|(dev.kord.gateway.retry.Retry?){}[0] + + final fun build(): dev.kord.voice.gateway/DefaultVoiceGateway // dev.kord.voice.gateway/DefaultVoiceGatewayBuilder.build|build(){}[0] } + final class dev.kord.voice.gateway/DefaultVoiceGatewayData { // dev.kord.voice.gateway/DefaultVoiceGatewayData|null[0] constructor (dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/String, io.ktor.client/HttpClient, dev.kord.gateway.retry/Retry, kotlinx.coroutines.flow/MutableSharedFlow) // dev.kord.voice.gateway/DefaultVoiceGatewayData.|(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;kotlinx.coroutines.flow.MutableSharedFlow){}[0] - final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.component1|component1(){}[0] - final fun component2(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.component2|component2(){}[0] - final fun component3(): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayData.component3|component3(){}[0] - final fun component4(): io.ktor.client/HttpClient // dev.kord.voice.gateway/DefaultVoiceGatewayData.component4|component4(){}[0] - final fun component5(): dev.kord.gateway.retry/Retry // dev.kord.voice.gateway/DefaultVoiceGatewayData.component5|component5(){}[0] - final fun component6(): kotlinx.coroutines.flow/MutableSharedFlow // dev.kord.voice.gateway/DefaultVoiceGatewayData.component6|component6(){}[0] - final fun copy(dev.kord.common.entity/Snowflake =..., dev.kord.common.entity/Snowflake =..., kotlin/String =..., io.ktor.client/HttpClient =..., dev.kord.gateway.retry/Retry =..., kotlinx.coroutines.flow/MutableSharedFlow =...): dev.kord.voice.gateway/DefaultVoiceGatewayData // dev.kord.voice.gateway/DefaultVoiceGatewayData.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;kotlinx.coroutines.flow.MutableSharedFlow){}[0] - final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/DefaultVoiceGatewayData.equals|equals(kotlin.Any?){}[0] - final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/DefaultVoiceGatewayData.hashCode|hashCode(){}[0] - final fun toString(): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayData.toString|toString(){}[0] + final val client // dev.kord.voice.gateway/DefaultVoiceGatewayData.client|{}client[0] final fun (): io.ktor.client/HttpClient // dev.kord.voice.gateway/DefaultVoiceGatewayData.client.|(){}[0] final val eventFlow // dev.kord.voice.gateway/DefaultVoiceGatewayData.eventFlow|{}eventFlow[0] @@ -154,345 +217,439 @@ final class dev.kord.voice.gateway/DefaultVoiceGatewayData { // dev.kord.voice.g final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.selfId.|(){}[0] final val sessionId // dev.kord.voice.gateway/DefaultVoiceGatewayData.sessionId|{}sessionId[0] final fun (): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayData.sessionId.|(){}[0] + + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.component1|component1(){}[0] + final fun component2(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/DefaultVoiceGatewayData.component2|component2(){}[0] + final fun component3(): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayData.component3|component3(){}[0] + final fun component4(): io.ktor.client/HttpClient // dev.kord.voice.gateway/DefaultVoiceGatewayData.component4|component4(){}[0] + final fun component5(): dev.kord.gateway.retry/Retry // dev.kord.voice.gateway/DefaultVoiceGatewayData.component5|component5(){}[0] + final fun component6(): kotlinx.coroutines.flow/MutableSharedFlow // dev.kord.voice.gateway/DefaultVoiceGatewayData.component6|component6(){}[0] + final fun copy(dev.kord.common.entity/Snowflake = ..., dev.kord.common.entity/Snowflake = ..., kotlin/String = ..., io.ktor.client/HttpClient = ..., dev.kord.gateway.retry/Retry = ..., kotlinx.coroutines.flow/MutableSharedFlow = ...): dev.kord.voice.gateway/DefaultVoiceGatewayData // dev.kord.voice.gateway/DefaultVoiceGatewayData.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;kotlinx.coroutines.flow.MutableSharedFlow){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/DefaultVoiceGatewayData.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/DefaultVoiceGatewayData.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/DefaultVoiceGatewayData.toString|toString(){}[0] } + final class dev.kord.voice.gateway/Heartbeat : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Heartbeat|null[0] constructor (kotlin/Long) // dev.kord.voice.gateway/Heartbeat.|(kotlin.Long){}[0] + + final val nonce // dev.kord.voice.gateway/Heartbeat.nonce|{}nonce[0] + final fun (): kotlin/Long // dev.kord.voice.gateway/Heartbeat.nonce.|(){}[0] + final fun component1(): kotlin/Long // dev.kord.voice.gateway/Heartbeat.component1|component1(){}[0] - final fun copy(kotlin/Long =...): dev.kord.voice.gateway/Heartbeat // dev.kord.voice.gateway/Heartbeat.copy|copy(kotlin.Long){}[0] + final fun copy(kotlin/Long = ...): dev.kord.voice.gateway/Heartbeat // dev.kord.voice.gateway/Heartbeat.copy|copy(kotlin.Long){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Heartbeat.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Heartbeat.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/Heartbeat.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Heartbeat.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/Heartbeat.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Heartbeat.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Heartbeat.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Heartbeat // dev.kord.voice.gateway/Heartbeat.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Heartbeat) // dev.kord.voice.gateway/Heartbeat.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Heartbeat){}[0] - final val descriptor // dev.kord.voice.gateway/Heartbeat.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Heartbeat.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/Heartbeat.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Heartbeat.Companion.serializer|serializer(){}[0] } - final val nonce // dev.kord.voice.gateway/Heartbeat.nonce|(){}[0] - final fun (): kotlin/Long // dev.kord.voice.gateway/Heartbeat.nonce.|(){}[0] } + final class dev.kord.voice.gateway/HeartbeatAck : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/HeartbeatAck|null[0] constructor (kotlin/Long) // dev.kord.voice.gateway/HeartbeatAck.|(kotlin.Long){}[0] + + final val nonce // dev.kord.voice.gateway/HeartbeatAck.nonce|{}nonce[0] + final fun (): kotlin/Long // dev.kord.voice.gateway/HeartbeatAck.nonce.|(){}[0] + final fun component1(): kotlin/Long // dev.kord.voice.gateway/HeartbeatAck.component1|component1(){}[0] - final fun copy(kotlin/Long =...): dev.kord.voice.gateway/HeartbeatAck // dev.kord.voice.gateway/HeartbeatAck.copy|copy(kotlin.Long){}[0] + final fun copy(kotlin/Long = ...): dev.kord.voice.gateway/HeartbeatAck // dev.kord.voice.gateway/HeartbeatAck.copy|copy(kotlin.Long){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/HeartbeatAck.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/HeartbeatAck.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/HeartbeatAck.toString|toString(){}[0] + final object Companion { // dev.kord.voice.gateway/HeartbeatAck.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/HeartbeatAck.Companion.serializer|serializer(){}[0] } - final val nonce // dev.kord.voice.gateway/HeartbeatAck.nonce|{}nonce[0] - final fun (): kotlin/Long // dev.kord.voice.gateway/HeartbeatAck.nonce.|(){}[0] } + final class dev.kord.voice.gateway/Hello : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Hello|null[0] constructor (kotlin/Short, kotlin/Double) // dev.kord.voice.gateway/Hello.|(kotlin.Short;kotlin.Double){}[0] + + final val heartbeatInterval // dev.kord.voice.gateway/Hello.heartbeatInterval|{}heartbeatInterval[0] + final fun (): kotlin/Double // dev.kord.voice.gateway/Hello.heartbeatInterval.|(){}[0] + final val version // dev.kord.voice.gateway/Hello.version|{}version[0] + final fun (): kotlin/Short // dev.kord.voice.gateway/Hello.version.|(){}[0] + final fun component1(): kotlin/Short // dev.kord.voice.gateway/Hello.component1|component1(){}[0] final fun component2(): kotlin/Double // dev.kord.voice.gateway/Hello.component2|component2(){}[0] - final fun copy(kotlin/Short =..., kotlin/Double =...): dev.kord.voice.gateway/Hello // dev.kord.voice.gateway/Hello.copy|copy(kotlin.Short;kotlin.Double){}[0] + final fun copy(kotlin/Short = ..., kotlin/Double = ...): dev.kord.voice.gateway/Hello // dev.kord.voice.gateway/Hello.copy|copy(kotlin.Short;kotlin.Double){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Hello.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Hello.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/Hello.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Hello.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/Hello.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Hello.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Hello.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Hello // dev.kord.voice.gateway/Hello.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Hello) // dev.kord.voice.gateway/Hello.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Hello){}[0] - final val descriptor // dev.kord.voice.gateway/Hello.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Hello.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/Hello.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Hello.Companion.serializer|serializer(){}[0] } - final val heartbeatInterval // dev.kord.voice.gateway/Hello.heartbeatInterval|{}heartbeatInterval[0] - final fun (): kotlin/Double // dev.kord.voice.gateway/Hello.heartbeatInterval.|(){}[0] - final val version // dev.kord.voice.gateway/Hello.version|{}version[0] - final fun (): kotlin/Short // dev.kord.voice.gateway/Hello.version.|(){}[0] } + final class dev.kord.voice.gateway/Identify : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Identify|null[0] constructor (dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/String, kotlin/String) // dev.kord.voice.gateway/Identify.|(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] + + final val serverId // dev.kord.voice.gateway/Identify.serverId|{}serverId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.serverId.|(){}[0] + final val sessionId // dev.kord.voice.gateway/Identify.sessionId|{}sessionId[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Identify.sessionId.|(){}[0] + final val token // dev.kord.voice.gateway/Identify.token|{}token[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Identify.token.|(){}[0] + final val userId // dev.kord.voice.gateway/Identify.userId|{}userId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.userId.|(){}[0] + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.component1|component1(){}[0] final fun component2(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.component2|component2(){}[0] final fun component3(): kotlin/String // dev.kord.voice.gateway/Identify.component3|component3(){}[0] final fun component4(): kotlin/String // dev.kord.voice.gateway/Identify.component4|component4(){}[0] - final fun copy(dev.kord.common.entity/Snowflake =..., dev.kord.common.entity/Snowflake =..., kotlin/String =..., kotlin/String =...): dev.kord.voice.gateway/Identify // dev.kord.voice.gateway/Identify.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] + final fun copy(dev.kord.common.entity/Snowflake = ..., dev.kord.common.entity/Snowflake = ..., kotlin/String = ..., kotlin/String = ...): dev.kord.voice.gateway/Identify // dev.kord.voice.gateway/Identify.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Identify.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Identify.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/Identify.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Identify.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/Identify.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Identify.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Identify.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Identify // dev.kord.voice.gateway/Identify.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Identify) // dev.kord.voice.gateway/Identify.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Identify){}[0] - final val descriptor // dev.kord.voice.gateway/Identify.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Identify.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/Identify.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Identify.Companion.serializer|serializer(){}[0] } - final val serverId // dev.kord.voice.gateway/Identify.serverId|{}serverId[0] - final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.serverId.|(){}[0] - final val sessionId // dev.kord.voice.gateway/Identify.sessionId|{}sessionId[0] - final fun (): kotlin/String // dev.kord.voice.gateway/Identify.sessionId.|(){}[0] - final val token // dev.kord.voice.gateway/Identify.token|{}token[0] - final fun (): kotlin/String // dev.kord.voice.gateway/Identify.token.|(){}[0] - final val userId // dev.kord.voice.gateway/Identify.userId|{}userId[0] - final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Identify.userId.|(){}[0] } + final class dev.kord.voice.gateway/Ready : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Ready|null[0] constructor (kotlin/UInt, kotlin/String, kotlin/Int, kotlin.collections/List) // dev.kord.voice.gateway/Ready.|(kotlin.UInt;kotlin.String;kotlin.Int;kotlin.collections.List){}[0] + + final val ip // dev.kord.voice.gateway/Ready.ip|{}ip[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Ready.ip.|(){}[0] + final val modes // dev.kord.voice.gateway/Ready.modes|{}modes[0] + final fun (): kotlin.collections/List // dev.kord.voice.gateway/Ready.modes.|(){}[0] + final val port // dev.kord.voice.gateway/Ready.port|{}port[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/Ready.port.|(){}[0] + final val ssrc // dev.kord.voice.gateway/Ready.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.gateway/Ready.ssrc.|(){}[0] + final fun component1(): kotlin/UInt // dev.kord.voice.gateway/Ready.component1|component1(){}[0] final fun component2(): kotlin/String // dev.kord.voice.gateway/Ready.component2|component2(){}[0] final fun component3(): kotlin/Int // dev.kord.voice.gateway/Ready.component3|component3(){}[0] final fun component4(): kotlin.collections/List // dev.kord.voice.gateway/Ready.component4|component4(){}[0] - final fun copy(kotlin/UInt =..., kotlin/String =..., kotlin/Int =..., kotlin.collections/List =...): dev.kord.voice.gateway/Ready // dev.kord.voice.gateway/Ready.copy|copy(kotlin.UInt;kotlin.String;kotlin.Int;kotlin.collections.List){}[0] + final fun copy(kotlin/UInt = ..., kotlin/String = ..., kotlin/Int = ..., kotlin.collections/List = ...): dev.kord.voice.gateway/Ready // dev.kord.voice.gateway/Ready.copy|copy(kotlin.UInt;kotlin.String;kotlin.Int;kotlin.collections.List){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Ready.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Ready.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/Ready.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Ready.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/Ready.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Ready.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Ready.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Ready // dev.kord.voice.gateway/Ready.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Ready) // dev.kord.voice.gateway/Ready.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Ready){}[0] - final val descriptor // dev.kord.voice.gateway/Ready.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Ready.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/Ready.Companion|null[0] - final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Ready.Companion.serializer|serializer(){}[0] final val $childSerializers // dev.kord.voice.gateway/Ready.Companion.$childSerializers|{}$childSerializers[0] + + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Ready.Companion.serializer|serializer(){}[0] } - final val ip // dev.kord.voice.gateway/Ready.ip|{}ip[0] - final fun (): kotlin/String // dev.kord.voice.gateway/Ready.ip.|(){}[0] - final val modes // dev.kord.voice.gateway/Ready.modes|{}modes[0] - final fun (): kotlin.collections/List // dev.kord.voice.gateway/Ready.modes.|(){}[0] - final val port // dev.kord.voice.gateway/Ready.port|{}port[0] - final fun (): kotlin/Int // dev.kord.voice.gateway/Ready.port.|(){}[0] - final val ssrc // dev.kord.voice.gateway/Ready.ssrc|{}ssrc[0] - final fun (): kotlin/UInt // dev.kord.voice.gateway/Ready.ssrc.|(){}[0] } + final class dev.kord.voice.gateway/Resume : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Resume|null[0] constructor (dev.kord.common.entity/Snowflake, kotlin/String, kotlin/String) // dev.kord.voice.gateway/Resume.|(dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] + + final val serverId // dev.kord.voice.gateway/Resume.serverId|{}serverId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Resume.serverId.|(){}[0] + final val sessionId // dev.kord.voice.gateway/Resume.sessionId|{}sessionId[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Resume.sessionId.|(){}[0] + final val token // dev.kord.voice.gateway/Resume.token|{}token[0] + final fun (): kotlin/String // dev.kord.voice.gateway/Resume.token.|(){}[0] + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Resume.component1|component1(){}[0] final fun component2(): kotlin/String // dev.kord.voice.gateway/Resume.component2|component2(){}[0] final fun component3(): kotlin/String // dev.kord.voice.gateway/Resume.component3|component3(){}[0] - final fun copy(dev.kord.common.entity/Snowflake =..., kotlin/String =..., kotlin/String =...): dev.kord.voice.gateway/Resume // dev.kord.voice.gateway/Resume.copy|copy(dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] + final fun copy(dev.kord.common.entity/Snowflake = ..., kotlin/String = ..., kotlin/String = ...): dev.kord.voice.gateway/Resume // dev.kord.voice.gateway/Resume.copy|copy(dev.kord.common.entity.Snowflake;kotlin.String;kotlin.String){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Resume.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Resume.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/Resume.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Resume.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/Resume.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Resume.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Resume.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Resume // dev.kord.voice.gateway/Resume.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Resume) // dev.kord.voice.gateway/Resume.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Resume){}[0] - final val descriptor // dev.kord.voice.gateway/Resume.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Resume.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/Resume.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Resume.Companion.serializer|serializer(){}[0] } - final val serverId // dev.kord.voice.gateway/Resume.serverId|{}serverId[0] - final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Resume.serverId.|(){}[0] - final val sessionId // dev.kord.voice.gateway/Resume.sessionId|{}sessionId[0] - final fun (): kotlin/String // dev.kord.voice.gateway/Resume.sessionId.|(){}[0] - final val token // dev.kord.voice.gateway/Resume.token|{}token[0] - final fun (): kotlin/String // dev.kord.voice.gateway/Resume.token.|(){}[0] } + final class dev.kord.voice.gateway/SelectProtocol : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/SelectProtocol|null[0] constructor (kotlin/String, dev.kord.voice.gateway/SelectProtocol.Data) // dev.kord.voice.gateway/SelectProtocol.|(kotlin.String;dev.kord.voice.gateway.SelectProtocol.Data){}[0] - final class Data { // dev.kord.voice.gateway/SelectProtocol.Data|null[0] - constructor (kotlin/String, kotlin/Int, dev.kord.voice/EncryptionMode) // dev.kord.voice.gateway/SelectProtocol.Data.|(kotlin.String;kotlin.Int;dev.kord.voice.EncryptionMode){}[0] - final fun component1(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.Data.component1|component1(){}[0] - final fun component2(): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.Data.component2|component2(){}[0] - final fun component3(): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SelectProtocol.Data.component3|component3(){}[0] - final fun copy(kotlin/String =..., kotlin/Int =..., dev.kord.voice/EncryptionMode =...): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.Data.copy|copy(kotlin.String;kotlin.Int;dev.kord.voice.EncryptionMode){}[0] + + final val data // dev.kord.voice.gateway/SelectProtocol.data|{}data[0] + final fun (): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.data.|(){}[0] + final val protocol // dev.kord.voice.gateway/SelectProtocol.protocol|{}protocol[0] + final fun (): kotlin/String // dev.kord.voice.gateway/SelectProtocol.protocol.|(){}[0] + + final fun component1(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.component1|component1(){}[0] + final fun component2(): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.component2|component2(){}[0] + final fun copy(kotlin/String = ..., dev.kord.voice.gateway/SelectProtocol.Data = ...): dev.kord.voice.gateway/SelectProtocol // dev.kord.voice.gateway/SelectProtocol.copy|copy(kotlin.String;dev.kord.voice.gateway.SelectProtocol.Data){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SelectProtocol.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.toString|toString(){}[0] + + final class Data { // dev.kord.voice.gateway/SelectProtocol.Data|null[0] + constructor (kotlin/String, kotlin/Int, dev.kord.voice/EncryptionMode) // dev.kord.voice.gateway/SelectProtocol.Data.|(kotlin.String;kotlin.Int;dev.kord.voice.EncryptionMode){}[0] + + final val address // dev.kord.voice.gateway/SelectProtocol.Data.address|{}address[0] + final fun (): kotlin/String // dev.kord.voice.gateway/SelectProtocol.Data.address.|(){}[0] + final val mode // dev.kord.voice.gateway/SelectProtocol.Data.mode|{}mode[0] + final fun (): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SelectProtocol.Data.mode.|(){}[0] + final val port // dev.kord.voice.gateway/SelectProtocol.Data.port|{}port[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.Data.port.|(){}[0] + + final fun component1(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.Data.component1|component1(){}[0] + final fun component2(): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.Data.component2|component2(){}[0] + final fun component3(): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SelectProtocol.Data.component3|component3(){}[0] + final fun copy(kotlin/String = ..., kotlin/Int = ..., dev.kord.voice/EncryptionMode = ...): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.Data.copy|copy(kotlin.String;kotlin.Int;dev.kord.voice.EncryptionMode){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SelectProtocol.Data.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.Data.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.Data.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/SelectProtocol.Data.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/SelectProtocol.Data) // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.SelectProtocol.Data){}[0] - final val descriptor // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SelectProtocol.Data.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/SelectProtocol.Data.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SelectProtocol.Data.Companion.serializer|serializer(){}[0] } - final val address // dev.kord.voice.gateway/SelectProtocol.Data.address|{}address[0] - final fun (): kotlin/String // dev.kord.voice.gateway/SelectProtocol.Data.address.|(){}[0] - final val mode // dev.kord.voice.gateway/SelectProtocol.Data.mode|{}mode[0] - final fun (): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SelectProtocol.Data.mode.|(){}[0] - final val port // dev.kord.voice.gateway/SelectProtocol.Data.port|{}port[0] - final fun (): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.Data.port.|(){}[0] } - final fun component1(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.component1|component1(){}[0] - final fun component2(): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.component2|component2(){}[0] - final fun copy(kotlin/String =..., dev.kord.voice.gateway/SelectProtocol.Data =...): dev.kord.voice.gateway/SelectProtocol // dev.kord.voice.gateway/SelectProtocol.copy|copy(kotlin.String;dev.kord.voice.gateway.SelectProtocol.Data){}[0] - final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SelectProtocol.equals|equals(kotlin.Any?){}[0] - final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SelectProtocol.hashCode|hashCode(){}[0] - final fun toString(): kotlin/String // dev.kord.voice.gateway/SelectProtocol.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/SelectProtocol.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/SelectProtocol.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SelectProtocol.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/SelectProtocol.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/SelectProtocol // dev.kord.voice.gateway/SelectProtocol.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/SelectProtocol) // dev.kord.voice.gateway/SelectProtocol.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.SelectProtocol){}[0] - final val descriptor // dev.kord.voice.gateway/SelectProtocol.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SelectProtocol.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/SelectProtocol.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SelectProtocol.Companion.serializer|serializer(){}[0] } - final val data // dev.kord.voice.gateway/SelectProtocol.data|{}data[0] - final fun (): dev.kord.voice.gateway/SelectProtocol.Data // dev.kord.voice.gateway/SelectProtocol.data.|(){}[0] - final val protocol // dev.kord.voice.gateway/SelectProtocol.protocol|{}protocol[0] - final fun (): kotlin/String // dev.kord.voice.gateway/SelectProtocol.protocol.|(){}[0] } + final class dev.kord.voice.gateway/SendSpeaking : dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/SendSpeaking|null[0] constructor (dev.kord.voice/SpeakingFlags, kotlin/Int, kotlin/UInt) // dev.kord.voice.gateway/SendSpeaking.|(dev.kord.voice.SpeakingFlags;kotlin.Int;kotlin.UInt){}[0] + + final val delay // dev.kord.voice.gateway/SendSpeaking.delay|{}delay[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/SendSpeaking.delay.|(){}[0] + final val speaking // dev.kord.voice.gateway/SendSpeaking.speaking|{}speaking[0] + final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/SendSpeaking.speaking.|(){}[0] + final val ssrc // dev.kord.voice.gateway/SendSpeaking.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.gateway/SendSpeaking.ssrc.|(){}[0] + final fun component1(): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/SendSpeaking.component1|component1(){}[0] final fun component2(): kotlin/Int // dev.kord.voice.gateway/SendSpeaking.component2|component2(){}[0] final fun component3(): kotlin/UInt // dev.kord.voice.gateway/SendSpeaking.component3|component3(){}[0] - final fun copy(dev.kord.voice/SpeakingFlags =..., kotlin/Int =..., kotlin/UInt =...): dev.kord.voice.gateway/SendSpeaking // dev.kord.voice.gateway/SendSpeaking.copy|copy(dev.kord.voice.SpeakingFlags;kotlin.Int;kotlin.UInt){}[0] + final fun copy(dev.kord.voice/SpeakingFlags = ..., kotlin/Int = ..., kotlin/UInt = ...): dev.kord.voice.gateway/SendSpeaking // dev.kord.voice.gateway/SendSpeaking.copy|copy(dev.kord.voice.SpeakingFlags;kotlin.Int;kotlin.UInt){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SendSpeaking.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SendSpeaking.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/SendSpeaking.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/SendSpeaking.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/SendSpeaking.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SendSpeaking.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/SendSpeaking.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/SendSpeaking // dev.kord.voice.gateway/SendSpeaking.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/SendSpeaking) // dev.kord.voice.gateway/SendSpeaking.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.SendSpeaking){}[0] - final val descriptor // dev.kord.voice.gateway/SendSpeaking.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SendSpeaking.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/SendSpeaking.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SendSpeaking.Companion.serializer|serializer(){}[0] } - final val delay // dev.kord.voice.gateway/SendSpeaking.delay|{}delay[0] - final fun (): kotlin/Int // dev.kord.voice.gateway/SendSpeaking.delay.|(){}[0] - final val speaking // dev.kord.voice.gateway/SendSpeaking.speaking|{}speaking[0] - final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/SendSpeaking.speaking.|(){}[0] - final val ssrc // dev.kord.voice.gateway/SendSpeaking.ssrc|{}ssrc[0] - final fun (): kotlin/UInt // dev.kord.voice.gateway/SendSpeaking.ssrc.|(){}[0] } + final class dev.kord.voice.gateway/SessionDescription : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/SessionDescription|null[0] constructor (dev.kord.voice/EncryptionMode, kotlin.collections/List) // dev.kord.voice.gateway/SessionDescription.|(dev.kord.voice.EncryptionMode;kotlin.collections.List){}[0] + + final val mode // dev.kord.voice.gateway/SessionDescription.mode|{}mode[0] + final fun (): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SessionDescription.mode.|(){}[0] + final val secretKey // dev.kord.voice.gateway/SessionDescription.secretKey|{}secretKey[0] + final fun (): kotlin.collections/List // dev.kord.voice.gateway/SessionDescription.secretKey.|(){}[0] + final fun component1(): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SessionDescription.component1|component1(){}[0] final fun component2(): kotlin.collections/List // dev.kord.voice.gateway/SessionDescription.component2|component2(){}[0] - final fun copy(dev.kord.voice/EncryptionMode =..., kotlin.collections/List =...): dev.kord.voice.gateway/SessionDescription // dev.kord.voice.gateway/SessionDescription.copy|copy(dev.kord.voice.EncryptionMode;kotlin.collections.List){}[0] + final fun copy(dev.kord.voice/EncryptionMode = ..., kotlin.collections/List = ...): dev.kord.voice.gateway/SessionDescription // dev.kord.voice.gateway/SessionDescription.copy|copy(dev.kord.voice.EncryptionMode;kotlin.collections.List){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/SessionDescription.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/SessionDescription.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/SessionDescription.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/SessionDescription.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/SessionDescription.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SessionDescription.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/SessionDescription.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/SessionDescription // dev.kord.voice.gateway/SessionDescription.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/SessionDescription) // dev.kord.voice.gateway/SessionDescription.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.SessionDescription){}[0] - final val descriptor // dev.kord.voice.gateway/SessionDescription.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/SessionDescription.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/SessionDescription.Companion|null[0] - final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SessionDescription.Companion.serializer|serializer(){}[0] final val $childSerializers // dev.kord.voice.gateway/SessionDescription.Companion.$childSerializers|{}$childSerializers[0] + + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/SessionDescription.Companion.serializer|serializer(){}[0] } - final val mode // dev.kord.voice.gateway/SessionDescription.mode|{}mode[0] - final fun (): dev.kord.voice/EncryptionMode // dev.kord.voice.gateway/SessionDescription.mode.|(){}[0] - final val secretKey // dev.kord.voice.gateway/SessionDescription.secretKey|{}secretKey[0] - final fun (): kotlin.collections/List // dev.kord.voice.gateway/SessionDescription.secretKey.|(){}[0] } + final class dev.kord.voice.gateway/Speaking : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Speaking|null[0] constructor (dev.kord.common.entity/Snowflake, kotlin/UInt, dev.kord.voice/SpeakingFlags) // dev.kord.voice.gateway/Speaking.|(dev.kord.common.entity.Snowflake;kotlin.UInt;dev.kord.voice.SpeakingFlags){}[0] + + final val speaking // dev.kord.voice.gateway/Speaking.speaking|{}speaking[0] + final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/Speaking.speaking.|(){}[0] + final val ssrc // dev.kord.voice.gateway/Speaking.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.gateway/Speaking.ssrc.|(){}[0] + final val userId // dev.kord.voice.gateway/Speaking.userId|{}userId[0] + final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Speaking.userId.|(){}[0] + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Speaking.component1|component1(){}[0] final fun component2(): kotlin/UInt // dev.kord.voice.gateway/Speaking.component2|component2(){}[0] final fun component3(): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/Speaking.component3|component3(){}[0] - final fun copy(dev.kord.common.entity/Snowflake =..., kotlin/UInt =..., dev.kord.voice/SpeakingFlags =...): dev.kord.voice.gateway/Speaking // dev.kord.voice.gateway/Speaking.copy|copy(dev.kord.common.entity.Snowflake;kotlin.UInt;dev.kord.voice.SpeakingFlags){}[0] + final fun copy(dev.kord.common.entity/Snowflake = ..., kotlin/UInt = ..., dev.kord.voice/SpeakingFlags = ...): dev.kord.voice.gateway/Speaking // dev.kord.voice.gateway/Speaking.copy|copy(dev.kord.common.entity.Snowflake;kotlin.UInt;dev.kord.voice.SpeakingFlags){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Speaking.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Speaking.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/Speaking.toString|toString(){}[0] + final object $serializer : kotlinx.serialization.internal/GeneratedSerializer { // dev.kord.voice.gateway/Speaking.$serializer|null[0] + final val descriptor // dev.kord.voice.gateway/Speaking.$serializer.descriptor|{}descriptor[0] + final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Speaking.$serializer.descriptor.|(){}[0] + final fun childSerializers(): kotlin/Array> // dev.kord.voice.gateway/Speaking.$serializer.childSerializers|childSerializers(){}[0] final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/Speaking // dev.kord.voice.gateway/Speaking.$serializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Speaking) // dev.kord.voice.gateway/Speaking.$serializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Speaking){}[0] - final val descriptor // dev.kord.voice.gateway/Speaking.$serializer.descriptor|{}descriptor[0] - final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Speaking.$serializer.descriptor.|(){}[0] } + final object Companion { // dev.kord.voice.gateway/Speaking.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Speaking.Companion.serializer|serializer(){}[0] } - final val speaking // dev.kord.voice.gateway/Speaking.speaking|{}speaking[0] - final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice.gateway/Speaking.speaking.|(){}[0] - final val ssrc // dev.kord.voice.gateway/Speaking.ssrc|{}ssrc[0] - final fun (): kotlin/UInt // dev.kord.voice.gateway/Speaking.ssrc.|(){}[0] - final val userId // dev.kord.voice.gateway/Speaking.userId|{}userId[0] - final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice.gateway/Speaking.userId.|(){}[0] } + final class dev.kord.voice.gateway/VoiceGatewayConfiguration { // dev.kord.voice.gateway/VoiceGatewayConfiguration|null[0] constructor (kotlin/String, kotlin/String) // dev.kord.voice.gateway/VoiceGatewayConfiguration.|(kotlin.String;kotlin.String){}[0] + + final val endpoint // dev.kord.voice.gateway/VoiceGatewayConfiguration.endpoint|{}endpoint[0] + final fun (): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.endpoint.|(){}[0] + final val token // dev.kord.voice.gateway/VoiceGatewayConfiguration.token|{}token[0] + final fun (): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.token.|(){}[0] + final fun component1(): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.component1|component1(){}[0] final fun component2(): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.component2|component2(){}[0] - final fun copy(kotlin/String =..., kotlin/String =...): dev.kord.voice.gateway/VoiceGatewayConfiguration // dev.kord.voice.gateway/VoiceGatewayConfiguration.copy|copy(kotlin.String;kotlin.String){}[0] + final fun copy(kotlin/String = ..., kotlin/String = ...): dev.kord.voice.gateway/VoiceGatewayConfiguration // dev.kord.voice.gateway/VoiceGatewayConfiguration.copy|copy(kotlin.String;kotlin.String){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/VoiceGatewayConfiguration.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/VoiceGatewayConfiguration.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.toString|toString(){}[0] - final val endpoint // dev.kord.voice.gateway/VoiceGatewayConfiguration.endpoint|{}endpoint[0] - final fun (): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.endpoint.|(){}[0] - final val token // dev.kord.voice.gateway/VoiceGatewayConfiguration.token|{}token[0] - final fun (): kotlin/String // dev.kord.voice.gateway/VoiceGatewayConfiguration.token.|(){}[0] } + final class dev.kord.voice.io/ByteArrayView : kotlin.collections/Iterable { // dev.kord.voice.io/ByteArrayView|null[0] + final val data // dev.kord.voice.io/ByteArrayView.data|{}data[0] + final fun (): kotlin/ByteArray // dev.kord.voice.io/ByteArrayView.data.|(){}[0] + final val viewSize // dev.kord.voice.io/ByteArrayView.viewSize|{}viewSize[0] + final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.viewSize.|(){}[0] + + final var dataEnd // dev.kord.voice.io/ByteArrayView.dataEnd|{}dataEnd[0] + final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.dataEnd.|(){}[0] + final var dataStart // dev.kord.voice.io/ByteArrayView.dataStart|{}dataStart[0] + final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.dataStart.|(){}[0] + final fun asInt(): kotlin/Int // dev.kord.voice.io/ByteArrayView.asInt|asInt(){}[0] final fun asShort(): kotlin/Short // dev.kord.voice.io/ByteArrayView.asShort|asShort(){}[0] final fun clone(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ByteArrayView.clone|clone(){}[0] final fun get(kotlin/Int): kotlin/Byte // dev.kord.voice.io/ByteArrayView.get|get(kotlin.Int){}[0] final fun iterator(): kotlin.collections/Iterator // dev.kord.voice.io/ByteArrayView.iterator|iterator(){}[0] - final fun resize(kotlin/Int =..., kotlin/Int =...): kotlin/Boolean // dev.kord.voice.io/ByteArrayView.resize|resize(kotlin.Int;kotlin.Int){}[0] + final fun resize(kotlin/Int = ..., kotlin/Int = ...): kotlin/Boolean // dev.kord.voice.io/ByteArrayView.resize|resize(kotlin.Int;kotlin.Int){}[0] final fun toByteArray(): kotlin/ByteArray // dev.kord.voice.io/ByteArrayView.toByteArray|toByteArray(){}[0] - final fun view(kotlin/Int =..., kotlin/Int =...): dev.kord.voice.io/ByteArrayView? // dev.kord.voice.io/ByteArrayView.view|view(kotlin.Int;kotlin.Int){}[0] + final fun view(kotlin/Int = ..., kotlin/Int = ...): dev.kord.voice.io/ByteArrayView? // dev.kord.voice.io/ByteArrayView.view|view(kotlin.Int;kotlin.Int){}[0] + final object Companion { // dev.kord.voice.io/ByteArrayView.Companion|null[0] final fun from(kotlin/ByteArray, kotlin/Int, kotlin/Int): dev.kord.voice.io/ByteArrayView? // dev.kord.voice.io/ByteArrayView.Companion.from|from(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0] } - final val data // dev.kord.voice.io/ByteArrayView.data|{}data[0] - final fun (): kotlin/ByteArray // dev.kord.voice.io/ByteArrayView.data.|(){}[0] - final val viewSize // dev.kord.voice.io/ByteArrayView.viewSize|{}viewSize[0] - final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.viewSize.|(){}[0] - final var dataEnd // dev.kord.voice.io/ByteArrayView.dataEnd|{}dataEnd[0] - final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.dataEnd.|(){}[0] - final var dataStart // dev.kord.voice.io/ByteArrayView.dataStart|{}dataStart[0] - final fun (): kotlin/Int // dev.kord.voice.io/ByteArrayView.dataStart.|(){}[0] } + final class dev.kord.voice.io/MutableByteArrayCursor { // dev.kord.voice.io/MutableByteArrayCursor|null[0] constructor (kotlin/ByteArray) // dev.kord.voice.io/MutableByteArrayCursor.|(kotlin.ByteArray){}[0] - final fun reset() // dev.kord.voice.io/MutableByteArrayCursor.reset|reset(){}[0] - final fun resize(kotlin/Int, kotlin/Boolean =...): kotlin/Boolean // dev.kord.voice.io/MutableByteArrayCursor.resize|resize(kotlin.Int;kotlin.Boolean){}[0] - final fun writeByte(kotlin/Byte) // dev.kord.voice.io/MutableByteArrayCursor.writeByte|writeByte(kotlin.Byte){}[0] - final fun writeByteArray(kotlin/ByteArray, kotlin/Int =..., kotlin/Int =...) // dev.kord.voice.io/MutableByteArrayCursor.writeByteArray|writeByteArray(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0] - final fun writeByteView(dev.kord.voice.io/ByteArrayView) // dev.kord.voice.io/MutableByteArrayCursor.writeByteView|writeByteView(dev.kord.voice.io.ByteArrayView){}[0] - final fun writeInt(kotlin/Int) // dev.kord.voice.io/MutableByteArrayCursor.writeInt|writeInt(kotlin.Int){}[0] - final fun writeShort(kotlin/Short) // dev.kord.voice.io/MutableByteArrayCursor.writeShort|writeShort(kotlin.Short){}[0] + final val isExhausted // dev.kord.voice.io/MutableByteArrayCursor.isExhausted|{}isExhausted[0] final fun (): kotlin/Boolean // dev.kord.voice.io/MutableByteArrayCursor.isExhausted.|(){}[0] final val remaining // dev.kord.voice.io/MutableByteArrayCursor.remaining|{}remaining[0] final fun (): kotlin/Int // dev.kord.voice.io/MutableByteArrayCursor.remaining.|(){}[0] + final var cursor // dev.kord.voice.io/MutableByteArrayCursor.cursor|{}cursor[0] final fun (): kotlin/Int // dev.kord.voice.io/MutableByteArrayCursor.cursor.|(){}[0] final fun (kotlin/Int) // dev.kord.voice.io/MutableByteArrayCursor.cursor.|(kotlin.Int){}[0] final var data // dev.kord.voice.io/MutableByteArrayCursor.data|{}data[0] final fun (): kotlin/ByteArray // dev.kord.voice.io/MutableByteArrayCursor.data.|(){}[0] + + final fun reset() // dev.kord.voice.io/MutableByteArrayCursor.reset|reset(){}[0] + final fun resize(kotlin/Int, kotlin/Boolean = ...): kotlin/Boolean // dev.kord.voice.io/MutableByteArrayCursor.resize|resize(kotlin.Int;kotlin.Boolean){}[0] + final fun writeByte(kotlin/Byte) // dev.kord.voice.io/MutableByteArrayCursor.writeByte|writeByte(kotlin.Byte){}[0] + final fun writeByteArray(kotlin/ByteArray, kotlin/Int = ..., kotlin/Int = ...) // dev.kord.voice.io/MutableByteArrayCursor.writeByteArray|writeByteArray(kotlin.ByteArray;kotlin.Int;kotlin.Int){}[0] + final fun writeByteView(dev.kord.voice.io/ByteArrayView) // dev.kord.voice.io/MutableByteArrayCursor.writeByteView|writeByteView(dev.kord.voice.io.ByteArrayView){}[0] + final fun writeInt(kotlin/Int) // dev.kord.voice.io/MutableByteArrayCursor.writeInt|writeInt(kotlin.Int){}[0] + final fun writeShort(kotlin/Short) // dev.kord.voice.io/MutableByteArrayCursor.writeShort|writeShort(kotlin.Short){}[0] } + final class dev.kord.voice.io/ReadableByteArrayCursor { // dev.kord.voice.io/ReadableByteArrayCursor|null[0] constructor (dev.kord.voice.io/ByteArrayView) // dev.kord.voice.io/ReadableByteArrayCursor.|(dev.kord.voice.io.ByteArrayView){}[0] - final fun consume(kotlin/Int) // dev.kord.voice.io/ReadableByteArrayCursor.consume|consume(kotlin.Int){}[0] - final fun readByte(): kotlin/Byte // dev.kord.voice.io/ReadableByteArrayCursor.readByte|readByte(){}[0] - final fun readBytes(kotlin/Int): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ReadableByteArrayCursor.readBytes|readBytes(kotlin.Int){}[0] - final fun readInt(): kotlin/Int // dev.kord.voice.io/ReadableByteArrayCursor.readInt|readInt(){}[0] - final fun readRemaining(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ReadableByteArrayCursor.readRemaining|readRemaining(){}[0] - final fun readShort(): kotlin/Short // dev.kord.voice.io/ReadableByteArrayCursor.readShort|readShort(){}[0] + final val remaining // dev.kord.voice.io/ReadableByteArrayCursor.remaining|{}remaining[0] final fun (): kotlin/Int // dev.kord.voice.io/ReadableByteArrayCursor.remaining.|(){}[0] final val view // dev.kord.voice.io/ReadableByteArrayCursor.view|{}view[0] final fun (): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ReadableByteArrayCursor.view.|(){}[0] + final var cursor // dev.kord.voice.io/ReadableByteArrayCursor.cursor|{}cursor[0] final fun (): kotlin/Int // dev.kord.voice.io/ReadableByteArrayCursor.cursor.|(){}[0] final fun (kotlin/Int) // dev.kord.voice.io/ReadableByteArrayCursor.cursor.|(kotlin.Int){}[0] + + final fun consume(kotlin/Int) // dev.kord.voice.io/ReadableByteArrayCursor.consume|consume(kotlin.Int){}[0] + final fun readByte(): kotlin/Byte // dev.kord.voice.io/ReadableByteArrayCursor.readByte|readByte(){}[0] + final fun readBytes(kotlin/Int): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ReadableByteArrayCursor.readBytes|readBytes(kotlin.Int){}[0] + final fun readInt(): kotlin/Int // dev.kord.voice.io/ReadableByteArrayCursor.readInt|readInt(){}[0] + final fun readRemaining(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/ReadableByteArrayCursor.readRemaining|readRemaining(){}[0] + final fun readShort(): kotlin/Short // dev.kord.voice.io/ReadableByteArrayCursor.readShort|readShort(){}[0] } + final class dev.kord.voice.streams/DefaultStreams : dev.kord.voice.streams/Streams { // dev.kord.voice.streams/DefaultStreams|null[0] constructor (dev.kord.voice.gateway/VoiceGateway, dev.kord.voice.udp/VoiceUdpSocket, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.streams/DefaultStreams.|(dev.kord.voice.gateway.VoiceGateway;dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] - final val incomingAudioFrames // dev.kord.voice.streams/DefaultStreams.incomingAudioFrames|(){}[0] + + final val incomingAudioFrames // dev.kord.voice.streams/DefaultStreams.incomingAudioFrames|{}incomingAudioFrames[0] final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/DefaultStreams.incomingAudioFrames.|(){}[0] final val incomingAudioPackets // dev.kord.voice.streams/DefaultStreams.incomingAudioPackets|{}incomingAudioPackets[0] final fun (): kotlinx.coroutines.flow/SharedFlow // dev.kord.voice.streams/DefaultStreams.incomingAudioPackets.|(){}[0] @@ -500,18 +657,15 @@ final class dev.kord.voice.streams/DefaultStreams : dev.kord.voice.streams/Strea final fun (): kotlinx.coroutines.flow/SharedFlow> // dev.kord.voice.streams/DefaultStreams.incomingUserStreams.|(){}[0] final val ssrcToUser // dev.kord.voice.streams/DefaultStreams.ssrcToUser|{}ssrcToUser[0] final fun (): kotlin.collections/Map // dev.kord.voice.streams/DefaultStreams.ssrcToUser.|(){}[0] + // Targets: [apple, linux] final suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/DefaultStreams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [js, mingwX64] final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/DefaultStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } + final class dev.kord.voice.udp/AudioFrameSenderConfiguration { // dev.kord.voice.udp/AudioFrameSenderConfiguration|null[0] - final fun component2(): kotlin/UInt // dev.kord.voice.udp/AudioFrameSenderConfiguration.component2|component2(){}[0] - final fun component3(): kotlin/ByteArray // dev.kord.voice.udp/AudioFrameSenderConfiguration.component3|component3(){}[0] - final fun component4(): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.component4|component4(){}[0] - final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/AudioFrameSenderConfiguration.equals|equals(kotlin.Any?){}[0] - final fun hashCode(): kotlin/Int // dev.kord.voice.udp/AudioFrameSenderConfiguration.hashCode|hashCode(){}[0] - final fun toString(): kotlin/String // dev.kord.voice.udp/AudioFrameSenderConfiguration.toString|toString(){}[0] final val interceptorConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.interceptorConfiguration|{}interceptorConfiguration[0] final fun (): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.interceptorConfiguration.|(){}[0] final val key // dev.kord.voice.udp/AudioFrameSenderConfiguration.key|{}key[0] @@ -519,39 +673,53 @@ final class dev.kord.voice.udp/AudioFrameSenderConfiguration { // dev.kord.voice final val server // dev.kord.voice.udp/AudioFrameSenderConfiguration.server|{}server[0] // Targets: [apple, linux] final fun (): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.server.|(){}[0] + // Targets: [js, mingwX64] final fun (): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.server.|(){}[0] final val ssrc // dev.kord.voice.udp/AudioFrameSenderConfiguration.ssrc|{}ssrc[0] final fun (): kotlin/UInt // dev.kord.voice.udp/AudioFrameSenderConfiguration.ssrc.|(){}[0] + + final fun component2(): kotlin/UInt // dev.kord.voice.udp/AudioFrameSenderConfiguration.component2|component2(){}[0] + final fun component3(): kotlin/ByteArray // dev.kord.voice.udp/AudioFrameSenderConfiguration.component3|component3(){}[0] + final fun component4(): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.component4|component4(){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/AudioFrameSenderConfiguration.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.udp/AudioFrameSenderConfiguration.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/AudioFrameSenderConfiguration.toString|toString(){}[0] + // Targets: [apple, linux] constructor (io.ktor.network.sockets/InetSocketAddress, kotlin/UInt, kotlin/ByteArray, dev.kord.voice/FrameInterceptorConfiguration) // dev.kord.voice.udp/AudioFrameSenderConfiguration.|(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + // Targets: [apple, linux] final fun component1(): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.component1|component1(){}[0] - // Targets: [apple, linux] + + // Targets: [apple] final fun copy(io.ktor.network.sockets/InetSocketAddress =..., kotlin/UInt =..., kotlin/ByteArray =..., dev.kord.voice/FrameInterceptorConfiguration =...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + // Targets: [js, mingwX64] constructor (dev.kord.voice.udp/SocketAddress, kotlin/UInt, kotlin/ByteArray, dev.kord.voice/FrameInterceptorConfiguration) // dev.kord.voice.udp/AudioFrameSenderConfiguration.|(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + // Targets: [js, mingwX64] final fun component1(): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.component1|component1(){}[0] + // Targets: [js, mingwX64] - final fun copy(dev.kord.voice.udp/SocketAddress =..., kotlin/UInt =..., kotlin/ByteArray =..., dev.kord.voice/FrameInterceptorConfiguration =...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + final fun copy(dev.kord.voice.udp/SocketAddress = ..., kotlin/UInt = ..., kotlin/ByteArray = ..., dev.kord.voice/FrameInterceptorConfiguration = ...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + + // Targets: [linux] + final fun copy(io.ktor.network.sockets/InetSocketAddress = ..., kotlin/UInt = ..., kotlin/ByteArray = ..., dev.kord.voice/FrameInterceptorConfiguration = ...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] } + final class dev.kord.voice.udp/DefaultAudioFrameSender : dev.kord.voice.udp/AudioFrameSender { // dev.kord.voice.udp/DefaultAudioFrameSender|null[0] constructor (dev.kord.voice.udp/DefaultAudioFrameSenderData) // dev.kord.voice.udp/DefaultAudioFrameSender.|(dev.kord.voice.udp.DefaultAudioFrameSenderData){}[0] - final suspend fun start(dev.kord.voice.udp/AudioFrameSenderConfiguration) // dev.kord.voice.udp/DefaultAudioFrameSender.start|start(dev.kord.voice.udp.AudioFrameSenderConfiguration){}[0] + final val data // dev.kord.voice.udp/DefaultAudioFrameSender.data|{}data[0] final fun (): dev.kord.voice.udp/DefaultAudioFrameSenderData // dev.kord.voice.udp/DefaultAudioFrameSender.data.|(){}[0] + + final suspend fun start(dev.kord.voice.udp/AudioFrameSenderConfiguration) // dev.kord.voice.udp/DefaultAudioFrameSender.start|start(dev.kord.voice.udp.AudioFrameSenderConfiguration){}[0] } + final class dev.kord.voice.udp/DefaultAudioFrameSenderData { // dev.kord.voice.udp/DefaultAudioFrameSenderData|null[0] constructor (dev.kord.voice.udp/VoiceUdpSocket, dev.kord.voice/FrameInterceptor, dev.kord.voice/AudioProvider, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.udp/DefaultAudioFrameSenderData.|(dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.FrameInterceptor;dev.kord.voice.AudioProvider;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] - final fun component1(): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/DefaultAudioFrameSenderData.component1|component1(){}[0] - final fun component2(): dev.kord.voice/FrameInterceptor // dev.kord.voice.udp/DefaultAudioFrameSenderData.component2|component2(){}[0] - final fun component3(): dev.kord.voice/AudioProvider // dev.kord.voice.udp/DefaultAudioFrameSenderData.component3|component3(){}[0] - final fun component4(): dev.kord.voice.encryption.strategies/NonceStrategy // dev.kord.voice.udp/DefaultAudioFrameSenderData.component4|component4(){}[0] - final fun copy(dev.kord.voice.udp/VoiceUdpSocket =..., dev.kord.voice/FrameInterceptor =..., dev.kord.voice/AudioProvider =..., dev.kord.voice.encryption.strategies/NonceStrategy =...): dev.kord.voice.udp/DefaultAudioFrameSenderData // dev.kord.voice.udp/DefaultAudioFrameSenderData.copy|copy(dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.FrameInterceptor;dev.kord.voice.AudioProvider;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] - final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/DefaultAudioFrameSenderData.equals|equals(kotlin.Any?){}[0] - final fun hashCode(): kotlin/Int // dev.kord.voice.udp/DefaultAudioFrameSenderData.hashCode|hashCode(){}[0] - final fun toString(): kotlin/String // dev.kord.voice.udp/DefaultAudioFrameSenderData.toString|toString(){}[0] + final val interceptor // dev.kord.voice.udp/DefaultAudioFrameSenderData.interceptor|{}interceptor[0] final fun (): dev.kord.voice/FrameInterceptor // dev.kord.voice.udp/DefaultAudioFrameSenderData.interceptor.|(){}[0] final val nonceStrategy // dev.kord.voice.udp/DefaultAudioFrameSenderData.nonceStrategy|{}nonceStrategy[0] @@ -560,16 +728,67 @@ final class dev.kord.voice.udp/DefaultAudioFrameSenderData { // dev.kord.voice.u final fun (): dev.kord.voice/AudioProvider // dev.kord.voice.udp/DefaultAudioFrameSenderData.provider.|(){}[0] final val udp // dev.kord.voice.udp/DefaultAudioFrameSenderData.udp|{}udp[0] final fun (): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/DefaultAudioFrameSenderData.udp.|(){}[0] + + final fun component1(): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/DefaultAudioFrameSenderData.component1|component1(){}[0] + final fun component2(): dev.kord.voice/FrameInterceptor // dev.kord.voice.udp/DefaultAudioFrameSenderData.component2|component2(){}[0] + final fun component3(): dev.kord.voice/AudioProvider // dev.kord.voice.udp/DefaultAudioFrameSenderData.component3|component3(){}[0] + final fun component4(): dev.kord.voice.encryption.strategies/NonceStrategy // dev.kord.voice.udp/DefaultAudioFrameSenderData.component4|component4(){}[0] + final fun copy(dev.kord.voice.udp/VoiceUdpSocket = ..., dev.kord.voice/FrameInterceptor = ..., dev.kord.voice/AudioProvider = ..., dev.kord.voice.encryption.strategies/NonceStrategy = ...): dev.kord.voice.udp/DefaultAudioFrameSenderData // dev.kord.voice.udp/DefaultAudioFrameSenderData.copy|copy(dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.FrameInterceptor;dev.kord.voice.AudioProvider;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/DefaultAudioFrameSenderData.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.udp/DefaultAudioFrameSenderData.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/DefaultAudioFrameSenderData.toString|toString(){}[0] } + final class dev.kord.voice.udp/DefaultNativeAudioPacketProvider : dev.kord.voice.udp/AudioPacketProvider { // dev.kord.voice.udp/DefaultNativeAudioPacketProvider|null[0] constructor (kotlin/ByteArray, dev.kord.voice.encryption.strategies/NonceStrategy) // dev.kord.voice.udp/DefaultNativeAudioPacketProvider.|(kotlin.ByteArray;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] + final fun provide(kotlin/UShort, kotlin/UInt, kotlin/UInt, kotlin/ByteArray): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/DefaultNativeAudioPacketProvider.provide|provide(kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.ByteArray){}[0] } + final class dev.kord.voice.udp/RTPPacket { // dev.kord.voice.udp/RTPPacket|null[0] constructor (kotlin/UByte, kotlin/Byte, kotlin/UShort, kotlin/UInt, kotlin/UInt, kotlin/UIntArray, kotlin/Boolean, kotlin/Boolean, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/RTPPacket.|(kotlin.UByte;kotlin.Byte;kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.UIntArray;kotlin.Boolean;kotlin.Boolean;dev.kord.voice.io.ByteArrayView){}[0] + + final val csrcIdentifiers // dev.kord.voice.udp/RTPPacket.csrcIdentifiers|{}csrcIdentifiers[0] + final fun (): kotlin/UIntArray // dev.kord.voice.udp/RTPPacket.csrcIdentifiers.|(){}[0] + final val hasExtension // dev.kord.voice.udp/RTPPacket.hasExtension|{}hasExtension[0] + final fun (): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.hasExtension.|(){}[0] + final val hasMarker // dev.kord.voice.udp/RTPPacket.hasMarker|{}hasMarker[0] + final fun (): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.hasMarker.|(){}[0] + final val paddingBytes // dev.kord.voice.udp/RTPPacket.paddingBytes|{}paddingBytes[0] + final fun (): kotlin/UByte // dev.kord.voice.udp/RTPPacket.paddingBytes.|(){}[0] + final val payload // dev.kord.voice.udp/RTPPacket.payload|{}payload[0] + final fun (): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.payload.|(){}[0] + final val payloadType // dev.kord.voice.udp/RTPPacket.payloadType|{}payloadType[0] + final fun (): kotlin/Byte // dev.kord.voice.udp/RTPPacket.payloadType.|(){}[0] + final val sequence // dev.kord.voice.udp/RTPPacket.sequence|{}sequence[0] + final fun (): kotlin/UShort // dev.kord.voice.udp/RTPPacket.sequence.|(){}[0] + final val ssrc // dev.kord.voice.udp/RTPPacket.ssrc|{}ssrc[0] + final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.ssrc.|(){}[0] + final val timestamp // dev.kord.voice.udp/RTPPacket.timestamp|{}timestamp[0] + final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.timestamp.|(){}[0] + + final fun asByteArray(): kotlin/ByteArray // dev.kord.voice.udp/RTPPacket.asByteArray|asByteArray(){}[0] + final fun asByteArrayView(dev.kord.voice.io/MutableByteArrayCursor): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.asByteArrayView|asByteArrayView(dev.kord.voice.io.MutableByteArrayCursor){}[0] + final fun clone(): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.clone|clone(){}[0] + final fun component1(): kotlin/UByte // dev.kord.voice.udp/RTPPacket.component1|component1(){}[0] + final fun component2(): kotlin/Byte // dev.kord.voice.udp/RTPPacket.component2|component2(){}[0] + final fun component3(): kotlin/UShort // dev.kord.voice.udp/RTPPacket.component3|component3(){}[0] + final fun component4(): kotlin/UInt // dev.kord.voice.udp/RTPPacket.component4|component4(){}[0] + final fun component5(): kotlin/UInt // dev.kord.voice.udp/RTPPacket.component5|component5(){}[0] + final fun component6(): kotlin/UIntArray // dev.kord.voice.udp/RTPPacket.component6|component6(){}[0] + final fun component7(): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.component7|component7(){}[0] + final fun component8(): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.component8|component8(){}[0] + final fun component9(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.component9|component9(){}[0] + final fun copy(kotlin/UByte = ..., kotlin/Byte = ..., kotlin/UShort = ..., kotlin/UInt = ..., kotlin/UInt = ..., kotlin/UIntArray = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., dev.kord.voice.io/ByteArrayView = ...): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.copy|copy(kotlin.UByte;kotlin.Byte;kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.UIntArray;kotlin.Boolean;kotlin.Boolean;dev.kord.voice.io.ByteArrayView){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice.udp/RTPPacket.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/RTPPacket.toString|toString(){}[0] + final fun writeHeader(): kotlin/ByteArray // dev.kord.voice.udp/RTPPacket.writeHeader|writeHeader(){}[0] + final fun writeHeader(dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.udp/RTPPacket.writeHeader|writeHeader(dev.kord.voice.io.MutableByteArrayCursor){}[0] + final class Builder { // dev.kord.voice.udp/RTPPacket.Builder|null[0] constructor (kotlin/UInt, kotlin/UInt, kotlin/UShort, kotlin/Byte, kotlin/ByteArray) // dev.kord.voice.udp/RTPPacket.Builder.|(kotlin.UInt;kotlin.UInt;kotlin.UShort;kotlin.Byte;kotlin.ByteArray){}[0] - final fun build(): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.Builder.build|build(){}[0] + final var csrcIdentifiers // dev.kord.voice.udp/RTPPacket.Builder.csrcIdentifiers|{}csrcIdentifiers[0] final fun (): kotlin/UIntArray // dev.kord.voice.udp/RTPPacket.Builder.csrcIdentifiers.|(){}[0] final fun (kotlin/UIntArray) // dev.kord.voice.udp/RTPPacket.Builder.csrcIdentifiers.|(kotlin.UIntArray){}[0] @@ -597,86 +816,59 @@ final class dev.kord.voice.udp/RTPPacket { // dev.kord.voice.udp/RTPPacket|null[ final var timestamp // dev.kord.voice.udp/RTPPacket.Builder.timestamp|{}timestamp[0] final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.Builder.timestamp.|(){}[0] final fun (kotlin/UInt) // dev.kord.voice.udp/RTPPacket.Builder.timestamp.|(kotlin.UInt){}[0] + + final fun build(): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.Builder.build|build(){}[0] } - final fun asByteArray(): kotlin/ByteArray // dev.kord.voice.udp/RTPPacket.asByteArray|asByteArray(){}[0] - final fun asByteArrayView(dev.kord.voice.io/MutableByteArrayCursor): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.asByteArrayView|asByteArrayView(dev.kord.voice.io.MutableByteArrayCursor){}[0] - final fun clone(): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.clone|clone(){}[0] - final fun component1(): kotlin/UByte // dev.kord.voice.udp/RTPPacket.component1|component1(){}[0] - final fun component2(): kotlin/Byte // dev.kord.voice.udp/RTPPacket.component2|component2(){}[0] - final fun component3(): kotlin/UShort // dev.kord.voice.udp/RTPPacket.component3|component3(){}[0] - final fun component4(): kotlin/UInt // dev.kord.voice.udp/RTPPacket.component4|component4(){}[0] - final fun component5(): kotlin/UInt // dev.kord.voice.udp/RTPPacket.component5|component5(){}[0] - final fun component6(): kotlin/UIntArray // dev.kord.voice.udp/RTPPacket.component6|component6(){}[0] - final fun component7(): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.component7|component7(){}[0] - final fun component8(): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.component8|component8(){}[0] - final fun component9(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.component9|component9(){}[0] - final fun copy(kotlin/UByte =..., kotlin/Byte =..., kotlin/UShort =..., kotlin/UInt =..., kotlin/UInt =..., kotlin/UIntArray =..., kotlin/Boolean =..., kotlin/Boolean =..., dev.kord.voice.io/ByteArrayView =...): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket.copy|copy(kotlin.UByte;kotlin.Byte;kotlin.UShort;kotlin.UInt;kotlin.UInt;kotlin.UIntArray;kotlin.Boolean;kotlin.Boolean;dev.kord.voice.io.ByteArrayView){}[0] - final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.equals|equals(kotlin.Any?){}[0] - final fun hashCode(): kotlin/Int // dev.kord.voice.udp/RTPPacket.hashCode|hashCode(){}[0] - final fun toString(): kotlin/String // dev.kord.voice.udp/RTPPacket.toString|toString(){}[0] - final fun writeHeader(): kotlin/ByteArray // dev.kord.voice.udp/RTPPacket.writeHeader|writeHeader(){}[0] - final fun writeHeader(dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.udp/RTPPacket.writeHeader|writeHeader(dev.kord.voice.io.MutableByteArrayCursor){}[0] + final object Companion { // dev.kord.voice.udp/RTPPacket.Companion|null[0] final fun fromPacket(io.ktor.utils.io.core/ByteReadPacket): dev.kord.voice.udp/RTPPacket? // dev.kord.voice.udp/RTPPacket.Companion.fromPacket|fromPacket(io.ktor.utils.io.core.ByteReadPacket){}[0] } - final val csrcIdentifiers // dev.kord.voice.udp/RTPPacket.csrcIdentifiers|{}csrcIdentifiers[0] - final fun (): kotlin/UIntArray // dev.kord.voice.udp/RTPPacket.csrcIdentifiers.|(){}[0] - final val hasExtension // dev.kord.voice.udp/RTPPacket.hasExtension|{}hasExtension[0] - final fun (): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.hasExtension.|(){}[0] - final val hasMarker // dev.kord.voice.udp/RTPPacket.hasMarker|{}hasMarker[0] - final fun (): kotlin/Boolean // dev.kord.voice.udp/RTPPacket.hasMarker.|(){}[0] - final val paddingBytes // dev.kord.voice.udp/RTPPacket.paddingBytes|{}paddingBytes[0] - final fun (): kotlin/UByte // dev.kord.voice.udp/RTPPacket.paddingBytes.|(){}[0] - final val payload // dev.kord.voice.udp/RTPPacket.payload|{}payload[0] - final fun (): dev.kord.voice.io/ByteArrayView // dev.kord.voice.udp/RTPPacket.payload.|(){}[0] - final val payloadType // dev.kord.voice.udp/RTPPacket.payloadType|{}payloadType[0] - final fun (): kotlin/Byte // dev.kord.voice.udp/RTPPacket.payloadType.|(){}[0] - final val sequence // dev.kord.voice.udp/RTPPacket.sequence|{}sequence[0] - final fun (): kotlin/UShort // dev.kord.voice.udp/RTPPacket.sequence.|(){}[0] - final val ssrc // dev.kord.voice.udp/RTPPacket.ssrc|{}ssrc[0] - final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.ssrc.|(){}[0] - final val timestamp // dev.kord.voice.udp/RTPPacket.timestamp|{}timestamp[0] - final fun (): kotlin/UInt // dev.kord.voice.udp/RTPPacket.timestamp.|(){}[0] } + final class dev.kord.voice/DefaultFrameInterceptor : dev.kord.voice/FrameInterceptor { // dev.kord.voice/DefaultFrameInterceptor|null[0] - constructor (dev.kord.voice/DefaultFrameInterceptorData =...) // dev.kord.voice/DefaultFrameInterceptor.|(dev.kord.voice.DefaultFrameInterceptorData){}[0] + constructor (dev.kord.voice/DefaultFrameInterceptorData = ...) // dev.kord.voice/DefaultFrameInterceptor.|(dev.kord.voice.DefaultFrameInterceptorData){}[0] + final fun (kotlinx.coroutines.flow/Flow).intercept(dev.kord.voice/FrameInterceptorConfiguration): kotlinx.coroutines.flow/Flow // dev.kord.voice/DefaultFrameInterceptor.intercept|intercept@kotlinx.coroutines.flow.Flow(dev.kord.voice.FrameInterceptorConfiguration){}[0] } + final class dev.kord.voice/DefaultFrameInterceptorData { // dev.kord.voice/DefaultFrameInterceptorData|null[0] - constructor (dev.kord.voice/SpeakingFlags =...) // dev.kord.voice/DefaultFrameInterceptorData.|(dev.kord.voice.SpeakingFlags){}[0] + constructor (dev.kord.voice/SpeakingFlags = ...) // dev.kord.voice/DefaultFrameInterceptorData.|(dev.kord.voice.SpeakingFlags){}[0] + + final val speakingState // dev.kord.voice/DefaultFrameInterceptorData.speakingState|{}speakingState[0] + final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice/DefaultFrameInterceptorData.speakingState.|(){}[0] + final fun component1(): dev.kord.voice/SpeakingFlags // dev.kord.voice/DefaultFrameInterceptorData.component1|component1(){}[0] - final fun copy(dev.kord.voice/SpeakingFlags =...): dev.kord.voice/DefaultFrameInterceptorData // dev.kord.voice/DefaultFrameInterceptorData.copy|copy(dev.kord.voice.SpeakingFlags){}[0] + final fun copy(dev.kord.voice/SpeakingFlags = ...): dev.kord.voice/DefaultFrameInterceptorData // dev.kord.voice/DefaultFrameInterceptorData.copy|copy(dev.kord.voice.SpeakingFlags){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/DefaultFrameInterceptorData.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice/DefaultFrameInterceptorData.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice/DefaultFrameInterceptorData.toString|toString(){}[0] - final val speakingState // dev.kord.voice/DefaultFrameInterceptorData.speakingState|{}speakingState[0] - final fun (): dev.kord.voice/SpeakingFlags // dev.kord.voice/DefaultFrameInterceptorData.speakingState.|(){}[0] } + final class dev.kord.voice/FrameInterceptorConfiguration { // dev.kord.voice/FrameInterceptorConfiguration|null[0] constructor (dev.kord.gateway/Gateway, dev.kord.voice.gateway/VoiceGateway, kotlin/UInt) // dev.kord.voice/FrameInterceptorConfiguration.|(dev.kord.gateway.Gateway;dev.kord.voice.gateway.VoiceGateway;kotlin.UInt){}[0] - final fun component1(): dev.kord.gateway/Gateway // dev.kord.voice/FrameInterceptorConfiguration.component1|component1(){}[0] - final fun component2(): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice/FrameInterceptorConfiguration.component2|component2(){}[0] - final fun component3(): kotlin/UInt // dev.kord.voice/FrameInterceptorConfiguration.component3|component3(){}[0] - final fun copy(dev.kord.gateway/Gateway =..., dev.kord.voice.gateway/VoiceGateway =..., kotlin/UInt =...): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice/FrameInterceptorConfiguration.copy|copy(dev.kord.gateway.Gateway;dev.kord.voice.gateway.VoiceGateway;kotlin.UInt){}[0] - final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/FrameInterceptorConfiguration.equals|equals(kotlin.Any?){}[0] - final fun hashCode(): kotlin/Int // dev.kord.voice/FrameInterceptorConfiguration.hashCode|hashCode(){}[0] - final fun toString(): kotlin/String // dev.kord.voice/FrameInterceptorConfiguration.toString|toString(){}[0] + final val gateway // dev.kord.voice/FrameInterceptorConfiguration.gateway|{}gateway[0] final fun (): dev.kord.gateway/Gateway // dev.kord.voice/FrameInterceptorConfiguration.gateway.|(){}[0] final val ssrc // dev.kord.voice/FrameInterceptorConfiguration.ssrc|{}ssrc[0] final fun (): kotlin/UInt // dev.kord.voice/FrameInterceptorConfiguration.ssrc.|(){}[0] final val voiceGateway // dev.kord.voice/FrameInterceptorConfiguration.voiceGateway|{}voiceGateway[0] final fun (): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice/FrameInterceptorConfiguration.voiceGateway.|(){}[0] + + final fun component1(): dev.kord.gateway/Gateway // dev.kord.voice/FrameInterceptorConfiguration.component1|component1(){}[0] + final fun component2(): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice/FrameInterceptorConfiguration.component2|component2(){}[0] + final fun component3(): kotlin/UInt // dev.kord.voice/FrameInterceptorConfiguration.component3|component3(){}[0] + final fun copy(dev.kord.gateway/Gateway = ..., dev.kord.voice.gateway/VoiceGateway = ..., kotlin/UInt = ...): dev.kord.voice/FrameInterceptorConfiguration // dev.kord.voice/FrameInterceptorConfiguration.copy|copy(dev.kord.gateway.Gateway;dev.kord.voice.gateway.VoiceGateway;kotlin.UInt){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/FrameInterceptorConfiguration.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/FrameInterceptorConfiguration.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice/FrameInterceptorConfiguration.toString|toString(){}[0] } + final class dev.kord.voice/SpeakingFlags { // dev.kord.voice/SpeakingFlags|null[0] - final class Builder { // dev.kord.voice/SpeakingFlags.Builder|null[0] - constructor (kotlin/Int =...) // dev.kord.voice/SpeakingFlags.Builder.|(kotlin.Int){}[0] - final fun (dev.kord.voice/SpeakingFlag).unaryMinus() // dev.kord.voice/SpeakingFlags.Builder.unaryMinus|unaryMinus@dev.kord.voice.SpeakingFlag(){}[0] - final fun (dev.kord.voice/SpeakingFlag).unaryPlus() // dev.kord.voice/SpeakingFlags.Builder.unaryPlus|unaryPlus@dev.kord.voice.SpeakingFlag(){}[0] - final fun (dev.kord.voice/SpeakingFlags).unaryMinus() // dev.kord.voice/SpeakingFlags.Builder.unaryMinus|unaryMinus@dev.kord.voice.SpeakingFlags(){}[0] - final fun (dev.kord.voice/SpeakingFlags).unaryPlus() // dev.kord.voice/SpeakingFlags.Builder.unaryPlus|unaryPlus@dev.kord.voice.SpeakingFlags(){}[0] - final fun build(): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.Builder.build|build(){}[0] - } + final val code // dev.kord.voice/SpeakingFlags.code|{}code[0] + final fun (): kotlin/Int // dev.kord.voice/SpeakingFlags.code.|(){}[0] + final val values // dev.kord.voice/SpeakingFlags.values|{}values[0] + final fun (): kotlin.collections/Set // dev.kord.voice/SpeakingFlags.values.|(){}[0] + final fun contains(dev.kord.voice/SpeakingFlag): kotlin/Boolean // dev.kord.voice/SpeakingFlags.contains|contains(dev.kord.voice.SpeakingFlag){}[0] final fun contains(dev.kord.voice/SpeakingFlags): kotlin/Boolean // dev.kord.voice/SpeakingFlags.contains|contains(dev.kord.voice.SpeakingFlags){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/SpeakingFlags.equals|equals(kotlin.Any?){}[0] @@ -687,21 +879,25 @@ final class dev.kord.voice/SpeakingFlags { // dev.kord.voice/SpeakingFlags|null[ final fun plus(dev.kord.voice/SpeakingFlags): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.plus|plus(dev.kord.voice.SpeakingFlags){}[0] final fun toString(): kotlin/String // dev.kord.voice/SpeakingFlags.toString|toString(){}[0] final inline fun copy(kotlin/Function1): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.copy|copy(kotlin.Function1){}[0] + + final class Builder { // dev.kord.voice/SpeakingFlags.Builder|null[0] + constructor (kotlin/Int = ...) // dev.kord.voice/SpeakingFlags.Builder.|(kotlin.Int){}[0] + + final fun (dev.kord.voice/SpeakingFlag).unaryMinus() // dev.kord.voice/SpeakingFlags.Builder.unaryMinus|unaryMinus@dev.kord.voice.SpeakingFlag(){}[0] + final fun (dev.kord.voice/SpeakingFlag).unaryPlus() // dev.kord.voice/SpeakingFlags.Builder.unaryPlus|unaryPlus@dev.kord.voice.SpeakingFlag(){}[0] + final fun (dev.kord.voice/SpeakingFlags).unaryMinus() // dev.kord.voice/SpeakingFlags.Builder.unaryMinus|unaryMinus@dev.kord.voice.SpeakingFlags(){}[0] + final fun (dev.kord.voice/SpeakingFlags).unaryPlus() // dev.kord.voice/SpeakingFlags.Builder.unaryPlus|unaryPlus@dev.kord.voice.SpeakingFlags(){}[0] + final fun build(): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags.Builder.build|build(){}[0] + } + final object Companion { // dev.kord.voice/SpeakingFlags.Companion|null[0] final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice/SpeakingFlags.Companion.serializer|serializer(){}[0] } - final val code // dev.kord.voice/SpeakingFlags.code|(){}[0] - final fun (): kotlin/Int // dev.kord.voice/SpeakingFlags.code.|(){}[0] - final val values // dev.kord.voice/SpeakingFlags.values|{}values[0] - final fun (): kotlin.collections/Set // dev.kord.voice/SpeakingFlags.values.|(){}[0] } + final class dev.kord.voice/VoiceConnection { // dev.kord.voice/VoiceConnection|null[0] - constructor (kotlinx.coroutines/CoroutineScope, dev.kord.voice/VoiceConnectionData, dev.kord.gateway/Gateway, dev.kord.voice.gateway/VoiceGateway, dev.kord.voice.udp/VoiceUdpSocket, dev.kord.voice.gateway/VoiceGatewayConfiguration, dev.kord.voice.streams/Streams, dev.kord.voice/AudioProvider, dev.kord.voice/FrameInterceptor, dev.kord.voice.udp/AudioFrameSender, dev.kord.voice.encryption.strategies/NonceStrategy, kotlin.time/Duration) // dev.kord.voice/VoiceConnection.|(kotlinx.coroutines.CoroutineScope;dev.kord.voice.VoiceConnectionData;dev.kord.gateway.Gateway;dev.kord.voice.gateway.VoiceGateway;dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.gateway.VoiceGatewayConfiguration;dev.kord.voice.streams.Streams;dev.kord.voice.AudioProvider;dev.kord.voice.FrameInterceptor;dev.kord.voice.udp.AudioFrameSender;dev.kord.voice.encryption.strategies.NonceStrategy;kotlin.time.Duration){}[0] - final suspend fun connect(kotlinx.coroutines/CoroutineScope =...) // dev.kord.voice/VoiceConnection.connect|connect(kotlinx.coroutines.CoroutineScope){}[0] - final suspend fun disconnect() // dev.kord.voice/VoiceConnection.disconnect|disconnect(){}[0] - final suspend fun leave() // dev.kord.voice/VoiceConnection.leave|leave(){}[0] - final suspend fun move(dev.kord.common.entity/Snowflake, kotlin/Boolean =..., kotlin/Boolean =...) // dev.kord.voice/VoiceConnection.move|move(dev.kord.common.entity.Snowflake;kotlin.Boolean;kotlin.Boolean){}[0] - final suspend fun shutdown() // dev.kord.voice/VoiceConnection.shutdown|shutdown(){}[0] + constructor (kotlinx.coroutines/CoroutineScope, dev.kord.voice/VoiceConnectionData, dev.kord.gateway/Gateway, dev.kord.voice.gateway/VoiceGateway, dev.kord.voice.udp/VoiceUdpSocket, dev.kord.voice.gateway/VoiceGatewayConfiguration, dev.kord.voice.streams/Streams, dev.kord.voice/AudioProvider, dev.kord.voice/FrameInterceptor, dev.kord.voice.udp/AudioFrameSender, dev.kord.voice.encryption.strategies/NonceStrategy, kotlin.time/Duration) // dev.kord.voice/VoiceConnection.|(kotlinx.coroutines.CoroutineScope;dev.kord.voice.VoiceConnectionData;dev.kord.gateway.Gateway;dev.kord.voice.gateway.VoiceGateway;dev.kord.voice.udp.VoiceUdpSocket;dev.kord.voice.gateway.VoiceGatewayConfiguration;dev.kord.voice.streams.Streams;dev.kord.voice.AudioProvider;dev.kord.voice.FrameInterceptor;dev.kord.voice.udp.AudioFrameSender;dev.kord.voice.encryption.strategies.NonceStrategy;kotlin.time.Duration){}[0] + final val audioProvider // dev.kord.voice/VoiceConnection.audioProvider|{}audioProvider[0] final fun (): dev.kord.voice/AudioProvider // dev.kord.voice/VoiceConnection.audioProvider.|(){}[0] final val data // dev.kord.voice/VoiceConnection.data|{}data[0] @@ -722,16 +918,21 @@ final class dev.kord.voice/VoiceConnection { // dev.kord.voice/VoiceConnection|n final fun (): dev.kord.voice.streams/Streams // dev.kord.voice/VoiceConnection.streams.|(){}[0] final val voiceGateway // dev.kord.voice/VoiceConnection.voiceGateway|{}voiceGateway[0] final fun (): dev.kord.voice.gateway/VoiceGateway // dev.kord.voice/VoiceConnection.voiceGateway.|(){}[0] + final var voiceGatewayConfiguration // dev.kord.voice/VoiceConnection.voiceGatewayConfiguration|{}voiceGatewayConfiguration[0] final fun (): dev.kord.voice.gateway/VoiceGatewayConfiguration // dev.kord.voice/VoiceConnection.voiceGatewayConfiguration.|(){}[0] final fun (dev.kord.voice.gateway/VoiceGatewayConfiguration) // dev.kord.voice/VoiceConnection.voiceGatewayConfiguration.|(dev.kord.voice.gateway.VoiceGatewayConfiguration){}[0] + + final suspend fun connect(kotlinx.coroutines/CoroutineScope = ...) // dev.kord.voice/VoiceConnection.connect|connect(kotlinx.coroutines.CoroutineScope){}[0] + final suspend fun disconnect() // dev.kord.voice/VoiceConnection.disconnect|disconnect(){}[0] + final suspend fun leave() // dev.kord.voice/VoiceConnection.leave|leave(){}[0] + final suspend fun move(dev.kord.common.entity/Snowflake, kotlin/Boolean = ..., kotlin/Boolean = ...) // dev.kord.voice/VoiceConnection.move|move(dev.kord.common.entity.Snowflake;kotlin.Boolean;kotlin.Boolean){}[0] + final suspend fun shutdown() // dev.kord.voice/VoiceConnection.shutdown|shutdown(){}[0] } + final class dev.kord.voice/VoiceConnectionBuilder { // dev.kord.voice/VoiceConnectionBuilder|null[0] constructor (dev.kord.gateway/Gateway, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake) // dev.kord.voice/VoiceConnectionBuilder.|(dev.kord.gateway.Gateway;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake){}[0] - final fun audioProvider(dev.kord.voice/AudioProvider) // dev.kord.voice/VoiceConnectionBuilder.audioProvider|audioProvider(dev.kord.voice.AudioProvider){}[0] - final fun frameInterceptor(dev.kord.voice/FrameInterceptor) // dev.kord.voice/VoiceConnectionBuilder.frameInterceptor|frameInterceptor(dev.kord.voice.FrameInterceptor){}[0] - final fun voiceGateway(kotlin/Function1) // dev.kord.voice/VoiceConnectionBuilder.voiceGateway|voiceGateway(kotlin.Function1){}[0] - final suspend fun build(): dev.kord.voice/VoiceConnection // dev.kord.voice/VoiceConnectionBuilder.build|build(){}[0] + final var audioProvider // dev.kord.voice/VoiceConnectionBuilder.audioProvider|{}audioProvider[0] final fun (): dev.kord.voice/AudioProvider? // dev.kord.voice/VoiceConnectionBuilder.audioProvider.|(){}[0] final fun (dev.kord.voice/AudioProvider?) // dev.kord.voice/VoiceConnectionBuilder.audioProvider.|(dev.kord.voice.AudioProvider?){}[0] @@ -780,235 +981,285 @@ final class dev.kord.voice/VoiceConnectionBuilder { // dev.kord.voice/VoiceConne final var udpSocket // dev.kord.voice/VoiceConnectionBuilder.udpSocket|{}udpSocket[0] final fun (): dev.kord.voice.udp/VoiceUdpSocket? // dev.kord.voice/VoiceConnectionBuilder.udpSocket.|(){}[0] final fun (dev.kord.voice.udp/VoiceUdpSocket?) // dev.kord.voice/VoiceConnectionBuilder.udpSocket.|(dev.kord.voice.udp.VoiceUdpSocket?){}[0] + + final fun audioProvider(dev.kord.voice/AudioProvider) // dev.kord.voice/VoiceConnectionBuilder.audioProvider|audioProvider(dev.kord.voice.AudioProvider){}[0] + final fun frameInterceptor(dev.kord.voice/FrameInterceptor) // dev.kord.voice/VoiceConnectionBuilder.frameInterceptor|frameInterceptor(dev.kord.voice.FrameInterceptor){}[0] + final fun voiceGateway(kotlin/Function1) // dev.kord.voice/VoiceConnectionBuilder.voiceGateway|voiceGateway(kotlin.Function1){}[0] + final suspend fun build(): dev.kord.voice/VoiceConnection // dev.kord.voice/VoiceConnectionBuilder.build|build(){}[0] } + final class dev.kord.voice/VoiceConnectionData { // dev.kord.voice/VoiceConnectionData|null[0] constructor (dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/String) // dev.kord.voice/VoiceConnectionData.|(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String){}[0] - final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.component1|component1(){}[0] - final fun component2(): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.component2|component2(){}[0] - final fun component3(): kotlin/String // dev.kord.voice/VoiceConnectionData.component3|component3(){}[0] - final fun copy(dev.kord.common.entity/Snowflake =..., dev.kord.common.entity/Snowflake =..., kotlin/String =...): dev.kord.voice/VoiceConnectionData // dev.kord.voice/VoiceConnectionData.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String){}[0] - final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/VoiceConnectionData.equals|equals(kotlin.Any?){}[0] - final fun hashCode(): kotlin/Int // dev.kord.voice/VoiceConnectionData.hashCode|hashCode(){}[0] - final fun toString(): kotlin/String // dev.kord.voice/VoiceConnectionData.toString|toString(){}[0] + final val guildId // dev.kord.voice/VoiceConnectionData.guildId|{}guildId[0] final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.guildId.|(){}[0] final val selfId // dev.kord.voice/VoiceConnectionData.selfId|{}selfId[0] final fun (): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.selfId.|(){}[0] final val sessionId // dev.kord.voice/VoiceConnectionData.sessionId|{}sessionId[0] final fun (): kotlin/String // dev.kord.voice/VoiceConnectionData.sessionId.|(){}[0] + + final fun component1(): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.component1|component1(){}[0] + final fun component2(): dev.kord.common.entity/Snowflake // dev.kord.voice/VoiceConnectionData.component2|component2(){}[0] + final fun component3(): kotlin/String // dev.kord.voice/VoiceConnectionData.component3|component3(){}[0] + final fun copy(dev.kord.common.entity/Snowflake = ..., dev.kord.common.entity/Snowflake = ..., kotlin/String = ...): dev.kord.voice/VoiceConnectionData // dev.kord.voice/VoiceConnectionData.copy|copy(dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.String){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/VoiceConnectionData.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // dev.kord.voice/VoiceConnectionData.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // dev.kord.voice/VoiceConnectionData.toString|toString(){}[0] } -final enum class dev.kord.voice.gateway/OpCode : kotlin/Enum { // dev.kord.voice.gateway/OpCode|null[0] - enum entry ClientDisconnect // dev.kord.voice.gateway/OpCode.ClientDisconnect|null[0] - enum entry Heartbeat // dev.kord.voice.gateway/OpCode.Heartbeat|null[0] - enum entry HeartbeatAck // dev.kord.voice.gateway/OpCode.HeartbeatAck|null[0] - enum entry Hello // dev.kord.voice.gateway/OpCode.Hello|null[0] - enum entry Identify // dev.kord.voice.gateway/OpCode.Identify|null[0] - enum entry Ready // dev.kord.voice.gateway/OpCode.Ready|null[0] - enum entry Resume // dev.kord.voice.gateway/OpCode.Resume|null[0] - enum entry Resumed // dev.kord.voice.gateway/OpCode.Resumed|null[0] - enum entry SelectProtocol // dev.kord.voice.gateway/OpCode.SelectProtocol|null[0] - enum entry SessionDescription // dev.kord.voice.gateway/OpCode.SessionDescription|null[0] - enum entry Speaking // dev.kord.voice.gateway/OpCode.Speaking|null[0] - enum entry Unknown // dev.kord.voice.gateway/OpCode.Unknown|null[0] - final fun valueOf(kotlin/String): dev.kord.voice.gateway/OpCode // dev.kord.voice.gateway/OpCode.valueOf|valueOf#static(kotlin.String){}[0] - final fun values(): kotlin/Array // dev.kord.voice.gateway/OpCode.values|values#static(){}[0] - final object Companion : kotlinx.serialization.internal/SerializerFactory { // dev.kord.voice.gateway/OpCode.Companion|null[0] - final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/OpCode.Companion.serializer|serializer(){}[0] - final fun serializer(kotlin/Array>...): kotlinx.serialization/KSerializer<*> // dev.kord.voice.gateway/OpCode.Companion.serializer|serializer(kotlin.Array>...){}[0] - } - final val code // dev.kord.voice.gateway/OpCode.code|{}code[0] - final fun (): kotlin/Int // dev.kord.voice.gateway/OpCode.code.|(){}[0] - final val entries // dev.kord.voice.gateway/OpCode.entries|#static(){}[0] - final fun (): kotlin.enums/EnumEntries // dev.kord.voice.gateway/OpCode.entries.|#static(){}[0] -} -final fun (dev.kord.voice.io/ByteArrayView).dev.kord.voice.io/mutableCursor(): dev.kord.voice.io/MutableByteArrayCursor // dev.kord.voice.io/mutableCursor|mutableCursor@dev.kord.voice.io.ByteArrayView(){}[0] -final fun (dev.kord.voice.io/ByteArrayView).dev.kord.voice.io/readableCursor(): dev.kord.voice.io/ReadableByteArrayCursor // dev.kord.voice.io/readableCursor|readableCursor@dev.kord.voice.io.ByteArrayView(){}[0] -final fun (dev.kord.voice.io/MutableByteArrayCursor).dev.kord.voice.io/writeByteArrayOrResize(kotlin/ByteArray) // dev.kord.voice.io/writeByteArrayOrResize|writeByteArrayOrResize@dev.kord.voice.io.MutableByteArrayCursor(kotlin.ByteArray){}[0] -final fun (dev.kord.voice.io/MutableByteArrayCursor).dev.kord.voice.io/writeByteViewOrResize(dev.kord.voice.io/ByteArrayView) // dev.kord.voice.io/writeByteViewOrResize|writeByteViewOrResize@dev.kord.voice.io.MutableByteArrayCursor(dev.kord.voice.io.ByteArrayView){}[0] -final fun (kotlin/ByteArray).dev.kord.voice.io/mutableCursor(): dev.kord.voice.io/MutableByteArrayCursor // dev.kord.voice.io/mutableCursor|mutableCursor@kotlin.ByteArray(){}[0] -final fun (kotlin/ByteArray).dev.kord.voice.io/readableCursor(): dev.kord.voice.io/ReadableByteArrayCursor // dev.kord.voice.io/readableCursor|readableCursor@kotlin.ByteArray(){}[0] -final fun (kotlin/ByteArray).dev.kord.voice.io/view(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/view|view@kotlin.ByteArray(){}[0] -final fun (kotlin/ByteArray).dev.kord.voice.io/view(kotlin/Int, kotlin/Int): dev.kord.voice.io/ByteArrayView? // dev.kord.voice.io/view|view@kotlin.ByteArray(kotlin.Int;kotlin.Int){}[0] -final fun dev.kord.voice.gateway/logCaughtThrowable(kotlin/Throwable) // dev.kord.voice.gateway/logCaughtThrowable|logCaughtThrowable(kotlin.Throwable){}[0] -final fun dev.kord.voice.udp/DefaultAudioPacketProvider(kotlin/ByteArray, dev.kord.voice.encryption.strategies/NonceStrategy): dev.kord.voice.udp/AudioPacketProvider // dev.kord.voice.udp/DefaultAudioPacketProvider|DefaultAudioPacketProvider(kotlin.ByteArray;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] -final fun dev.kord.voice.udp/RTPPacket(kotlin/UInt, kotlin/UInt, kotlin/UShort, kotlin/Byte, kotlin/ByteArray, kotlin/Function1 =...): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket|RTPPacket(kotlin.UInt;kotlin.UInt;kotlin.UShort;kotlin.Byte;kotlin.ByteArray;kotlin.Function1){}[0] -final fun dev.kord.voice/SpeakingFlags(kotlin.collections/Iterable): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.collections.Iterable){}[0] -final fun dev.kord.voice/SpeakingFlags(kotlin.collections/Iterable): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.collections.Iterable){}[0] -final fun dev.kord.voice/SpeakingFlags(kotlin/Array...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Array...){}[0] -final fun dev.kord.voice/SpeakingFlags(kotlin/Array...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Array...){}[0] -final inline fun <#A: reified dev.kord.voice.gateway/VoiceEvent> (dev.kord.voice.gateway/VoiceGateway).dev.kord.voice.gateway/on(kotlinx.coroutines/CoroutineScope =..., crossinline kotlin.coroutines/SuspendFunction1<#A, kotlin/Unit>): kotlinx.coroutines/Job // dev.kord.voice.gateway/on|on@dev.kord.voice.gateway.VoiceGateway(kotlinx.coroutines.CoroutineScope;kotlin.coroutines.SuspendFunction1<0:0,kotlin.Unit>){0§}[0] -final inline fun dev.kord.voice/SpeakingFlags(kotlin/Function1 =...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Function1){}[0] -final object dev.kord.voice.gateway/Resumed : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Resumed|null[0] - final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Resumed.serializer|serializer(){}[0] -} -final object dev.kord.voice.streams/NOPStreams : dev.kord.voice.streams/Streams { // dev.kord.voice.streams/NOPStreams|null[0] - final val incomingAudioFrames // dev.kord.voice.streams/NOPStreams.incomingAudioFrames|{}incomingAudioFrames[0] - final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/NOPStreams.incomingAudioFrames.|(){}[0] - final val incomingAudioPackets // dev.kord.voice.streams/NOPStreams.incomingAudioPackets|{}incomingAudioPackets[0] - final fun (): kotlinx.coroutines.flow/Flow // dev.kord.voice.streams/NOPStreams.incomingAudioPackets.|(){}[0] - final val incomingUserStreams // dev.kord.voice.streams/NOPStreams.incomingUserStreams|{}incomingUserStreams[0] - final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/NOPStreams.incomingUserStreams.|(){}[0] - final val ssrcToUser // dev.kord.voice.streams/NOPStreams.ssrcToUser|{}ssrcToUser[0] - final fun (): kotlin.collections/Map // dev.kord.voice.streams/NOPStreams.ssrcToUser.|(){}[0] - // Targets: [apple, linux] - final suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] - // Targets: [js, mingwX64] - final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] -} -final suspend inline fun dev.kord.voice/VoiceConnection(dev.kord.gateway/Gateway, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/Function1 =...): dev.kord.voice/VoiceConnection // dev.kord.voice/VoiceConnection|VoiceConnection(dev.kord.gateway.Gateway;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.Function1){}[0] -final val dev.kord.voice.udp/GlobalVoiceUdpSocket // dev.kord.voice.udp/GlobalVoiceUdpSocket|{}GlobalVoiceUdpSocket[0] - final fun (): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/GlobalVoiceUdpSocket.|(){}[0] + final value class dev.kord.voice/AudioFrame { // dev.kord.voice/AudioFrame|null[0] constructor (kotlin/ByteArray) // dev.kord.voice/AudioFrame.|(kotlin.ByteArray){}[0] + + final val data // dev.kord.voice/AudioFrame.data|{}data[0] + final fun (): kotlin/ByteArray // dev.kord.voice/AudioFrame.data.|(){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/AudioFrame.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice/AudioFrame.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice/AudioFrame.toString|toString(){}[0] + final object Companion { // dev.kord.voice/AudioFrame.Companion|null[0] - final fun fromData(kotlin/ByteArray?): dev.kord.voice/AudioFrame? // dev.kord.voice/AudioFrame.Companion.fromData|fromData(kotlin.ByteArray?){}[0] final val SILENCE // dev.kord.voice/AudioFrame.Companion.SILENCE|{}SILENCE[0] final fun (): dev.kord.voice/AudioFrame // dev.kord.voice/AudioFrame.Companion.SILENCE.|(){}[0] + + final fun fromData(kotlin/ByteArray?): dev.kord.voice/AudioFrame? // dev.kord.voice/AudioFrame.Companion.fromData|fromData(kotlin.ByteArray?){}[0] } - final val data // dev.kord.voice/AudioFrame.data|{}data[0] - final fun (): kotlin/ByteArray // dev.kord.voice/AudioFrame.data.|(){}[0] } + sealed class dev.kord.voice.gateway/Close : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Close|null[0] constructor () // dev.kord.voice.gateway/Close.|(){}[0] + final class DiscordClose : dev.kord.voice.gateway/Close { // dev.kord.voice.gateway/Close.DiscordClose|null[0] constructor (dev.kord.voice.gateway/VoiceGatewayCloseCode, kotlin/Boolean) // dev.kord.voice.gateway/Close.DiscordClose.|(dev.kord.voice.gateway.VoiceGatewayCloseCode;kotlin.Boolean){}[0] + + final val closeCode // dev.kord.voice.gateway/Close.DiscordClose.closeCode|{}closeCode[0] + final fun (): dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/Close.DiscordClose.closeCode.|(){}[0] + final val recoverable // dev.kord.voice.gateway/Close.DiscordClose.recoverable|{}recoverable[0] + final fun (): kotlin/Boolean // dev.kord.voice.gateway/Close.DiscordClose.recoverable.|(){}[0] + final fun component1(): dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/Close.DiscordClose.component1|component1(){}[0] final fun component2(): kotlin/Boolean // dev.kord.voice.gateway/Close.DiscordClose.component2|component2(){}[0] - final fun copy(dev.kord.voice.gateway/VoiceGatewayCloseCode =..., kotlin/Boolean =...): dev.kord.voice.gateway/Close.DiscordClose // dev.kord.voice.gateway/Close.DiscordClose.copy|copy(dev.kord.voice.gateway.VoiceGatewayCloseCode;kotlin.Boolean){}[0] + final fun copy(dev.kord.voice.gateway/VoiceGatewayCloseCode = ..., kotlin/Boolean = ...): dev.kord.voice.gateway/Close.DiscordClose // dev.kord.voice.gateway/Close.DiscordClose.copy|copy(dev.kord.voice.gateway.VoiceGatewayCloseCode;kotlin.Boolean){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.gateway/Close.DiscordClose.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.gateway/Close.DiscordClose.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.gateway/Close.DiscordClose.toString|toString(){}[0] - final val closeCode // dev.kord.voice.gateway/Close.DiscordClose.closeCode|{}closeCode[0] - final fun (): dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/Close.DiscordClose.closeCode.|(){}[0] - final val recoverable // dev.kord.voice.gateway/Close.DiscordClose.recoverable|{}recoverable[0] - final fun (): kotlin/Boolean // dev.kord.voice.gateway/Close.DiscordClose.recoverable.|(){}[0] } + final object Reconnecting : dev.kord.voice.gateway/Close // dev.kord.voice.gateway/Close.Reconnecting|null[0] + final object RetryLimitReached : dev.kord.voice.gateway/Close // dev.kord.voice.gateway/Close.RetryLimitReached|null[0] + final object Timeout : dev.kord.voice.gateway/Close // dev.kord.voice.gateway/Close.Timeout|null[0] + final object UserClose : dev.kord.voice.gateway/Close // dev.kord.voice.gateway/Close.UserClose|null[0] } + sealed class dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Command|null[0] constructor () // dev.kord.voice.gateway/Command.|(){}[0] + final object SerializationStrategy : kotlinx.serialization/SerializationStrategy { // dev.kord.voice.gateway/Command.SerializationStrategy|null[0] - final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/Command.SerializationStrategy.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Command){}[0] final val descriptor // dev.kord.voice.gateway/Command.SerializationStrategy.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Command.SerializationStrategy.descriptor.|(){}[0] + + final fun serialize(kotlinx.serialization.encoding/Encoder, dev.kord.voice.gateway/Command) // dev.kord.voice.gateway/Command.SerializationStrategy.serialize|serialize(kotlinx.serialization.encoding.Encoder;dev.kord.voice.gateway.Command){}[0] } } + sealed class dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/VoiceEvent|null[0] constructor () // dev.kord.voice.gateway/VoiceEvent.|(){}[0] + final object DeserializationStrategy : kotlinx.serialization/DeserializationStrategy { // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy|null[0] - final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/VoiceEvent? // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] final val descriptor // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.descriptor.|(){}[0] + + final fun deserialize(kotlinx.serialization.encoding/Decoder): dev.kord.voice.gateway/VoiceEvent? // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0] } } + sealed class dev.kord.voice.gateway/VoiceGatewayCloseCode { // dev.kord.voice.gateway/VoiceGatewayCloseCode|null[0] constructor (kotlin/Int) // dev.kord.voice.gateway/VoiceGatewayCloseCode.|(kotlin.Int){}[0] + + final val code // dev.kord.voice.gateway/VoiceGatewayCloseCode.code|{}code[0] + final fun (): kotlin/Int // dev.kord.voice.gateway/VoiceGatewayCloseCode.code.|(){}[0] + final class Unknown : dev.kord.voice.gateway/VoiceGatewayCloseCode { // dev.kord.voice.gateway/VoiceGatewayCloseCode.Unknown|null[0] constructor (kotlin/Int) // dev.kord.voice.gateway/VoiceGatewayCloseCode.Unknown.|(kotlin.Int){}[0] } + final object AlreadyAuthenticated : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.AlreadyAuthenticated|null[0] + final object AuthenticationFailed : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.AuthenticationFailed|null[0] + final object Companion { // dev.kord.voice.gateway/VoiceGatewayCloseCode.Companion|null[0] final fun of(kotlin/Int): dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.Companion.of|of(kotlin.Int){}[0] } + final object Disconnect : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.Disconnect|null[0] + final object FailedToDecodePayload : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.FailedToDecodePayload|null[0] + final object NotAuthenticated : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.NotAuthenticated|null[0] + final object ServerNotFound : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.ServerNotFound|null[0] + final object SessionNoLongerValid : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.SessionNoLongerValid|null[0] + final object SessionTimeout : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.SessionTimeout|null[0] + final object UnknownEncryptionMode : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.UnknownEncryptionMode|null[0] + final object UnknownOpcode : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.UnknownOpcode|null[0] + final object UnknownProtocol : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.UnknownProtocol|null[0] + final object VoiceServerCrashed : dev.kord.voice.gateway/VoiceGatewayCloseCode // dev.kord.voice.gateway/VoiceGatewayCloseCode.VoiceServerCrashed|null[0] - final val code // dev.kord.voice.gateway/VoiceGatewayCloseCode.code|{}code[0] - final fun (): kotlin/Int // dev.kord.voice.gateway/VoiceGatewayCloseCode.code.|(){}[0] } + sealed class dev.kord.voice.udp/PayloadType { // dev.kord.voice.udp/PayloadType|null[0] constructor (kotlin/Byte) // dev.kord.voice.udp/PayloadType.|(kotlin.Byte){}[0] + + final val raw // dev.kord.voice.udp/PayloadType.raw|{}raw[0] + final fun (): kotlin/Byte // dev.kord.voice.udp/PayloadType.raw.|(){}[0] + final class Unknown : dev.kord.voice.udp/PayloadType { // dev.kord.voice.udp/PayloadType.Unknown|null[0] constructor (kotlin/Byte) // dev.kord.voice.udp/PayloadType.Unknown.|(kotlin.Byte){}[0] + final fun toString(): kotlin/String // dev.kord.voice.udp/PayloadType.Unknown.toString|toString(){}[0] } + final object Alive : dev.kord.voice.udp/PayloadType // dev.kord.voice.udp/PayloadType.Alive|null[0] + final object Audio : dev.kord.voice.udp/PayloadType // dev.kord.voice.udp/PayloadType.Audio|null[0] + final object Companion { // dev.kord.voice.udp/PayloadType.Companion|null[0] final fun from(kotlin/Byte): dev.kord.voice.udp/PayloadType // dev.kord.voice.udp/PayloadType.Companion.from|from(kotlin.Byte){}[0] } - final val raw // dev.kord.voice.udp/PayloadType.raw|{}raw[0] - final fun (): kotlin/Byte // dev.kord.voice.udp/PayloadType.raw.|(){}[0] } + sealed class dev.kord.voice/EncryptionMode { // dev.kord.voice/EncryptionMode|null[0] constructor (kotlin/String) // dev.kord.voice/EncryptionMode.|(kotlin.String){}[0] - final class Unknown : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.Unknown|null[0] + + final val value // dev.kord.voice/EncryptionMode.value|{}value[0] + final fun (): kotlin/String // dev.kord.voice/EncryptionMode.value.|(){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/EncryptionMode.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice/EncryptionMode.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice/EncryptionMode.toString|toString(){}[0] + + final class Unknown : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.Unknown|null[0] + final object Companion { // dev.kord.voice/EncryptionMode.Companion|null[0] - final fun from(kotlin/String): dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.Companion.from|from(kotlin.String){}[0] - final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice/EncryptionMode.Companion.serializer|serializer(){}[0] final val entries // dev.kord.voice/EncryptionMode.Companion.entries|{}entries[0] final fun (): kotlin.collections/List // dev.kord.voice/EncryptionMode.Companion.entries.|(){}[0] + + final fun from(kotlin/String): dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.Companion.from|from(kotlin.String){}[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice/EncryptionMode.Companion.serializer|serializer(){}[0] } + final object XSalsa20Poly1305 : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.XSalsa20Poly1305|null[0] + final object XSalsa20Poly1305Lite : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.XSalsa20Poly1305Lite|null[0] + final object XSalsa20Poly1305Suffix : dev.kord.voice/EncryptionMode // dev.kord.voice/EncryptionMode.XSalsa20Poly1305Suffix|null[0] - final val value // dev.kord.voice/EncryptionMode.value|{}value[0] - final fun (): kotlin/String // dev.kord.voice/EncryptionMode.value.|(){}[0] } + sealed class dev.kord.voice/SpeakingFlag { // dev.kord.voice/SpeakingFlag|null[0] constructor (kotlin/Int) // dev.kord.voice/SpeakingFlag.|(kotlin.Int){}[0] - final class Unknown : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Unknown|null[0] + + final val code // dev.kord.voice/SpeakingFlag.code|{}code[0] + final fun (): kotlin/Int // dev.kord.voice/SpeakingFlag.code.|(){}[0] + final val shift // dev.kord.voice/SpeakingFlag.shift|{}shift[0] + final fun (): kotlin/Int // dev.kord.voice/SpeakingFlag.shift.|(){}[0] + final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice/SpeakingFlag.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice/SpeakingFlag.hashCode|hashCode(){}[0] final fun plus(dev.kord.voice/SpeakingFlag): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlag.plus|plus(dev.kord.voice.SpeakingFlag){}[0] final fun plus(dev.kord.voice/SpeakingFlags): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlag.plus|plus(dev.kord.voice.SpeakingFlags){}[0] final fun toString(): kotlin/String // dev.kord.voice/SpeakingFlag.toString|toString(){}[0] + + final class Unknown : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Unknown|null[0] + final object Companion { // dev.kord.voice/SpeakingFlag.Companion|null[0] - final fun fromShift(kotlin/Int): dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Companion.fromShift|fromShift(kotlin.Int){}[0] final val entries // dev.kord.voice/SpeakingFlag.Companion.entries|{}entries[0] final fun (): kotlin.collections/List // dev.kord.voice/SpeakingFlag.Companion.entries.|(){}[0] + + final fun fromShift(kotlin/Int): dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Companion.fromShift|fromShift(kotlin.Int){}[0] } + final object Microphone : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Microphone|null[0] + final object Priority : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Priority|null[0] + final object Soundshare : dev.kord.voice/SpeakingFlag // dev.kord.voice/SpeakingFlag.Soundshare|null[0] - final val code // dev.kord.voice/SpeakingFlag.code|{}code[0] - final fun (): kotlin/Int // dev.kord.voice/SpeakingFlag.code.|(){}[0] - final val shift // dev.kord.voice/SpeakingFlag.shift|{}shift[0] - final fun (): kotlin/Int // dev.kord.voice/SpeakingFlag.shift.|(){}[0] } -sealed interface dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/NonceStrategy|null[0] - abstract fun append(dev.kord.voice.io/ByteArrayView, dev.kord.voice.io/MutableByteArrayCursor) // dev.kord.voice.encryption.strategies/NonceStrategy.append|append(dev.kord.voice.io.ByteArrayView;dev.kord.voice.io.MutableByteArrayCursor){}[0] - abstract fun generate(kotlin/Function0): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NonceStrategy.generate|generate(kotlin.Function0){}[0] - abstract fun strip(dev.kord.voice.udp/RTPPacket): dev.kord.voice.io/ByteArrayView // dev.kord.voice.encryption.strategies/NonceStrategy.strip|strip(dev.kord.voice.udp.RTPPacket){}[0] - abstract val nonceLength // dev.kord.voice.encryption.strategies/NonceStrategy.nonceLength|{}nonceLength[0] - abstract fun (): kotlin/Int // dev.kord.voice.encryption.strategies/NonceStrategy.nonceLength.|(){}[0] + +final object dev.kord.voice.gateway/Resumed : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Resumed|null[0] + final fun serializer(): kotlinx.serialization/KSerializer // dev.kord.voice.gateway/Resumed.serializer|serializer(){}[0] +} + +final object dev.kord.voice.streams/NOPStreams : dev.kord.voice.streams/Streams { // dev.kord.voice.streams/NOPStreams|null[0] + final val incomingAudioFrames // dev.kord.voice.streams/NOPStreams.incomingAudioFrames|{}incomingAudioFrames[0] + final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/NOPStreams.incomingAudioFrames.|(){}[0] + final val incomingAudioPackets // dev.kord.voice.streams/NOPStreams.incomingAudioPackets|{}incomingAudioPackets[0] + final fun (): kotlinx.coroutines.flow/Flow // dev.kord.voice.streams/NOPStreams.incomingAudioPackets.|(){}[0] + final val incomingUserStreams // dev.kord.voice.streams/NOPStreams.incomingUserStreams|{}incomingUserStreams[0] + final fun (): kotlinx.coroutines.flow/Flow> // dev.kord.voice.streams/NOPStreams.incomingUserStreams.|(){}[0] + final val ssrcToUser // dev.kord.voice.streams/NOPStreams.ssrcToUser|{}ssrcToUser[0] + final fun (): kotlin.collections/Map // dev.kord.voice.streams/NOPStreams.ssrcToUser.|(){}[0] + + // Targets: [apple, linux] + final suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] + + // Targets: [js, mingwX64] + final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } + +final val dev.kord.voice.udp/GlobalVoiceUdpSocket // dev.kord.voice.udp/GlobalVoiceUdpSocket|{}GlobalVoiceUdpSocket[0] + final fun (): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/GlobalVoiceUdpSocket.|(){}[0] + +final fun (dev.kord.voice.io/ByteArrayView).dev.kord.voice.io/mutableCursor(): dev.kord.voice.io/MutableByteArrayCursor // dev.kord.voice.io/mutableCursor|mutableCursor@dev.kord.voice.io.ByteArrayView(){}[0] +final fun (dev.kord.voice.io/ByteArrayView).dev.kord.voice.io/readableCursor(): dev.kord.voice.io/ReadableByteArrayCursor // dev.kord.voice.io/readableCursor|readableCursor@dev.kord.voice.io.ByteArrayView(){}[0] +final fun (dev.kord.voice.io/MutableByteArrayCursor).dev.kord.voice.io/writeByteArrayOrResize(kotlin/ByteArray) // dev.kord.voice.io/writeByteArrayOrResize|writeByteArrayOrResize@dev.kord.voice.io.MutableByteArrayCursor(kotlin.ByteArray){}[0] +final fun (dev.kord.voice.io/MutableByteArrayCursor).dev.kord.voice.io/writeByteViewOrResize(dev.kord.voice.io/ByteArrayView) // dev.kord.voice.io/writeByteViewOrResize|writeByteViewOrResize@dev.kord.voice.io.MutableByteArrayCursor(dev.kord.voice.io.ByteArrayView){}[0] +final fun (kotlin/ByteArray).dev.kord.voice.io/mutableCursor(): dev.kord.voice.io/MutableByteArrayCursor // dev.kord.voice.io/mutableCursor|mutableCursor@kotlin.ByteArray(){}[0] +final fun (kotlin/ByteArray).dev.kord.voice.io/readableCursor(): dev.kord.voice.io/ReadableByteArrayCursor // dev.kord.voice.io/readableCursor|readableCursor@kotlin.ByteArray(){}[0] +final fun (kotlin/ByteArray).dev.kord.voice.io/view(): dev.kord.voice.io/ByteArrayView // dev.kord.voice.io/view|view@kotlin.ByteArray(){}[0] +final fun (kotlin/ByteArray).dev.kord.voice.io/view(kotlin/Int, kotlin/Int): dev.kord.voice.io/ByteArrayView? // dev.kord.voice.io/view|view@kotlin.ByteArray(kotlin.Int;kotlin.Int){}[0] +final fun dev.kord.voice.gateway/logCaughtThrowable(kotlin/Throwable) // dev.kord.voice.gateway/logCaughtThrowable|logCaughtThrowable(kotlin.Throwable){}[0] +final fun dev.kord.voice.udp/DefaultAudioPacketProvider(kotlin/ByteArray, dev.kord.voice.encryption.strategies/NonceStrategy): dev.kord.voice.udp/AudioPacketProvider // dev.kord.voice.udp/DefaultAudioPacketProvider|DefaultAudioPacketProvider(kotlin.ByteArray;dev.kord.voice.encryption.strategies.NonceStrategy){}[0] +final fun dev.kord.voice.udp/RTPPacket(kotlin/UInt, kotlin/UInt, kotlin/UShort, kotlin/Byte, kotlin/ByteArray, kotlin/Function1 = ...): dev.kord.voice.udp/RTPPacket // dev.kord.voice.udp/RTPPacket|RTPPacket(kotlin.UInt;kotlin.UInt;kotlin.UShort;kotlin.Byte;kotlin.ByteArray;kotlin.Function1){}[0] +final fun dev.kord.voice/SpeakingFlags(kotlin.collections/Iterable): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.collections.Iterable){}[0] +final fun dev.kord.voice/SpeakingFlags(kotlin.collections/Iterable): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.collections.Iterable){}[0] +final fun dev.kord.voice/SpeakingFlags(kotlin/Array...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Array...){}[0] +final fun dev.kord.voice/SpeakingFlags(kotlin/Array...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Array...){}[0] +final inline fun <#A: reified dev.kord.voice.gateway/VoiceEvent> (dev.kord.voice.gateway/VoiceGateway).dev.kord.voice.gateway/on(kotlinx.coroutines/CoroutineScope = ..., crossinline kotlin.coroutines/SuspendFunction1<#A, kotlin/Unit>): kotlinx.coroutines/Job // dev.kord.voice.gateway/on|on@dev.kord.voice.gateway.VoiceGateway(kotlinx.coroutines.CoroutineScope;kotlin.coroutines.SuspendFunction1<0:0,kotlin.Unit>){0§}[0] +final inline fun dev.kord.voice/SpeakingFlags(kotlin/Function1 = ...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Function1){}[0] +final suspend inline fun dev.kord.voice/VoiceConnection(dev.kord.gateway/Gateway, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/Function1 = ...): dev.kord.voice/VoiceConnection // dev.kord.voice/VoiceConnection|VoiceConnection(dev.kord.gateway.Gateway;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.Function1){}[0] + // Targets: [apple, linux] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(io.ktor.network.sockets/InetSocketAddress, kotlin/Int): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress;kotlin.Int){}[0] + // Targets: [apple, linux] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(io.ktor.network.sockets/InetSocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [js, mingwX64] final class dev.kord.voice.udp/SocketAddress { // dev.kord.voice.udp/SocketAddress|null[0] constructor (kotlin/String, kotlin/Int) // dev.kord.voice.udp/SocketAddress.|(kotlin.String;kotlin.Int){}[0] + + final val hostname // dev.kord.voice.udp/SocketAddress.hostname|{}hostname[0] + final fun (): kotlin/String // dev.kord.voice.udp/SocketAddress.hostname.|(){}[0] + final val port // dev.kord.voice.udp/SocketAddress.port|{}port[0] + final fun (): kotlin/Int // dev.kord.voice.udp/SocketAddress.port.|(){}[0] + final fun component1(): kotlin/String // dev.kord.voice.udp/SocketAddress.component1|component1(){}[0] final fun component2(): kotlin/Int // dev.kord.voice.udp/SocketAddress.component2|component2(){}[0] - final fun copy(kotlin/String =..., kotlin/Int =...): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/SocketAddress.copy|copy(kotlin.String;kotlin.Int){}[0] + final fun copy(kotlin/String = ..., kotlin/Int = ...): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/SocketAddress.copy|copy(kotlin.String;kotlin.Int){}[0] final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.voice.udp/SocketAddress.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // dev.kord.voice.udp/SocketAddress.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.udp/SocketAddress.toString|toString(){}[0] - final val hostname // dev.kord.voice.udp/SocketAddress.hostname|{}hostname[0] - final fun (): kotlin/String // dev.kord.voice.udp/SocketAddress.hostname.|(){}[0] - final val port // dev.kord.voice.udp/SocketAddress.port|{}port[0] - final fun (): kotlin/Int // dev.kord.voice.udp/SocketAddress.port.|(){}[0] } + // Targets: [js, mingwX64] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(dev.kord.voice.udp/SocketAddress, kotlin/Int): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress;kotlin.Int){}[0] + // Targets: [js, mingwX64] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(dev.kord.voice.udp/SocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress){}[0] diff --git a/voice/src/commonMain/kotlin/gateway/VoiceGateway.kt b/voice/src/commonMain/kotlin/gateway/VoiceGateway.kt index f058e0fee36..27b9d0aead7 100644 --- a/voice/src/commonMain/kotlin/gateway/VoiceGateway.kt +++ b/voice/src/commonMain/kotlin/gateway/VoiceGateway.kt @@ -85,12 +85,6 @@ public interface VoiceGateway { public suspend fun detach() } - -@Suppress("unused") -@Deprecated("Binary compatibility, remove after deprecation cycle.", level = DeprecationLevel.ERROR) -@PublishedApi -internal val voiceGatewayOnLogger: mu.KLogger = mu.KotlinLogging.logger("Gateway.on") - /** * Logger used to report [Throwable]s caught in [VoiceGateway.on]. */ From 00d8b98b721403183657232726e208a601dfd4f1 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 2 Jul 2024 18:24:20 +0200 Subject: [PATCH 74/83] Add missing opt ins --- buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index df2404123d6..20b91f0192f 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -44,13 +44,13 @@ kotlin { targets() explicitApi() jvmToolchain(Jvm.target) - compilerOptions { applyKordCompilerOptions() optIn.addAll(kordOptIns) } sourceSets { + applyKordTestOptIns() commonMain { // mark ksp src dir kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin") From 0bb255067cbfa0883c4785fd188dd8c3ce7c6b28 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 2 Jul 2024 21:18:17 +0200 Subject: [PATCH 75/83] Fix build --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8863602633f..cad66ed2dd4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -34,7 +34,7 @@ dokka = "1.9.20" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.25.0" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.15.0-Beta.3" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "5.3.5" # https://github.com/gmazzo/gradle-buildconfig-plugin -kord-gradle-tools = "1.6.0" # https://github.com/kordlib/gradle-tools +kord-gradle-tools = "1.6.1" # https://github.com/kordlib/gradle-tools maven-publish-plugin = "0.27.0" # https://github.com/vanniktech/gradle-maven-publish-plugin [libraries] From 9d86e3147a8157c40b8a65c4dad11e21e1600127 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Tue, 2 Jul 2024 21:37:19 +0200 Subject: [PATCH 76/83] Fix build --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cad66ed2dd4..01ed30a3dab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -34,7 +34,7 @@ dokka = "1.9.20" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.25.0" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.15.0-Beta.3" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "5.3.5" # https://github.com/gmazzo/gradle-buildconfig-plugin -kord-gradle-tools = "1.6.1" # https://github.com/kordlib/gradle-tools +kord-gradle-tools = "1.6.2" # https://github.com/kordlib/gradle-tools maven-publish-plugin = "0.27.0" # https://github.com/vanniktech/gradle-maven-publish-plugin [libraries] From 4ea31994866f78d8a1901fe509ea7b22160461ce Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Thu, 18 Jul 2024 21:55:52 +0200 Subject: [PATCH 77/83] Update to Ktor 3.0.0-beta-2 --- .../kord-multiplatform-module.gradle.kts | 2 +- common/src/nonJvmMain/kotlin/DiscordBitSet.kt | 14 ++++++------- gradle/libs.versions.toml | 4 +++- rest/src/commonTest/kotlin/json/Util.kt | 2 +- .../kotlin/request/MessageRequests.kt | 3 +-- test-kit/src/commonMain/kotlin/Platform.kt | 3 ++- test-kit/src/jsMain/kotlin/Platform.kt | 2 +- test-kit/src/jvmMain/kotlin/Platform.kt | 3 ++- test-kit/src/nativeMain/kotlin/Platform.kt | 2 +- voice/api/voice.api | 2 +- voice/api/voice.klib.api | 20 ++++++++++++------- voice/src/commonMain/kotlin/udp/RTPPacket.kt | 7 +++++-- .../commonMain/kotlin/udp/VoiceUdpSocket.kt | 7 ++++--- .../src/commonMain/kotlin/udp/ipDiscovery.kt | 7 ++++--- .../jsMain/kotlin/udp/VoiceUdpSocket.js.kt | 3 ++- .../kotlin/udp/VoiceUdpSocket.ktor.kt | 3 ++- .../kotlin/udp/VoiceUdpSocket.mingw.kt | 4 ++-- 17 files changed, 52 insertions(+), 36 deletions(-) diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 20b91f0192f..b9c3f13f541 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -78,7 +78,7 @@ tasks { afterEvaluate { val compilationTasks = kotlin.targets.flatMap { - listOf("compileKotlin${it.name.capitalized()}", "${it.name}SourcesJar") + listOf("compileKotlin${it.name.replaceFirstChar(Char::titlecase)}", "${it.name}SourcesJar") } for (task in compilationTasks) { named(task) { diff --git a/common/src/nonJvmMain/kotlin/DiscordBitSet.kt b/common/src/nonJvmMain/kotlin/DiscordBitSet.kt index c883976ebf8..77a1de493bf 100644 --- a/common/src/nonJvmMain/kotlin/DiscordBitSet.kt +++ b/common/src/nonJvmMain/kotlin/DiscordBitSet.kt @@ -2,14 +2,14 @@ package dev.kord.common import com.ionspin.kotlin.bignum.integer.BigInteger import com.ionspin.kotlin.bignum.integer.Sign -import io.ktor.utils.io.core.* +import kotlinx.io.Buffer +import kotlinx.io.readByteArray -internal actual fun formatIntegerFromLittleEndianLongArray(data: LongArray) = - withBuffer(data.size * Long.SIZE_BYTES) { - // need to convert from little-endian data to big-endian expected by BigInteger - writeFully(data.reversedArray()) - BigInteger.fromByteArray(readBytes(), Sign.POSITIVE).toString() - } +internal actual fun formatIntegerFromLittleEndianLongArray(data: LongArray): String { + val buffer = Buffer() + data.reversedArray().forEach(buffer::writeLong) + return BigInteger.fromByteArray(buffer.readByteArray(), Sign.POSITIVE).toString() +} internal actual fun parseNonNegativeIntegerToBigEndianByteArray(value: String): ByteArray = BigInteger .parseString(value) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9fde325e057..d83ae947ac5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,6 +9,7 @@ kotlinx-datetime = "0.6.0" # https://github.com/Kotlin/kotlinx-datetime kord-cache = "0.5.4" # https://github.com/kordlib/cache # implementation dependencies +kotlinx-io = "0.5.1" # https://github.com/Kotlin/kotlinx-io kotlin-logging = "7.0.0" # https://github.com/oshai/kotlin-logging slf4j = "2.0.13" # https://www.slf4j.org kotlin-node = "20.14.10-pre.773" # https://github.com/JetBrains/kotlin-wrappers @@ -32,7 +33,8 @@ dokka = "1.9.20" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.25.0" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.15.1" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "5.4.0" # https://github.com/gmazzo/gradle-buildconfig-plugin - +kord-gradle-tools = "1.6.2" # https://github.com/kordlib/gradle-tools/blob/main/build.gradle.kts#L10 +maven-publish-plugin = "0.29.0" # https://github.com/vanniktech/gradle-maven-publish-plugin [libraries] diff --git a/rest/src/commonTest/kotlin/json/Util.kt b/rest/src/commonTest/kotlin/json/Util.kt index dd6f1420ef5..5f47781fe40 100644 --- a/rest/src/commonTest/kotlin/json/Util.kt +++ b/rest/src/commonTest/kotlin/json/Util.kt @@ -5,4 +5,4 @@ import dev.kord.test.file as platformFile import dev.kord.test.readFile as platformReadFile internal suspend fun file(name: String): String = platformFile("rest", "json/$name.json") -internal suspend fun readFile(name: String): ByteReadChannel = platformReadFile("rest", name) +internal suspend fun readFile(name: String): CountedByteReadChannel = platformReadFile("rest", name) diff --git a/rest/src/commonTest/kotlin/request/MessageRequests.kt b/rest/src/commonTest/kotlin/request/MessageRequests.kt index 4ce92ad2cff..a49498723ed 100644 --- a/rest/src/commonTest/kotlin/request/MessageRequests.kt +++ b/rest/src/commonTest/kotlin/request/MessageRequests.kt @@ -13,6 +13,7 @@ import dev.kord.test.Platform import io.ktor.client.* import io.ktor.client.engine.mock.* import io.ktor.client.request.forms.* +import io.ktor.utils.io.* import kotlinx.coroutines.test.runTest import kotlinx.datetime.Clock import kotlinx.serialization.encodeToString @@ -67,7 +68,6 @@ class MessageRequests { val fileChannel = readFile("images/kord.png") with(fileChannel) { - if (Platform.IS_JVM) assertFalse(isClosedForWrite) // only read lazily on jvm assertFalse(isClosedForRead) assertEquals(0L, totalBytesRead) @@ -76,7 +76,6 @@ class MessageRequests { } assertEquals(mockMessage, createdMessage) - assertTrue(isClosedForWrite) assertTrue(isClosedForRead) assertTrue(totalBytesRead > 0L) } diff --git a/test-kit/src/commonMain/kotlin/Platform.kt b/test-kit/src/commonMain/kotlin/Platform.kt index 9c3e732f129..6fbe0600f97 100644 --- a/test-kit/src/commonMain/kotlin/Platform.kt +++ b/test-kit/src/commonMain/kotlin/Platform.kt @@ -13,4 +13,5 @@ expect object Platform { expect fun getEnv(name: String): String? expect suspend fun file(project: String, path: String): String -expect suspend fun readFile(project: String, path: String): ByteReadChannel +suspend fun readFile(project: String, path: String) = readFile0(project, path).counted() +expect suspend fun readFile0(project: String, path: String): ByteReadChannel diff --git a/test-kit/src/jsMain/kotlin/Platform.kt b/test-kit/src/jsMain/kotlin/Platform.kt index c9cc7a4220a..5d5094b8275 100644 --- a/test-kit/src/jsMain/kotlin/Platform.kt +++ b/test-kit/src/jsMain/kotlin/Platform.kt @@ -23,5 +23,5 @@ actual fun getEnv(name: String) = process.env[name] actual suspend fun file(project: String, path: String): String = if (Platform.IS_NODE) nodeFile(project, path) else TODO("Browser JS is not supported yet") -actual suspend fun readFile(project: String, path: String): ByteReadChannel = +actual suspend fun readFile0(project: String, path: String): ByteReadChannel = if (Platform.IS_NODE) nodeReadFile(project, path) else TODO("Browser JS is not supported yet") diff --git a/test-kit/src/jvmMain/kotlin/Platform.kt b/test-kit/src/jvmMain/kotlin/Platform.kt index d70783d045a..616692b9c31 100644 --- a/test-kit/src/jvmMain/kotlin/Platform.kt +++ b/test-kit/src/jvmMain/kotlin/Platform.kt @@ -1,3 +1,4 @@ +@file:JvmName("PlatformJvm") package dev.kord.test import io.ktor.utils.io.* @@ -14,5 +15,5 @@ actual object Platform { actual fun getEnv(name: String): String? = System.getenv(name) actual suspend fun file(project: String, path: String): String = ClassLoader.getSystemResource(path).readText() -actual suspend fun readFile(project: String, path: String): ByteReadChannel = +actual suspend fun readFile0(project: String, path: String): ByteReadChannel = ClassLoader.getSystemResourceAsStream(path)!!.toByteReadChannel() diff --git a/test-kit/src/nativeMain/kotlin/Platform.kt b/test-kit/src/nativeMain/kotlin/Platform.kt index 01887908a3e..d15f5d0dbf7 100644 --- a/test-kit/src/nativeMain/kotlin/Platform.kt +++ b/test-kit/src/nativeMain/kotlin/Platform.kt @@ -28,7 +28,7 @@ actual fun getEnv(name: String) = getenv(name)?.toKString() actual suspend fun file(project: String, path: String): String = read(project, path, Source::readString) -actual suspend fun readFile(project: String, path: String): ByteReadChannel = +actual suspend fun readFile0(project: String, path: String): ByteReadChannel = read(project, path) { ByteReadChannel(readByteArray()) } private inline fun read(project: String, path: String, readerAction: Source.() -> T): T { diff --git a/voice/api/voice.api b/voice/api/voice.api index 085c7a52ed8..59f0ab8da34 100644 --- a/voice/api/voice.api +++ b/voice/api/voice.api @@ -1234,7 +1234,7 @@ public final class dev/kord/voice/udp/RTPPacket$Builder { } public final class dev/kord/voice/udp/RTPPacket$Companion { - public final fun fromPacket (Lio/ktor/utils/io/core/ByteReadPacket;)Ldev/kord/voice/udp/RTPPacket; + public final fun fromPacket (Lkotlinx/io/Source;)Ldev/kord/voice/udp/RTPPacket; } public final class dev/kord/voice/udp/RTPPacketKt { diff --git a/voice/api/voice.klib.api b/voice/api/voice.klib.api index 4291e74d795..de44c2249d4 100644 --- a/voice/api/voice.klib.api +++ b/voice/api/voice.klib.api @@ -91,17 +91,20 @@ abstract interface dev.kord.voice.udp/VoiceUdpSocket { // dev.kord.voice.udp/Voi final fun none(): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/VoiceUdpSocket.Companion.none|none(){}[0] } - // Targets: [apple, linux] - abstract fun all(io.ktor.network.sockets/InetSocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(io.ktor.network.sockets.InetSocketAddress){}[0] - // Targets: [apple, linux] abstract suspend fun send(io.ktor.network.sockets/InetSocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(io.ktor.network.sockets.InetSocketAddress;dev.kord.voice.io.ByteArrayView){}[0] + // Targets: [apple] + abstract fun all(io.ktor.network.sockets/InetSocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [js, mingwX64] - abstract fun all(dev.kord.voice.udp/SocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(dev.kord.voice.udp.SocketAddress){}[0] + abstract fun all(dev.kord.voice.udp/SocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(dev.kord.voice.udp.SocketAddress){}[0] // Targets: [js, mingwX64] abstract suspend fun send(dev.kord.voice.udp/SocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(dev.kord.voice.udp.SocketAddress;dev.kord.voice.io.ByteArrayView){}[0] + + // Targets: [linux] + abstract fun all(io.ktor.network.sockets/InetSocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(io.ktor.network.sockets.InetSocketAddress){}[0] } sealed interface dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/NonceStrategy|null[0] @@ -821,7 +824,7 @@ final class dev.kord.voice.udp/RTPPacket { // dev.kord.voice.udp/RTPPacket|null[ } final object Companion { // dev.kord.voice.udp/RTPPacket.Companion|null[0] - final fun fromPacket(io.ktor.utils.io.core/ByteReadPacket): dev.kord.voice.udp/RTPPacket? // dev.kord.voice.udp/RTPPacket.Companion.fromPacket|fromPacket(io.ktor.utils.io.core.ByteReadPacket){}[0] + final fun fromPacket(kotlinx.io/Source): dev.kord.voice.udp/RTPPacket? // dev.kord.voice.udp/RTPPacket.Companion.fromPacket|fromPacket(kotlinx.io.Source){}[0] } } @@ -1238,7 +1241,7 @@ final suspend inline fun dev.kord.voice/VoiceConnection(dev.kord.gateway/Gateway // Targets: [apple, linux] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(io.ktor.network.sockets/InetSocketAddress, kotlin/Int): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress;kotlin.Int){}[0] -// Targets: [apple, linux] +// Targets: [apple] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(io.ktor.network.sockets/InetSocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress){}[0] // Targets: [js, mingwX64] @@ -1262,4 +1265,7 @@ final class dev.kord.voice.udp/SocketAddress { // dev.kord.voice.udp/SocketAddre final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(dev.kord.voice.udp/SocketAddress, kotlin/Int): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress;kotlin.Int){}[0] // Targets: [js, mingwX64] -final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(dev.kord.voice.udp/SocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress){}[0] +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(dev.kord.voice.udp/SocketAddress): kotlinx.io/Source // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress){}[0] + +// Targets: [linux] +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(io.ktor.network.sockets/InetSocketAddress): kotlinx.io/Source // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress){}[0] diff --git a/voice/src/commonMain/kotlin/udp/RTPPacket.kt b/voice/src/commonMain/kotlin/udp/RTPPacket.kt index 43d734c38f7..a28ae415afe 100644 --- a/voice/src/commonMain/kotlin/udp/RTPPacket.kt +++ b/voice/src/commonMain/kotlin/udp/RTPPacket.kt @@ -5,6 +5,9 @@ import dev.kord.voice.io.MutableByteArrayCursor import dev.kord.voice.io.mutableCursor import dev.kord.voice.io.view import io.ktor.utils.io.core.* +import kotlinx.io.Source +import kotlinx.io.readByteArray +import kotlinx.io.readUInt import kotlin.experimental.and internal const val RTP_HEADER_LENGTH = 12 @@ -38,7 +41,7 @@ public data class RTPPacket( public companion object { internal const val VERSION = 2 - public fun fromPacket(packet: ByteReadPacket): RTPPacket? = with(packet) base@{ + public fun fromPacket(packet: Source): RTPPacket? = with(packet) base@{ if (remaining <= 13) return@base null /* @@ -80,7 +83,7 @@ public data class RTPPacket( if (remaining <= csrcCount * 4 + 1) return@base null val csrcIdentifiers = UIntArray(csrcCount.toInt()) { readUInt() } - val payload = readBytes().view() + val payload = readByteArray().view() val paddingBytes = if (hasPadding) { payload[payload.viewSize - 1] } else 0 diff --git a/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt b/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt index af13af28f32..15103c1f262 100644 --- a/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt +++ b/voice/src/commonMain/kotlin/udp/VoiceUdpSocket.kt @@ -4,6 +4,7 @@ import dev.kord.common.annotation.KordVoice import dev.kord.voice.io.ByteArrayView import io.ktor.utils.io.core.* import kotlinx.coroutines.flow.* +import kotlinx.io.Source @KordVoice public expect class SocketAddress(hostname: String, port: Int) { @@ -21,7 +22,7 @@ public expect val GlobalVoiceUdpSocket: VoiceUdpSocket @KordVoice public interface VoiceUdpSocket { - public fun all(address: SocketAddress): Flow + public fun all(address: SocketAddress): Flow public suspend fun send(address: SocketAddress, packet: ByteArrayView): Unit @@ -29,7 +30,7 @@ public interface VoiceUdpSocket { public companion object { private object None : VoiceUdpSocket { - override fun all(address: SocketAddress): Flow = emptyFlow() + override fun all(address: SocketAddress): Flow = emptyFlow() override suspend fun send(address: SocketAddress, packet: ByteArrayView) {} @@ -40,4 +41,4 @@ public interface VoiceUdpSocket { } } -public suspend fun VoiceUdpSocket.recv(address: SocketAddress): ByteReadPacket = all(address).first() +public suspend fun VoiceUdpSocket.recv(address: SocketAddress): Source = all(address).first() diff --git a/voice/src/commonMain/kotlin/udp/ipDiscovery.kt b/voice/src/commonMain/kotlin/udp/ipDiscovery.kt index 6b791bd5524..21628f77d18 100644 --- a/voice/src/commonMain/kotlin/udp/ipDiscovery.kt +++ b/voice/src/commonMain/kotlin/udp/ipDiscovery.kt @@ -4,6 +4,8 @@ import dev.kord.voice.io.mutableCursor import dev.kord.voice.io.view import io.github.oshai.kotlinlogging.KotlinLogging import io.ktor.utils.io.core.* +import kotlinx.io.readByteArray +import kotlinx.io.readUShort private val ipDiscoveryLogger = KotlinLogging.logger { } @@ -15,7 +17,6 @@ private const val DISCOVERY_MESSAGE_SIZE = DISCOVERY_HEADER_SIZE + DISCOVERY_DAT private const val REQUEST: Short = 0x01 private const val RESPONSE: Short = 0x02 -@OptIn(ExperimentalUnsignedTypes::class) public suspend fun VoiceUdpSocket.discoverIP(address: SocketAddress, ssrc: Int): SocketAddress { ipDiscoveryLogger.trace { "discovering ip" } @@ -31,9 +32,9 @@ public suspend fun VoiceUdpSocket.discoverIP(address: SocketAddress, ssrc: Int): return with(recv(address)) { require(readShort() == RESPONSE) { "did not receive a response." } require(readShort() == MESSAGE_LENGTH) { "expected $MESSAGE_LENGTH bytes of data."} - discardExact(4) // ssrc + skip(4) // ssrc - val ip = String(readBytes(64)).trimEnd(0.toChar()) + val ip = readByteArray(64).decodeToString().trimEnd(0.toChar()) val port = readUShort().toInt() SocketAddress(ip, port) diff --git a/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt b/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt index c411dbc582a..89361b574cf 100644 --- a/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt +++ b/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map +import kotlinx.io.Source import node.dgram.SocketEvent import node.dgram.SocketType import node.dgram.createSocket @@ -33,7 +34,7 @@ public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket } } - override fun all(address: SocketAddress): Flow = incoming + override fun all(address: SocketAddress): Flow = incoming .filter { it.first == address } .map { ByteReadPacket(it.second) } diff --git a/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt b/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt index 8289998c890..027f66ec2f9 100644 --- a/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt +++ b/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt @@ -8,6 +8,7 @@ import io.ktor.network.sockets.Datagram import io.ktor.utils.io.core.* import kotlinx.coroutines.* import kotlinx.coroutines.flow.* +import kotlinx.io.Source import io.ktor.network.sockets.Datagram as KtorDatagram @KordVoice @@ -29,7 +30,7 @@ public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket .launchIn(socketScope) } - override fun all(address: SocketAddress): Flow { + override fun all(address: SocketAddress): Flow { return incoming .filter { it.address == address } .map { it.packet } diff --git a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt index d2454f76b7f..ba0defda4d5 100644 --- a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt +++ b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt @@ -2,12 +2,12 @@ package dev.kord.voice.udp import dev.kord.common.annotation.KordVoice import dev.kord.voice.io.ByteArrayView -import io.ktor.utils.io.core.* import kotlinx.coroutines.flow.Flow +import kotlinx.io.Source @KordVoice public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket { - override fun all(address: SocketAddress): Flow = unsupported() + override fun all(address: SocketAddress): Flow = unsupported() override suspend fun send(address: SocketAddress, packet: ByteArrayView) = unsupported() From 6cf5769b7c1c7b3b2124b99304bafe3319691fc1 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Thu, 12 Sep 2024 15:12:23 +0200 Subject: [PATCH 78/83] More fixes in regards to merge --- buildSrc/src/main/kotlin/Compiler.kt | 6 +++--- buildSrc/src/main/kotlin/Targets.kt | 10 +++++----- .../kotlin/kord-multiplatform-module.gradle.kts | 8 ++++++-- .../src/main/kotlin/kord-publishing.gradle.kts | 14 +++----------- ksp-annotations/build.gradle.kts | 10 ++++++++++ test-kit/build.gradle.kts | 10 ++++++++++ voice/api/voice.klib.api | 14 -------------- 7 files changed, 37 insertions(+), 35 deletions(-) diff --git a/buildSrc/src/main/kotlin/Compiler.kt b/buildSrc/src/main/kotlin/Compiler.kt index 6caa6484fc3..35b50c6d0f6 100644 --- a/buildSrc/src/main/kotlin/Compiler.kt +++ b/buildSrc/src/main/kotlin/Compiler.kt @@ -14,13 +14,13 @@ val kordOptIns = listOf( "dev.kord.common.annotation.KordVoice", ) -internal fun KotlinCommonCompilerOptions.applyKordCommonCompilerOptions() { +fun KotlinCommonCompilerOptions.applyKordCommonCompilerOptions() { allWarningsAsErrors = true progressiveMode = true - freeCompilerArgs.add("-Xexpect-actual-classes") + freeCompilerArgs.addAll("-Xexpect-actual-classes", "-Xexpect-actual-classes") } -internal const val KORD_JVM_TARGET = 8 +const val KORD_JVM_TARGET = 8 internal fun KotlinJvmCompilerOptions.applyKordJvmCompilerOptions() { applyKordCommonCompilerOptions() diff --git a/buildSrc/src/main/kotlin/Targets.kt b/buildSrc/src/main/kotlin/Targets.kt index 8188fd9e02e..f804f3e7acf 100644 --- a/buildSrc/src/main/kotlin/Targets.kt +++ b/buildSrc/src/main/kotlin/Targets.kt @@ -5,7 +5,11 @@ import org.jetbrains.kotlin.konan.target.HostManager @OptIn(ExperimentalKotlinGradlePluginApi::class) fun KotlinMultiplatformExtension.targets() { - jvm() + jvm { + compilerOptions { + applyKordJvmCompilerOptions() + } + } js { nodejs { @@ -38,10 +42,6 @@ fun KotlinMultiplatformExtension.targets() { tvosX64() tvosArm64() tvosSimulatorArm64() - - compilerOptions { - applyKordCompilerOptions() - } } // There are issues with linking the linux variant on windows. diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index b37339635c2..59a69c782dc 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -1,6 +1,7 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest +import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest plugins { org.jetbrains.kotlin.multiplatform @@ -41,10 +42,9 @@ kotlin { targets() explicitApi() - jvmToolchain(Jvm.target) compilerOptions { - applyKordCompilerOptions() optIn.addAll(kordOptIns) + applyKordCommonCompilerOptions() } sourceSets { @@ -74,6 +74,10 @@ tasks { environment("PROJECT_ROOT", rootProject.projectDir.absolutePath) } + withType().configureEach { + options.release = KORD_JVM_TARGET + } + afterEvaluate { val compilationTasks = kotlin.targets.flatMap { listOf("compileKotlin${it.name.replaceFirstChar(Char::titlecase)}", "${it.name}SourcesJar") diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index 20d05a7dc4b..64f4f66714a 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -1,3 +1,4 @@ +import org.jetbrains.kotlin.konan.target.Family import java.lang.System.getenv import java.util.Base64 @@ -17,7 +18,7 @@ mavenPublishing { signAllPublications() if (plugins.hasPlugin("org.jetbrains.kotlin.multiplatform")) { - configure(KotlinMultiplatform(javadocJar = JavadocJar.Dokka("dokkaHtml"))) +// configure(KotlinMultipla(javadocJar = JavadocJar.Dokka("dokkaHtml"))) } pom { @@ -56,16 +57,7 @@ mavenPublishing { } repositories { - maven { - url = uri(if (isRelease) Repo.releasesUrl else Repo.snapshotsUrl) - - credentials { - username = getenv("NEXUS_USER") - password = getenv("NEXUS_PASSWORD") - } - } - - if (!isRelease) { + if (true) { maven { name = "kordSnapshots" url = uri("https://repo.kord.dev/snapshots") diff --git a/ksp-annotations/build.gradle.kts b/ksp-annotations/build.gradle.kts index c2fa45ec56f..524da336279 100644 --- a/ksp-annotations/build.gradle.kts +++ b/ksp-annotations/build.gradle.kts @@ -10,8 +10,18 @@ plugins { `kord-publishing` } +kotlin { + targets() +} + tasks.withType().configureEach { dokkaSourceSets.configureEach { suppress = true } } + +tasks { + withType().configureEach { + options.release = KORD_JVM_TARGET + } +} diff --git a/test-kit/build.gradle.kts b/test-kit/build.gradle.kts index b0deb0f21bd..652f677426b 100644 --- a/test-kit/build.gradle.kts +++ b/test-kit/build.gradle.kts @@ -41,4 +41,14 @@ kotlin { } } } + + compilerOptions { + applyKordCommonCompilerOptions() + } +} + +tasks { + withType().configureEach { + options.release = KORD_JVM_TARGET + } } diff --git a/voice/api/voice.klib.api b/voice/api/voice.klib.api index de44c2249d4..1a2cd4e778b 100644 --- a/voice/api/voice.klib.api +++ b/voice/api/voice.klib.api @@ -1029,8 +1029,6 @@ final value class dev.kord.voice/AudioFrame { // dev.kord.voice/AudioFrame|null[ } sealed class dev.kord.voice.gateway/Close : dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Close|null[0] - constructor () // dev.kord.voice.gateway/Close.|(){}[0] - final class DiscordClose : dev.kord.voice.gateway/Close { // dev.kord.voice.gateway/Close.DiscordClose|null[0] constructor (dev.kord.voice.gateway/VoiceGatewayCloseCode, kotlin/Boolean) // dev.kord.voice.gateway/Close.DiscordClose.|(dev.kord.voice.gateway.VoiceGatewayCloseCode;kotlin.Boolean){}[0] @@ -1057,8 +1055,6 @@ sealed class dev.kord.voice.gateway/Close : dev.kord.voice.gateway/VoiceEvent { } sealed class dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Command|null[0] - constructor () // dev.kord.voice.gateway/Command.|(){}[0] - final object SerializationStrategy : kotlinx.serialization/SerializationStrategy { // dev.kord.voice.gateway/Command.SerializationStrategy|null[0] final val descriptor // dev.kord.voice.gateway/Command.SerializationStrategy.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/Command.SerializationStrategy.descriptor.|(){}[0] @@ -1068,8 +1064,6 @@ sealed class dev.kord.voice.gateway/Command { // dev.kord.voice.gateway/Command| } sealed class dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/VoiceEvent|null[0] - constructor () // dev.kord.voice.gateway/VoiceEvent.|(){}[0] - final object DeserializationStrategy : kotlinx.serialization/DeserializationStrategy { // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy|null[0] final val descriptor // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.descriptor|{}descriptor[0] final fun (): kotlinx.serialization.descriptors/SerialDescriptor // dev.kord.voice.gateway/VoiceEvent.DeserializationStrategy.descriptor.|(){}[0] @@ -1079,8 +1073,6 @@ sealed class dev.kord.voice.gateway/VoiceEvent { // dev.kord.voice.gateway/Voice } sealed class dev.kord.voice.gateway/VoiceGatewayCloseCode { // dev.kord.voice.gateway/VoiceGatewayCloseCode|null[0] - constructor (kotlin/Int) // dev.kord.voice.gateway/VoiceGatewayCloseCode.|(kotlin.Int){}[0] - final val code // dev.kord.voice.gateway/VoiceGatewayCloseCode.code|{}code[0] final fun (): kotlin/Int // dev.kord.voice.gateway/VoiceGatewayCloseCode.code.|(){}[0] @@ -1118,8 +1110,6 @@ sealed class dev.kord.voice.gateway/VoiceGatewayCloseCode { // dev.kord.voice.ga } sealed class dev.kord.voice.udp/PayloadType { // dev.kord.voice.udp/PayloadType|null[0] - constructor (kotlin/Byte) // dev.kord.voice.udp/PayloadType.|(kotlin.Byte){}[0] - final val raw // dev.kord.voice.udp/PayloadType.raw|{}raw[0] final fun (): kotlin/Byte // dev.kord.voice.udp/PayloadType.raw.|(){}[0] @@ -1139,8 +1129,6 @@ sealed class dev.kord.voice.udp/PayloadType { // dev.kord.voice.udp/PayloadType| } sealed class dev.kord.voice/EncryptionMode { // dev.kord.voice/EncryptionMode|null[0] - constructor (kotlin/String) // dev.kord.voice/EncryptionMode.|(kotlin.String){}[0] - final val value // dev.kord.voice/EncryptionMode.value|{}value[0] final fun (): kotlin/String // dev.kord.voice/EncryptionMode.value.|(){}[0] @@ -1166,8 +1154,6 @@ sealed class dev.kord.voice/EncryptionMode { // dev.kord.voice/EncryptionMode|nu } sealed class dev.kord.voice/SpeakingFlag { // dev.kord.voice/SpeakingFlag|null[0] - constructor (kotlin/Int) // dev.kord.voice/SpeakingFlag.|(kotlin.Int){}[0] - final val code // dev.kord.voice/SpeakingFlag.code|{}code[0] final fun (): kotlin/Int // dev.kord.voice/SpeakingFlag.code.|(){}[0] final val shift // dev.kord.voice/SpeakingFlag.shift|{}shift[0] From a08068b5927370bd3e97c460d647d953a951ba64 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Thu, 12 Sep 2024 22:17:14 +0200 Subject: [PATCH 79/83] Remove duplicate -Xexpect-actual-classes --- buildSrc/src/main/kotlin/Compiler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Compiler.kt b/buildSrc/src/main/kotlin/Compiler.kt index 35b50c6d0f6..f767ee0cbca 100644 --- a/buildSrc/src/main/kotlin/Compiler.kt +++ b/buildSrc/src/main/kotlin/Compiler.kt @@ -17,7 +17,7 @@ val kordOptIns = listOf( fun KotlinCommonCompilerOptions.applyKordCommonCompilerOptions() { allWarningsAsErrors = true progressiveMode = true - freeCompilerArgs.addAll("-Xexpect-actual-classes", "-Xexpect-actual-classes") + freeCompilerArgs.add("-Xexpect-actual-classes") } const val KORD_JVM_TARGET = 8 From 10834bfa167b15376bfafb736109e7d019f32490 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Thu, 12 Sep 2024 22:17:45 +0200 Subject: [PATCH 80/83] Imports, formatting --- README.md | 2 +- gradle/libs.versions.toml | 1 + rest/src/commonTest/kotlin/request/MessageRequests.kt | 2 -- .../src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt | 4 ++-- samples/src/jvmMain/kotlin/runMain.jvm.kt | 4 +--- voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt | 1 - voice/src/commonMain/kotlin/udp/ipDiscovery.kt | 3 +-- voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt | 1 - .../dev/kord/voice/encryption/XSalsa20Poly1305Encryption.kt | 1 - .../jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt | 1 + 10 files changed, 7 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 65963393922..f20a05979d1 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ mapping of the Voice API on Kotlin/JVM | [core-voice](core-voice) | [core-voice](https://kordlib.github.io/kord/core-voice) | `kord-core-voice`¹ | ✅ | ✅ | ✅² | ¹ These artifacts only supports Gradle Version 5.3 or higher, for older Gradle versions and Maven please append `-jvm` -² Currently not on Windows(MinGW) targets, see #69 +² Currently not on Windows(MinGW) targets, see #69 ## Installation diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d7b57b40170..79ff5902d77 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -37,6 +37,7 @@ buildconfig = "5.4.0" # https://github.com/gmazzo/gradle-buildconfig-plugin kord-gradle-tools = "1.6.2" # https://github.com/kordlib/gradle-tools/blob/main/build.gradle.kts#L10 maven-publish-plugin = "0.29.0" # https://github.com/vanniktech/gradle-maven-publish-plugin + [libraries] # cache diff --git a/rest/src/commonTest/kotlin/request/MessageRequests.kt b/rest/src/commonTest/kotlin/request/MessageRequests.kt index a49498723ed..bb3827f7470 100644 --- a/rest/src/commonTest/kotlin/request/MessageRequests.kt +++ b/rest/src/commonTest/kotlin/request/MessageRequests.kt @@ -9,11 +9,9 @@ import dev.kord.common.entity.optional.Optional import dev.kord.rest.json.readFile import dev.kord.rest.service.ChannelService import dev.kord.test.IgnoreOnSimulatorPlatforms -import dev.kord.test.Platform import io.ktor.client.* import io.ktor.client.engine.mock.* import io.ktor.client.request.forms.* -import io.ktor.utils.io.* import kotlinx.coroutines.test.runTest import kotlinx.datetime.Clock import kotlinx.serialization.encodeToString diff --git a/samples/src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt b/samples/src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt index 02e1fb0a4c3..60d729f9011 100644 --- a/samples/src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt +++ b/samples/src/commonMain/kotlin/dev/kord/gateway/GatewayExample.kt @@ -19,7 +19,7 @@ suspend fun main(args: Array) { gateway.events.filterIsInstance().onEach { val words = it.message.content.split(' ') when (words.firstOrNull()) { - "!close" -> gateway.stop() + "!close" -> gateway.stop() "!detach" -> gateway.detach() "!status" -> when (words.getOrNull(1)) { "playing" -> gateway.editPresence { @@ -29,7 +29,7 @@ suspend fun main(args: Array) { } } - "!ping" -> gateway.editPresence { + "!ping" -> gateway.editPresence { status = PresenceStatus.Online afk = false listening("a ${gateway.ping.value?.inWholeMilliseconds} ms ping") diff --git a/samples/src/jvmMain/kotlin/runMain.jvm.kt b/samples/src/jvmMain/kotlin/runMain.jvm.kt index 1166532b1e4..48392f5b700 100644 --- a/samples/src/jvmMain/kotlin/runMain.jvm.kt +++ b/samples/src/jvmMain/kotlin/runMain.jvm.kt @@ -1,8 +1,6 @@ import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking actual fun runMain(block: suspend CoroutineScope.() -> Unit) { runBlocking { block() } -} \ No newline at end of file +} diff --git a/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt b/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt index c1d835eac5a..f0316424563 100644 --- a/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt +++ b/voice/src/commonMain/kotlin/udp/DefaultAudioFrameSender.kt @@ -6,7 +6,6 @@ import dev.kord.voice.AudioProvider import dev.kord.voice.FrameInterceptor import dev.kord.voice.encryption.strategies.NonceStrategy import io.github.oshai.kotlinlogging.KotlinLogging -import io.ktor.utils.io.core.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.* diff --git a/voice/src/commonMain/kotlin/udp/ipDiscovery.kt b/voice/src/commonMain/kotlin/udp/ipDiscovery.kt index 21628f77d18..abfdf16536a 100644 --- a/voice/src/commonMain/kotlin/udp/ipDiscovery.kt +++ b/voice/src/commonMain/kotlin/udp/ipDiscovery.kt @@ -3,7 +3,6 @@ package dev.kord.voice.udp import dev.kord.voice.io.mutableCursor import dev.kord.voice.io.view import io.github.oshai.kotlinlogging.KotlinLogging -import io.ktor.utils.io.core.* import kotlinx.io.readByteArray import kotlinx.io.readUShort @@ -39,4 +38,4 @@ public suspend fun VoiceUdpSocket.discoverIP(address: SocketAddress, ssrc: Int): SocketAddress(ip, port) } -} \ No newline at end of file +} diff --git a/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt b/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt index 89361b574cf..08d4e7b382b 100644 --- a/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt +++ b/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt @@ -1,6 +1,5 @@ package dev.kord.voice.udp -import dev.kord.common.annotation.KordVoice import dev.kord.voice.io.ByteArrayView import io.ktor.utils.io.core.* import js.typedarrays.toUint8Array diff --git a/voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Encryption.kt b/voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Encryption.kt index 47363cfbfc6..808e9d502ae 100644 --- a/voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Encryption.kt +++ b/voice/src/jvmMain/kotlin/dev/kord/voice/encryption/XSalsa20Poly1305Encryption.kt @@ -5,7 +5,6 @@ import com.iwebpp.crypto.TweetNaclFast.SecretBox.boxzerobytesLength import com.iwebpp.crypto.TweetNaclFast.SecretBox.zerobytesLength import dev.kord.voice.io.MutableByteArrayCursor - // https://datatracker.ietf.org/doc/html/rfc6716#section-3.2.1 private const val OPUS_MAX_LENGTH = 1276 diff --git a/voice/src/jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt b/voice/src/jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt index 2e91381139c..28b0ab5f817 100644 --- a/voice/src/jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt +++ b/voice/src/jvmMain/kotlin/dev/kord/voice/streams/DefaultStreams.kt @@ -1,4 +1,5 @@ @file:JvmName("DefaultStreamsJvm") + package dev.kord.voice.streams import com.iwebpp.crypto.TweetNaclFast From 3dd43e1cf493cf7bf7f092bc18d914d07f3a8f54 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Thu, 12 Sep 2024 22:23:01 +0200 Subject: [PATCH 81/83] Remove unused version --- gradle/libs.versions.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 79ff5902d77..2b7df5b9b9f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,6 @@ kord-cache = "0.5.4" # https://github.com/kordlib/cache # implementation dependencies kotlinx-io = "0.5.1" # https://github.com/Kotlin/kotlinx-io kotlin-logging = "7.0.0" # https://github.com/oshai/kotlin-logging -kotlin-logging-old = "3.0.5" # TODO remove after dependency is removed in rest, gateway, voice and core slf4j = "2.0.16" # https://www.slf4j.org kotlin-node = "20.14.10-pre.800" # https://github.com/JetBrains/kotlin-wrappers bignum = "0.3.10" # https://github.com/ionspin/kotlin-multiplatform-bignum From 86ddabbd55472870141141f32505fc30f4ab997b Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Thu, 12 Sep 2024 22:32:44 +0200 Subject: [PATCH 82/83] Remove unused -Xcontext-receivers in buildSrc --- buildSrc/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 41189bbfb2a..d6abfed304d 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -12,7 +12,6 @@ repositories { kotlin { compilerOptions { allWarningsAsErrors = true - freeCompilerArgs.add("-Xcontext-receivers") } } From 1362153514cf8df98169c4139e4498639d47aa10 Mon Sep 17 00:00:00 2001 From: Michael Rittmeister Date: Mon, 21 Oct 2024 14:23:28 +0200 Subject: [PATCH 83/83] Update to current state of main --- buildSrc/src/main/kotlin/Documentation.kt | 7 ++- .../kord-multiplatform-module.gradle.kts | 16 ++--- .../main/kotlin/kord-publishing.gradle.kts | 1 + .../commonTest/kotlin/json/InteractionTest.kt | 1 + gradle.properties | 2 +- gradle/libs.versions.toml | 6 +- .../kotlin/request/MessageRequests.kt | 2 + voice/api/voice.klib.api | 60 +++++++++---------- voice/build.gradle.kts | 2 +- .../kotlin/VoiceConnectionBuilder.kt | 10 ---- voice/src/commonMain/kotlin/udp/RTPPacket.kt | 4 ++ .../kotlin/VoiceConnectionBuilder.js.kt | 3 - .../kotlin/{udp => }/VoiceUdpSocket.js.kt | 0 .../kotlin/VoiceConnectionBuilder.ktor.kt | 3 - .../kotlin/{udp => }/VoiceUdpSocket.ktor.kt | 11 ++-- .../kotlin/VoiceConnectionBuilder.mingw.kt | 4 -- .../kotlin/udp/VoiceUdpSocket.mingw.kt | 18 ------ 17 files changed, 59 insertions(+), 91 deletions(-) delete mode 100644 voice/src/jsMain/kotlin/VoiceConnectionBuilder.js.kt rename voice/src/jsMain/kotlin/{udp => }/VoiceUdpSocket.js.kt (100%) delete mode 100644 voice/src/ktorMain/kotlin/VoiceConnectionBuilder.ktor.kt rename voice/src/ktorMain/kotlin/{udp => }/VoiceUdpSocket.ktor.kt (81%) delete mode 100644 voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt delete mode 100644 voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt diff --git a/buildSrc/src/main/kotlin/Documentation.kt b/buildSrc/src/main/kotlin/Documentation.kt index ae88b459d18..b0adaa00097 100644 --- a/buildSrc/src/main/kotlin/Documentation.kt +++ b/buildSrc/src/main/kotlin/Documentation.kt @@ -1,6 +1,9 @@ +import dev.kord.gradle.tools.util.commitHash +import org.gradle.api.Project import org.gradle.kotlin.dsl.assign -import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask import java.net.URI +import org.jetbrains.dokka.gradle.DokkaExtension +import org.jetbrains.dokka.gradle.workers.ProcessIsolation internal fun DokkaExtension.applyKordDokkaOptions(project: Project) { @@ -25,7 +28,7 @@ internal fun DokkaExtension.applyKordDokkaOptions(project: Project) { remoteLineSuffix = "#L" } - externalDocumentationLinks { + externalDocumentationLinks.apply { register("kotlinx.coroutines") { url("https://kotlinlang.org/api/kotlinx.coroutines/") } diff --git a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts index 48fe6cb8c3a..a3414422aa8 100644 --- a/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-multiplatform-module.gradle.kts @@ -1,6 +1,7 @@ import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest +import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest plugins { org.jetbrains.kotlin.multiplatform @@ -81,14 +82,14 @@ tasks { options.release = KORD_JVM_TARGET } + val compilationTasks = kotlin.targets.flatMap { + listOf("compileKotlin${it.name.replaceFirstChar(Char::titlecase)}", "${it.name}SourcesJar") + } + for (task in listOf( - "compileKotlinJvm", - "compileKotlinJs", - "jvmSourcesJar", - "jsSourcesJar", "dokkaGenerateModuleHtml", "dokkaGeneratePublicationHtml", - )) { + ) + compilationTasks) { named(task) { dependsOn("kspCommonMainKotlinMetadata") } @@ -100,10 +101,5 @@ tasks { } } - withType().configureEach { - applyKordDokkaOptions() - dependsOn("kspCommonMainKotlinMetadata") - } - disableLinuxLinkTestTasksOnWindows() } diff --git a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts index 9cb99b44213..7b10ed4302e 100644 --- a/buildSrc/src/main/kotlin/kord-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/kord-publishing.gradle.kts @@ -1,3 +1,4 @@ +import org.jetbrains.kotlin.konan.target.Family import java.lang.System.getenv import java.util.Base64 diff --git a/common/src/commonTest/kotlin/json/InteractionTest.kt b/common/src/commonTest/kotlin/json/InteractionTest.kt index d9245eb72ac..02b10983bb0 100644 --- a/common/src/commonTest/kotlin/json/InteractionTest.kt +++ b/common/src/commonTest/kotlin/json/InteractionTest.kt @@ -4,6 +4,7 @@ import dev.kord.common.entity.* import dev.kord.common.entity.Permission.* import dev.kord.common.entity.optional.orEmpty import dev.kord.common.readFile +import dev.kord.test.IgnoreOnSimulatorPlatforms import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import kotlin.js.JsName diff --git a/gradle.properties b/gradle.properties index e470cf89158..b278d7bba58 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,6 +8,7 @@ kotlin.code.style=official # the Kotlin daemon runs out of memory with the default maximum heap size kotlin.daemon.jvmargs=-Xmx2g +org.gradle.jvmargs=-Xmx1g # https://kotlinlang.org/docs/dokka-migration.html#set-the-opt-in-flag org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled @@ -23,5 +24,4 @@ kotlinx.atomicfu.enableJsIrTransformation=true kotlinx.atomicfu.enableNativeIrTransformation=true # We are aware of these issues and their symptoms don't affect us -kotlin.native.ignoreIncorrectDependencies=true kotlin.native.ignoreDisabledTargets=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b2255c87c6c..1a2804826b8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kotlinx-datetime = "0.6.1" # https://github.com/Kotlin/kotlinx-datetime kord-cache = "0.5.4" # https://github.com/kordlib/cache # implementation dependencies -kotlinx-io = "0.5.1" # https://github.com/Kotlin/kotlinx-io +kotlinx-io = "0.5.4" # https://github.com/Kotlin/kotlinx-io kotlin-logging = "7.0.0" # https://github.com/oshai/kotlin-logging slf4j = "2.0.16" # https://www.slf4j.org kotlin-node = "22.5.4-pre.818" # https://github.com/JetBrains/kotlin-wrappers @@ -33,8 +33,8 @@ dokka = "2.0.0-Beta" # https://github.com/Kotlin/dokka kotlinx-atomicfu = "0.25.0" # https://github.com/Kotlin/kotlinx-atomicfu binary-compatibility-validator = "0.16.3" # https://github.com/Kotlin/binary-compatibility-validator buildconfig = "5.5.0" # https://github.com/gmazzo/gradle-buildconfig-plugin -kord-gradle-tools = "1.6.2" # https://github.com/kordlib/gradle-tools/blob/main/build.gradle.kts#L10 -maven-publish-plugin = "0.29.0" # https://github.com/vanniktech/gradle-maven-publish-plugin +kord-gradle-tools = "1.6.3" # https://github.com/kordlib/gradle-tools/blob/main/build.gradle.kts#L10 +maven-publish-plugin = "0.30.0" # https://github.com/vanniktech/gradle-maven-publish-plugin [libraries] diff --git a/rest/src/commonTest/kotlin/request/MessageRequests.kt b/rest/src/commonTest/kotlin/request/MessageRequests.kt index edb78b26c18..cea4d72b5d0 100644 --- a/rest/src/commonTest/kotlin/request/MessageRequests.kt +++ b/rest/src/commonTest/kotlin/request/MessageRequests.kt @@ -8,10 +8,12 @@ import dev.kord.common.entity.Snowflake import dev.kord.common.entity.optional.Optional import dev.kord.rest.json.readFile import dev.kord.rest.service.ChannelService +import dev.kord.test.IgnoreOnSimulatorPlatforms import dev.kord.test.Platform import io.ktor.client.* import io.ktor.client.engine.mock.* import io.ktor.client.request.forms.* +import io.ktor.utils.io.counted import kotlinx.coroutines.test.runTest import kotlinx.datetime.Clock import kotlinx.serialization.encodeToString diff --git a/voice/api/voice.klib.api b/voice/api/voice.klib.api index 1a2cd4e778b..f6b8cca3386 100644 --- a/voice/api/voice.klib.api +++ b/voice/api/voice.klib.api @@ -1,7 +1,7 @@ // Klib ABI Dump // Targets: [iosArm64, iosSimulatorArm64, iosX64, js, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] +// Alias: native => [iosArm64, iosSimulatorArm64, iosX64, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] // Alias: apple => [iosArm64, iosSimulatorArm64, iosX64, macosArm64, macosX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm64, watchosSimulatorArm64] -// Alias: linux => [linuxArm64, linuxX64] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true @@ -73,10 +73,10 @@ abstract interface dev.kord.voice.streams/Streams { // dev.kord.voice.streams/St abstract val ssrcToUser // dev.kord.voice.streams/Streams.ssrcToUser|{}ssrcToUser[0] abstract fun (): kotlin.collections/Map // dev.kord.voice.streams/Streams.ssrcToUser.|(){}[0] - // Targets: [apple, linux] + // Targets: [native] abstract suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/Streams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] - // Targets: [js, mingwX64] + // Targets: [js] abstract suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/Streams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } @@ -91,20 +91,20 @@ abstract interface dev.kord.voice.udp/VoiceUdpSocket { // dev.kord.voice.udp/Voi final fun none(): dev.kord.voice.udp/VoiceUdpSocket // dev.kord.voice.udp/VoiceUdpSocket.Companion.none|none(){}[0] } - // Targets: [apple, linux] + // Targets: [native] + abstract fun all(io.ktor.network.sockets/InetSocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(io.ktor.network.sockets.InetSocketAddress){}[0] + + // Targets: [native] abstract suspend fun send(io.ktor.network.sockets/InetSocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(io.ktor.network.sockets.InetSocketAddress;dev.kord.voice.io.ByteArrayView){}[0] // Targets: [apple] abstract fun all(io.ktor.network.sockets/InetSocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(io.ktor.network.sockets.InetSocketAddress){}[0] - // Targets: [js, mingwX64] + // Targets: [js] abstract fun all(dev.kord.voice.udp/SocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(dev.kord.voice.udp.SocketAddress){}[0] - // Targets: [js, mingwX64] + // Targets: [js] abstract suspend fun send(dev.kord.voice.udp/SocketAddress, dev.kord.voice.io/ByteArrayView) // dev.kord.voice.udp/VoiceUdpSocket.send|send(dev.kord.voice.udp.SocketAddress;dev.kord.voice.io.ByteArrayView){}[0] - - // Targets: [linux] - abstract fun all(io.ktor.network.sockets/InetSocketAddress): kotlinx.coroutines.flow/Flow // dev.kord.voice.udp/VoiceUdpSocket.all|all(io.ktor.network.sockets.InetSocketAddress){}[0] } sealed interface dev.kord.voice.encryption.strategies/NonceStrategy { // dev.kord.voice.encryption.strategies/NonceStrategy|null[0] @@ -661,10 +661,10 @@ final class dev.kord.voice.streams/DefaultStreams : dev.kord.voice.streams/Strea final val ssrcToUser // dev.kord.voice.streams/DefaultStreams.ssrcToUser|{}ssrcToUser[0] final fun (): kotlin.collections/Map // dev.kord.voice.streams/DefaultStreams.ssrcToUser.|(){}[0] - // Targets: [apple, linux] + // Targets: [native] final suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/DefaultStreams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] - // Targets: [js, mingwX64] + // Targets: [js] final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/DefaultStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } @@ -674,10 +674,10 @@ final class dev.kord.voice.udp/AudioFrameSenderConfiguration { // dev.kord.voice final val key // dev.kord.voice.udp/AudioFrameSenderConfiguration.key|{}key[0] final fun (): kotlin/ByteArray // dev.kord.voice.udp/AudioFrameSenderConfiguration.key.|(){}[0] final val server // dev.kord.voice.udp/AudioFrameSenderConfiguration.server|{}server[0] - // Targets: [apple, linux] + // Targets: [native] final fun (): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.server.|(){}[0] - // Targets: [js, mingwX64] + // Targets: [js] final fun (): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.server.|(){}[0] final val ssrc // dev.kord.voice.udp/AudioFrameSenderConfiguration.ssrc|{}ssrc[0] final fun (): kotlin/UInt // dev.kord.voice.udp/AudioFrameSenderConfiguration.ssrc.|(){}[0] @@ -689,26 +689,26 @@ final class dev.kord.voice.udp/AudioFrameSenderConfiguration { // dev.kord.voice final fun hashCode(): kotlin/Int // dev.kord.voice.udp/AudioFrameSenderConfiguration.hashCode|hashCode(){}[0] final fun toString(): kotlin/String // dev.kord.voice.udp/AudioFrameSenderConfiguration.toString|toString(){}[0] - // Targets: [apple, linux] + // Targets: [native] constructor (io.ktor.network.sockets/InetSocketAddress, kotlin/UInt, kotlin/ByteArray, dev.kord.voice/FrameInterceptorConfiguration) // dev.kord.voice.udp/AudioFrameSenderConfiguration.|(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] - // Targets: [apple, linux] + // Targets: [native] final fun component1(): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.component1|component1(){}[0] + // Targets: [native] + final fun copy(io.ktor.network.sockets/InetSocketAddress = ..., kotlin/UInt = ..., kotlin/ByteArray = ..., dev.kord.voice/FrameInterceptorConfiguration = ...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] + // Targets: [apple] final fun copy(io.ktor.network.sockets/InetSocketAddress =..., kotlin/UInt =..., kotlin/ByteArray =..., dev.kord.voice/FrameInterceptorConfiguration =...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] - // Targets: [js, mingwX64] + // Targets: [js] constructor (dev.kord.voice.udp/SocketAddress, kotlin/UInt, kotlin/ByteArray, dev.kord.voice/FrameInterceptorConfiguration) // dev.kord.voice.udp/AudioFrameSenderConfiguration.|(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] - // Targets: [js, mingwX64] + // Targets: [js] final fun component1(): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/AudioFrameSenderConfiguration.component1|component1(){}[0] - // Targets: [js, mingwX64] + // Targets: [js] final fun copy(dev.kord.voice.udp/SocketAddress = ..., kotlin/UInt = ..., kotlin/ByteArray = ..., dev.kord.voice/FrameInterceptorConfiguration = ...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(dev.kord.voice.udp.SocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] - - // Targets: [linux] - final fun copy(io.ktor.network.sockets/InetSocketAddress = ..., kotlin/UInt = ..., kotlin/ByteArray = ..., dev.kord.voice/FrameInterceptorConfiguration = ...): dev.kord.voice.udp/AudioFrameSenderConfiguration // dev.kord.voice.udp/AudioFrameSenderConfiguration.copy|copy(io.ktor.network.sockets.InetSocketAddress;kotlin.UInt;kotlin.ByteArray;dev.kord.voice.FrameInterceptorConfiguration){}[0] } final class dev.kord.voice.udp/DefaultAudioFrameSender : dev.kord.voice.udp/AudioFrameSender { // dev.kord.voice.udp/DefaultAudioFrameSender|null[0] @@ -1195,10 +1195,10 @@ final object dev.kord.voice.streams/NOPStreams : dev.kord.voice.streams/Streams final val ssrcToUser // dev.kord.voice.streams/NOPStreams.ssrcToUser|{}ssrcToUser[0] final fun (): kotlin.collections/Map // dev.kord.voice.streams/NOPStreams.ssrcToUser.|(){}[0] - // Targets: [apple, linux] + // Targets: [native] final suspend fun listen(kotlin/ByteArray, io.ktor.network.sockets/InetSocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;io.ktor.network.sockets.InetSocketAddress){}[0] - // Targets: [js, mingwX64] + // Targets: [js] final suspend fun listen(kotlin/ByteArray, dev.kord.voice.udp/SocketAddress) // dev.kord.voice.streams/NOPStreams.listen|listen(kotlin.ByteArray;dev.kord.voice.udp.SocketAddress){}[0] } @@ -1224,13 +1224,16 @@ final inline fun <#A: reified dev.kord.voice.gateway/VoiceEvent> (dev.kord.voice final inline fun dev.kord.voice/SpeakingFlags(kotlin/Function1 = ...): dev.kord.voice/SpeakingFlags // dev.kord.voice/SpeakingFlags|SpeakingFlags(kotlin.Function1){}[0] final suspend inline fun dev.kord.voice/VoiceConnection(dev.kord.gateway/Gateway, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, dev.kord.common.entity/Snowflake, kotlin/Function1 = ...): dev.kord.voice/VoiceConnection // dev.kord.voice/VoiceConnection|VoiceConnection(dev.kord.gateway.Gateway;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;dev.kord.common.entity.Snowflake;kotlin.Function1){}[0] -// Targets: [apple, linux] +// Targets: [native] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(io.ktor.network.sockets/InetSocketAddress, kotlin/Int): io.ktor.network.sockets/InetSocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress;kotlin.Int){}[0] +// Targets: [native] +final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(io.ktor.network.sockets/InetSocketAddress): kotlinx.io/Source // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress){}[0] + // Targets: [apple] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(io.ktor.network.sockets/InetSocketAddress): io.ktor.utils.io.core/ByteReadPacket // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress){}[0] -// Targets: [js, mingwX64] +// Targets: [js] final class dev.kord.voice.udp/SocketAddress { // dev.kord.voice.udp/SocketAddress|null[0] constructor (kotlin/String, kotlin/Int) // dev.kord.voice.udp/SocketAddress.|(kotlin.String;kotlin.Int){}[0] @@ -1247,11 +1250,8 @@ final class dev.kord.voice.udp/SocketAddress { // dev.kord.voice.udp/SocketAddre final fun toString(): kotlin/String // dev.kord.voice.udp/SocketAddress.toString|toString(){}[0] } -// Targets: [js, mingwX64] +// Targets: [js] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/discoverIP(dev.kord.voice.udp/SocketAddress, kotlin/Int): dev.kord.voice.udp/SocketAddress // dev.kord.voice.udp/discoverIP|discoverIP@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress;kotlin.Int){}[0] -// Targets: [js, mingwX64] +// Targets: [js] final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(dev.kord.voice.udp/SocketAddress): kotlinx.io/Source // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(dev.kord.voice.udp.SocketAddress){}[0] - -// Targets: [linux] -final suspend fun (dev.kord.voice.udp/VoiceUdpSocket).dev.kord.voice.udp/recv(io.ktor.network.sockets/InetSocketAddress): kotlinx.io/Source // dev.kord.voice.udp/recv|recv@dev.kord.voice.udp.VoiceUdpSocket(io.ktor.network.sockets.InetSocketAddress){}[0] diff --git a/voice/build.gradle.kts b/voice/build.gradle.kts index 6cdda52ccf9..153c6d93f68 100644 --- a/voice/build.gradle.kts +++ b/voice/build.gradle.kts @@ -13,11 +13,11 @@ kotlin { withJvm() withApple() withLinux() + withMingw() } group("nonKtor") { withJs() - withMingw() } } } diff --git a/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt b/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt index c0fd221612c..f9aa30990d7 100644 --- a/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt +++ b/voice/src/commonMain/kotlin/VoiceConnectionBuilder.kt @@ -25,8 +25,6 @@ import kotlinx.coroutines.flow.first import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds -internal expect val isSupported: Boolean - @KordVoice public class VoiceConnectionBuilder( public var gateway: Gateway, @@ -34,14 +32,6 @@ public class VoiceConnectionBuilder( public var channelId: Snowflake, public var guildId: Snowflake ) { - init { - if(!isSupported) { - throw UnsupportedOperationException(""" - Voice is currently not supported on Windows, if you're developing on Windows we recommend using - WSL: https://aka.ms/wsl - """.trimIndent()) - } - } /** * The amount in milliseconds to wait for the events required to create a [VoiceConnection]. Default is 5000, or 5 seconds. */ diff --git a/voice/src/commonMain/kotlin/udp/RTPPacket.kt b/voice/src/commonMain/kotlin/udp/RTPPacket.kt index 66dc53fc261..052dc0f640a 100644 --- a/voice/src/commonMain/kotlin/udp/RTPPacket.kt +++ b/voice/src/commonMain/kotlin/udp/RTPPacket.kt @@ -5,6 +5,10 @@ import dev.kord.voice.io.MutableByteArrayCursor import dev.kord.voice.io.mutableCursor import dev.kord.voice.io.view import io.ktor.utils.io.core.* +import kotlinx.io.Source +import kotlinx.io.readByteArray +import kotlinx.io.readUInt +import kotlinx.io.readUShort import kotlin.experimental.and internal const val RTP_HEADER_LENGTH = 12 diff --git a/voice/src/jsMain/kotlin/VoiceConnectionBuilder.js.kt b/voice/src/jsMain/kotlin/VoiceConnectionBuilder.js.kt deleted file mode 100644 index df8eacf9fe9..00000000000 --- a/voice/src/jsMain/kotlin/VoiceConnectionBuilder.js.kt +++ /dev/null @@ -1,3 +0,0 @@ -package dev.kord.voice - -internal actual val isSupported: Boolean = true diff --git a/voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt b/voice/src/jsMain/kotlin/VoiceUdpSocket.js.kt similarity index 100% rename from voice/src/jsMain/kotlin/udp/VoiceUdpSocket.js.kt rename to voice/src/jsMain/kotlin/VoiceUdpSocket.js.kt diff --git a/voice/src/ktorMain/kotlin/VoiceConnectionBuilder.ktor.kt b/voice/src/ktorMain/kotlin/VoiceConnectionBuilder.ktor.kt deleted file mode 100644 index df8eacf9fe9..00000000000 --- a/voice/src/ktorMain/kotlin/VoiceConnectionBuilder.ktor.kt +++ /dev/null @@ -1,3 +0,0 @@ -package dev.kord.voice - -internal actual val isSupported: Boolean = true diff --git a/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt b/voice/src/ktorMain/kotlin/VoiceUdpSocket.ktor.kt similarity index 81% rename from voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt rename to voice/src/ktorMain/kotlin/VoiceUdpSocket.ktor.kt index 027f66ec2f9..bb233d0f99f 100644 --- a/voice/src/ktorMain/kotlin/udp/VoiceUdpSocket.ktor.kt +++ b/voice/src/ktorMain/kotlin/VoiceUdpSocket.ktor.kt @@ -19,15 +19,14 @@ public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket private val socketScope = CoroutineScope(Dispatchers.Default + SupervisorJob() + CoroutineName("kord-voice-global-socket")) - private val socket = aSocket(SelectorManager(socketScope.coroutineContext)).udp().bind() + private val socket = socketScope.async { + aSocket(SelectorManager(socketScope.coroutineContext)).udp().bind() + } private val incoming: MutableSharedFlow = MutableSharedFlow() init { - socket.incoming - .consumeAsFlow() - .onEach { incoming.emit(it) } - .launchIn(socketScope) + socketScope.launch { incoming.emitAll(socket.await().incoming) } } override fun all(address: SocketAddress): Flow { @@ -38,7 +37,7 @@ public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket override suspend fun send(address: SocketAddress, packet: ByteArrayView) { val brp = ByteReadPacket(packet.data, packet.dataStart, packet.viewSize) - socket.send(KtorDatagram(brp, address)) + socket.await().send(KtorDatagram(brp, address)) } override suspend fun stop() { diff --git a/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt b/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt deleted file mode 100644 index 6486443b453..00000000000 --- a/voice/src/mingwMain/kotlin/VoiceConnectionBuilder.mingw.kt +++ /dev/null @@ -1,4 +0,0 @@ -package dev.kord.voice - -// https://youtrack.jetbrains.com/issue/KTOR-4080 -internal actual val isSupported: Boolean = false diff --git a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt b/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt deleted file mode 100644 index ba0defda4d5..00000000000 --- a/voice/src/mingwMain/kotlin/udp/VoiceUdpSocket.mingw.kt +++ /dev/null @@ -1,18 +0,0 @@ -package dev.kord.voice.udp - -import dev.kord.common.annotation.KordVoice -import dev.kord.voice.io.ByteArrayView -import kotlinx.coroutines.flow.Flow -import kotlinx.io.Source - -@KordVoice -public actual val GlobalVoiceUdpSocket: VoiceUdpSocket = object : VoiceUdpSocket { - override fun all(address: SocketAddress): Flow = unsupported() - - override suspend fun send(address: SocketAddress, packet: ByteArrayView) = unsupported() - - override suspend fun stop() = unsupported() -} - -// https://youtrack.jetbrains.com/issue/KTOR-4080 -private fun unsupported(): Nothing = TODO("Voice is not supported on windows")