Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/minndevelopment/jda-reactor

A collection of kotlin extensions for JDA that make use with reactor-core easier.
https://github.com/minndevelopment/jda-reactor

discord hacktoberfest jda kotlin reactive reactive-streams

Last synced: 3 months ago
JSON representation

A collection of kotlin extensions for JDA that make use with reactor-core easier.

Awesome Lists containing this project

README

        

[ ![version](https://shields.io/github/v/tag/MinnDevelopment/jda-reactor) ](#Installation)
# jda-reactor

A collection of kotlin extensions for JDA that make use with reactor-core easier.

## Installation

Replace the `$VERSION` with the latest release version.

Replace `$JDA_VERSION` with the latest stable JDA v5 release.

### Gradle

```gradle
dependencies {
implementation("net.dv8tion:JDA:$JDA_VERSION")
implementation("com.github.MinnDevelopment:jda-reactor:$VERSION")
}

repositories {
mavenCentral()
maven("https://jitpack.io")
}
```

### Maven

```xml

net.dv8tion
JDA
$JDA_VERSION

com.github.MinnDevelopment
jda-reactor
$VERSION

```

```xml

jitpack
jitpack
https://jitpack.io

```

## Examples

Some small example usages of the components supported by this library.

There is a complete bot written as an example available at [reactive-jda-bot](https://github.com/MinnDevelopment/reactive-jda-bot).

### ReactiveEventManager

```kotlin
fun main() {
// Create a ReactiveEventManager for Flux event streams
val manager = ReactiveEventManager()
// subscribe directly on the manager instance
manager.on() // Flux
.next() // Mono
.subscribe { println("Ready to go!") } // Subscribe to event

manager.on() // Flux
.map { it.message } // Flux
.filter { it.contentRaw == "!ping" } // filter by content
.map { it.channel } // Flux
.map { it.sendMessage("Pong!") } // Flux
.flatMap { it.asMono() } // Flux (send message and provide result)
.subscribe() // Subscribe to event

val jda = JDABuilder(BOT_TOKEN)
.setEventManager(manager)
.build()

// you can also subscribe to events from the JDA instance
jda.on() // Flux
.subscribe { println("That was fun!") } // Make a statement on shutdown, not guaranteed to run if daemon scheduler (default)
}
```

### Mono/Flux RestAction

Every RestAction receives an `asMono` extensions which converts them into a `Mono` of the same result type.

Additionally some more specific types such as `PaginationAction` can be streamed into a `Flux`
which will automatically paginate the endpoint as demanded by the subscription.

#### PaginationAction\

```kotlin
fun getMessagesForUser(channel: MessageChannel, user: User): Flux {
val action = channel.iterableHistory
return action.asFlux() // Flux
.filter { it.author == user } // filter by user
}
```

#### RestAction\

```kotlin
fun sendAndLog(channel: MessageChannel, content: String) {
val action = channel.sendMessage(content)
action.asMono() // Mono
.flatMap { it.addReaction(EMOTE).asMono() } // Mono = empty mono
.doOnSuccess { println("${channel.name}: $content") } // add side-effect
.subscribe() // subscribe to empty stream
}
```

#### RestAction>

```kotlin
fun getBannedUsers(guild: Guild): Flux {
return guild.retrieveBanList() // RestAction>
.toFlux() // Flux
.map { it.user } // Flux
.map { it.asTag } // Flux
}
```

### Entity Observers

```kotlin
fun onNextMessage(channel: MessageChannel, callback: (Message) -> Unit) {
channel.onMessage() // Flux
.next() // Mono
.map { it.message } // Mono
.subscribe { callback(it) }
}

fun onReaction(message: Message, reaction: String): Flux {
return message.on() // Flux
.filter { it.emoji.name == reaction } // Flux with filter
.map { it.user } // Flux
}
```

```kotlin
fun onNameChange(user: User): Flux {
return user.on() // Flux
.map { it.newValue } // Flux
}

fun onNameChange(channel: GuildChannel): Flux {
return channel.onUpdate() // Flux
.map { it.newValue } // Flux
}
```

### CacheView

I've added a special `toFluxLocked` which makes use of the `lockedIterator()` that was introduced in JDA version 4. This will automatically lock the cache view for read access when `subscribe()` is invoked and unlock it on the completion signal.

#### Example toFluxLocked

```kotlin
fun findUserByName(jda: JDA, name: String): Mono {
return jda.userCache
.toFluxLocked() // Flux lazy locked user cache
.filterFirst { it.name == name } // Mono unlock on first match
}

fun sendToUser(jda: JDA, name: String, content: String) {
return findUserByName(name) // Mono
.flatMap { it.openPrivateChannel().asMono() } // Mono
.flatMap { it.sendMessage(content).asMono() } // Mono
.subscribe() // lock the user cache and look for the user by name
}
```

### Quality of Life Extensions

I've added a few extensions to reactor itself that might be useful when working with JDA.

- `T?.toMono()` improvement of `T.toMono()` which uses `Mono.justOrEmpty` instead
- `Mono.then(() -> Mono)` lazy version of `Mono.then(Mono)` similar to `Mono.flatMap`
- `Flux.then(() -> Mono)` same as above
- `Flux.filterFirst((T) -> Boolean)` combination of `filter().next()`
- `Flux.filterFirstWhen((T) -> Publisher)` combination of `filterWhen().next()`
- `Flux.nextWhen((T) -> Mono)` combination of `next().flatMap()`
- `Iterable>.asFlux(): Flux` flatten lists of completion stages