Skip to content

Commit

Permalink
Support Kotlin/JS (#775)
Browse files Browse the repository at this point in the history
This commit attempts to provide Kotlin/JS support for Kord (see #69)

Breaking Changes:

 * The following member functions were replaced by extension functions.
   Importing the extension functions should fix this breaking change.
   * dev.kord.common.Locale.asJavaLocale ->
     import dev.kord.common.asJavaLocale
   * dev.kord.core.cache.KordCacheBuilder.lruCache ->
     import dev.kord.core.cache.lruCache
   * dev.kord.rest.builder.message.create.MessageCreateBuilder.addFile
     -> import dev.kord.rest.builder.message.create.addFile
   * dev.kord.rest.builder.message.modify.MessageModifyBuilder.addFile
     -> import dev.kord.rest.builder.message.modify.addFile
   * dev.kord.rest.request.RequestBuilder.file ->
     import dev.kord.rest.request.file

 * The type of the following declarations was changed from
   java.util.Locale to dev.kord.common.Locale:
   * dev.kord.core.entity.Guild.preferredLocale
   * dev.kord.rest.builder.guild.GuildModifyBuilder.preferredLocale

 * All annotations in dev.kord.common.annotation and the
   dev.kord.gateway.PrivilegedIntent annotation now have BINARY instead
   of RUNTIME retention. This means they are no longer visible for
   reflection.

 * All maven consumers must append '-jvm' to their artifact IDs for
   kord-common, kord-rest, kord-gateway and kord-core.

 * The core-voice capability has been removed, please use the
   kord-core-voice artifact instead.

---------

Co-authored-by: Lukellmann <[email protected]>
  • Loading branch information
DRSchlaubi and lukellmann authored Apr 5, 2023
1 parent d76ce05 commit 64f6636
Show file tree
Hide file tree
Showing 821 changed files with 2,962 additions and 1,739 deletions.
151 changes: 29 additions & 122 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ you to try out our library, we don't recommend you use this in production just y

If you have any feedback, we'd love to hear it, hit us up on discord or write up an issue if you have any suggestions!

## What is Kord
## What is Kord?

Kord is a [coroutine-based](https://kotlinlang.org/docs/reference/coroutines-overview.html), modularized implementation
of the Discord API, written 100% in [Kotlin](https://kotlinlang.org/).
Expand All @@ -26,28 +26,42 @@ unconventional things, and we want to allow you to do those in a safe and suppor

## Status of Kord

* [X] [Discord Gateway](https://github.com/kordlib/kord/tree/master/gateway)
* [x] [Discord Rest API](https://github.com/kordlib/kord/tree/master/rest)
* [X] [High level abstraction + caching](https://github.com/kordlib/kord/tree/master/core)
* [X] [Discord Voice](https://github.com/kordlib/kord/tree/master/voice)
* [X] [Discord Gateway](gateway)
* [x] [Discord Rest API](rest)
* [X] [High level abstraction + caching](core)
* [X] [Discord Voice](voice)
* [ ] Support for multiple processes [#7](https://github.com/kordlib/kord/issues/7)

Right now Kord *should* provide a full mapping of the non-voice API. We're currently working on a testing library for
easy bot testing against a semi mocked client as well as our own command system to facilitate more complex bot
development.
Right now, Kord *should* provide a full mapping of the non-voice API on Kotlin/JVM and Kotlin/JS and an experimental
mapping of the Voice API on Kotlin/JVM

## Documentation

* [Dokka docs](https://kordlib.github.io/kord/)
* [Wiki](https://github.com/kordlib/kord/wiki)

## 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` ||||

¹ 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

## Installation

Replace `{version}` with the latest version number on maven central.

For Snapshots replace `{version}` with `{branch}-SNAPSHOT`
For Snapshots replace `{version}` with `{branch}-SNAPSHOT`

e.g: `0.7.x-SNAPSHOT`
e.g: `0.9.x-SNAPSHOT` for the branch `0.9.x` or `feature-mpp-SNAPSHOT` for the branch `feature/mpp`

[![Download](https://img.shields.io/maven-central/v/dev.kord/kord-core.svg?label=Maven%20Central&style=for-the-badge)](https://search.maven.org/search?q=g:%22dev.kord%22%20AND%20a:%22kord-core%22)

Expand Down Expand Up @@ -111,129 +125,22 @@ dependencies {

<dependency>
<groupId>dev.kord</groupId>
<artifactId>kord-core</artifactId>
<artifactId>kord-core-jvm</artifactId>
<version>{version}</version>
</dependency>
```

## Modules

### Core

A higher level API, combining `rest` and `gateway`, with additional (optional) caching. Unless you're writing your own
abstractions, we'd recommend using this.

```kotlin
suspend fun main() {
val kord = Kord("your bot token")
val pingPong = ReactionEmoji.Unicode("\uD83C\uDFD3")

kord.on<MessageCreateEvent> {
if (message.content != "!ping") return@on

val response = message.channel.createMessage("Pong!")
response.addReaction(pingPong)

delay(5000)
message.delete()
response.delete()
}

kord.login {
@OptIn(PrivilegedIntent::class)
intents += Intent.MessageContent
}
}
```

### Rest

A low level mapping of Discord's REST API. Requests follow
Discord's [rate limits](https://discord.com/developers/docs/topics/rate-limits).

```kotlin
suspend fun main() {
val rest = RestClient("your bot token")
val channelId = Snowflake(605212557522763787)

rest.channel.createMessage(channelId) {
content = "Hello Kord!"

embed {
color = Color(red = 0, green = 0, blue = 255)
description = "Hello embed!"
}
}
}
```

### Gateway

A low level mapping of [Discord's Gateway](https://discord.com/developers/docs/topics/gateway), which maintains the
connection and rate limits commands.

```kotlin
suspend fun main() {
val gateway = DefaultGateway()

gateway.on<MessageCreate> {
println("${message.author.username}: ${message.content}")
val words = message.content.split(' ')
when (words.firstOrNull()) {
"!close" -> gateway.stop()
"!detach" -> gateway.detach()
}
}

gateway.start("your bot token") {
@OptIn(PrivilegedIntent::class)
intents += Intent.MessageContent
}
}
```


### Voice

A mapping of [Discord's Voice Connection](https://discord.com/developers/docs/topics/voice-connections), which maintains the connection and handles audio transmission.

If you want to use voice, you need to enable the voice capability,
which is only available for Gradle

```kotlin
dependencies {
implementation("dev.kord", "core", "<version>") {
capabilities {
requireCapability("dev.kord:core-voice:<version>")
}
}
}
```

```kotlin
suspend fun main() {
val kord = Kord("your token")
val voiceChannel = kord.getChannelOf<VoiceChannel>(id = Snowflake(1))!!

voiceChannel.connect {
audioProvider { AudioFrame.fromData(/* your opus encoded audio */) }
}

kord.login()
}
```

## FAQ

## Will you support kotlin multi-platform

We will, there's an [issue](https://github.com/kordlib/kord/issues/69) open to track the features we want/need to make a
transition to MPP smooth.
Currently we're supporting both Kotlin/JVM and Kotlin/JS for the majority of our API, for more information check
[Modules](#modules) and #69

## When will you document your code
## When will you document your code?

Yes.

# This project is supported by JetBrains

[![JetBrains Logo (Main) logo](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://jb.gg/OpenSourceSupport)
[![JetBrains Logo (Main) logo](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://jb.gg/OpenSourceSupport)
5 changes: 5 additions & 0 deletions buildSrc/src/main/kotlin/BinaryCompatibility.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import kotlinx.validation.ApiValidationExtension

fun ApiValidationExtension.applyKordBCVOptions() {
nonPublicMarkers += "dev.kord.common.annotation.KordInternal"
}
49 changes: 37 additions & 12 deletions buildSrc/src/main/kotlin/Compiler.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,46 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import kotlinx.atomicfu.plugin.gradle.AtomicFUPluginExtension
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.getByType
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet

object CompilerArguments {
const val time = "-opt-in=kotlin.time.ExperimentalTime"
const val contracts = "-opt-in=kotlin.contracts.ExperimentalContracts"
object OptIns {
const val coroutines = "kotlinx.coroutines.ExperimentalCoroutinesApi"
}

const val kordPreview = "-opt-in=dev.kord.common.annotation.KordPreview"
const val kordExperimental = "-opt-in=dev.kord.common.annotation.KordExperimental"
const val kordVoice = "-opt-in=dev.kord.common.annotation.KordVoice"
val kordOptIns = listOf(
"kotlin.time.ExperimentalTime",
"kotlin.contracts.ExperimentalContracts",

const val progressive = "-progressive"
}
"dev.kord.common.annotation.KordInternal",
"dev.kord.common.annotation.KordPreview",
"dev.kord.common.annotation.KordExperimental",
"dev.kord.common.annotation.KordVoice",
)

object Jvm {
const val target = 8
}

fun KotlinJvmCompilerOptions.applyKordCompilerOptions() {
allWarningsAsErrors.set(true)
freeCompilerArgs.add(CompilerArguments.progressive)
fun KotlinCommonCompilerOptions.applyKordCompilerOptions() {
// TODO: set to true again once https://github.com/Kotlin/kotlinx-atomicfu/issues/289 is fixed
allWarningsAsErrors.set(false)
freeCompilerArgs.add("-progressive")
}

fun KotlinSourceSet.applyKordOptIns() {
languageSettings {
if ("Test" in name) optIn(OptIns.coroutines)
kordOptIns.forEach(::optIn)
}
}

fun Project.configureAtomicFU() {
// https://github.com/Kotlin/kotlinx-atomicfu/issues/210
configure<AtomicFUPluginExtension> {
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependenciesVersion = libs.findVersion("kotlinx-atomicfu").get().requiredVersion
}
}
33 changes: 33 additions & 0 deletions buildSrc/src/main/kotlin/Documentation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask
import java.net.URL

fun AbstractDokkaLeafTask.applyKordDokkaOptions() {
failOnWarning.set(true)

dokkaSourceSets.configureEach {

jdkVersion.set(Jvm.target)

suppressGeneratedFiles.set(false)

sourceLink {
localDirectory.set(project.projectDir)
remoteUrl.set(URL("https://github.com/kordlib/kord/blob/${Library.commitHashOrDefault("0.9.x")}/${project.name}"))
remoteLineSuffix.set("#L")
}

externalDocumentationLink("https://kotlinlang.org/api/kotlinx.coroutines/")
externalDocumentationLink("https://kotlinlang.org/api/kotlinx.serialization/")
externalDocumentationLink(
url = "https://kotlinlang.org/api/kotlinx-datetime/",
packageListUrl = "https://kotlinlang.org/api/kotlinx-datetime/kotlinx-datetime/package-list",
)
externalDocumentationLink("https://api.ktor.io/")

// don't list `TweetNaclFast` in docs
perPackageOption {
matchingRegex.set("""com\.iwebpp\.crypto""")
suppress.set(true)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
org.jetbrains.kotlin.multiplatform
}

repositories {
mavenCentral()
}

kotlin {
jvm()
js(IR) {
nodejs()
}
jvmToolchain(Jvm.target)

targets {
all {
compilations.all {
compilerOptions.options.applyKordCompilerOptions()
}
}
}
}
Loading

0 comments on commit 64f6636

Please sign in to comment.