All Projects → MinnDevelopment → jda-ktx

MinnDevelopment / jda-ktx

Licence: Apache-2.0 License
Collection of useful Kotlin extensions for JDA

Programming Languages

kotlin
9241 projects

Projects that are alternatives of or similar to jda-ktx

CoroutineLite
Simple implementation of kotlinx.coroutines to clarify the design of Kotlin Coroutines.
Stars: ✭ 142 (+189.8%)
Mutual labels:  coroutines, kotlin-coroutines
mqtt
Kotlin cross-platform, coroutine based, reflectionless MQTT 3.1.1 & 5.0 client & server
Stars: ✭ 31 (-36.73%)
Mutual labels:  coroutines, kotlin-coroutines
StarWarsSearch-MVI
Star wars sample android project showcasing the use of View components for rendering UI in Fragments and Activities. Uses Android Jetpack, clean architecture with MVI (Uni-directional data flow), dagger hilt, and kotlin coroutines with StateFlow
Stars: ✭ 189 (+285.71%)
Mutual labels:  coroutines, kotlin-coroutines
Android Clean Arch Coroutines Koin
Implemented by Clean Architecture, MVVM, Koin, Coroutines, Moshi, Mockk, LiveData & DataBinding
Stars: ✭ 173 (+253.06%)
Mutual labels:  coroutines, kotlin-coroutines
android-clean-arc-coroutines
Clean Architecture(Coroutines,Dagger, MVVM, ROOM, retrofit, databinding)
Stars: ✭ 116 (+136.73%)
Mutual labels:  coroutines, kotlin-coroutines
the-white-rabbit
The White Rabbit is an asynchronous RabbitMQ (AMQP) client based on Kotlin coroutines
Stars: ✭ 90 (+83.67%)
Mutual labels:  coroutines, kotlin-coroutines
kotlin-coroutines-android
Useful extensions for coroutines. AutoDispose + MainScope
Stars: ✭ 84 (+71.43%)
Mutual labels:  coroutines, kotlin-coroutines
Androidcoroutinesplayground
Android Coroutines Playground
Stars: ✭ 119 (+142.86%)
Mutual labels:  coroutines, kotlin-coroutines
SketchwareManager
Coroutine-based library for managing Sketchware (Sketchware Pro/Studio) projects, collections and etc.
Stars: ✭ 54 (+10.2%)
Mutual labels:  coroutines, kotlin-coroutines
NewsReader
Android News Reader app. Kotlin Coroutines, Retrofit and Realm
Stars: ✭ 21 (-57.14%)
Mutual labels:  coroutines, kotlin-coroutines
Retrofit2-Flow-Call-Adapter
A Retrofit 2 adapter for Kotlin Flows.
Stars: ✭ 41 (-16.33%)
Mutual labels:  coroutines, kotlin-coroutines
BlueFlow
Android Bluetooth classic API wrapped in Coroutines Flow.
Stars: ✭ 64 (+30.61%)
Mutual labels:  coroutines, kotlin-coroutines
Splitties
A collection of hand-crafted extensions for your Kotlin projects.
Stars: ✭ 1,945 (+3869.39%)
Mutual labels:  coroutines, kotlin-coroutines
Delish
Delish, a Food Recipes App in Jetpack Compose and Hilt based on modern Android tech-stacks and MVI clean architecture.
Stars: ✭ 356 (+626.53%)
Mutual labels:  coroutines, kotlin-coroutines
Modular App Core
Core implementations for a modular Android App
Stars: ✭ 127 (+159.18%)
Mutual labels:  coroutines, kotlin-coroutines
NoMansWallpaperApp
Looking for your next No Man's Sky wallpaper?
Stars: ✭ 35 (-28.57%)
Mutual labels:  coroutines, kotlin-coroutines
Paperplane
📚 PaperPlane - An Android reading app, including articles from Zhihu Daily, Guokr Handpick and Douban Moment.
Stars: ✭ 1,147 (+2240.82%)
Mutual labels:  coroutines, kotlin-coroutines
Kotlin Coroutines Android
Useful extensions for coroutines. AutoDispose + MainScope
Stars: ✭ 77 (+57.14%)
Mutual labels:  coroutines, kotlin-coroutines
AndroidCoroutineScopes
This lib implements the most common CoroutineScopes used in Android apps.
Stars: ✭ 14 (-71.43%)
Mutual labels:  coroutines, kotlin-coroutines
WanAndroidJetpack
🔥 WanAndroid 客户端,Kotlin + MVVM + Jetpack + Retrofit + Glide。基于 MVVM 架构,用 Jetpack 实现,网络采用 Kotlin 的协程和 Retrofit 配合使用!精美的 UI,便捷突出的功能实现,欢迎下载体验!
Stars: ✭ 124 (+153.06%)
Mutual labels:  coroutines, kotlin-coroutines

Kotlin kotlinx-coroutines JDA

jda-ktx

Collection of useful Kotlin extensions for JDA. Great in combination with kotlinx-coroutines and jda-reactor.

Required Dependencies

  • Kotlin 1.6.10
  • kotlinx.coroutines 1.6.0
  • JDA 5.0.0-alpha.5

Examples

You can look at my own bot (strumbot) for inspiration, or look at the examples listed here. The most useful feature of this library is the CoroutineEventManager which adds the ability to use suspending functions in your event handlers.

// enableCoroutines (default true) changes the event manager to CoroutineEventManager
// this event manager uses the GlobalScope by default but can be configured to use a custom scope if you set it manually
val jda = light("token", enableCoroutines=true) {
    intents += listOf(GatewayIntent.GUILD_MEMBERS)
}

// This can only be used with the CoroutineEventManager
jda.listener<MessageReceivedEvent> {
    val guild = it.guild
    val channel = it.channel
    val message = it.message
    val content = message.contentRaw

    if (content.startsWith("!profile")) {
        // Send typing indicator and wait for it to arrive
        channel.sendTyping().await()
        val user = message.mentionedUsers.firstOrNull() ?: run {
            // Try loading user through prefix loading
            val matches = guild.retrieveMembersByPrefix(content.substringAfter("!profile "), 1).await()
            // Take first result, or null
            matches.firstOrNull()
        }

        if (user == null) // unknown user for name
            channel.send("${it.author.asMention}, I cannot find a user for your query!").queue()
        else // load profile and send it as embed
            channel.send("${it.author.asMention}, here is the user profile:", embed=profile(user)).queue()
    }
}

jda.onCommand("ban", timeout=2.minutes) { event -> // 2 minute timeout listener
    val user = event.getOption("user")!!.asUser
    val confirm = danger("${user.id}:ban", "Confirm")
    event.reply_(
        "Are you sure you want to ban **${user.asTag}**?",
        components=confirm.into(),
        ephemeral=true
    ).queue()

    withTimeoutOrNull(1.minutes) { // 1 minute scoped timeout
        val pressed = event.user.awaitButton(confirm) // await for user to click button
        pressed.deferEdit().queue() // Acknowledge the button press
        event.guild.ban(user, 0).queue() // the button is pressed -> execute action
    } ?: event.hook.editMessage(/*id="@original" is default */content="Timed out.", components=emptyList()).queue()
}

jda.onButton("hello") { // Button that says hello
    it.reply_("Hello :)").queue()
}

Coroutine Extensions

I've added a few suspending extension functions to various JDA components. None of these extensions require the CoroutineEventManager!

To use await<Event> and awaitMessage the event manager must support either EventListener or @SubscribeEvent, the ReactiveEventManager and CoroutineEventManager both support this.

/* Async Operations */

// Await RestAction result
suspend fun <T> RestAction<T>.await()
// Await Task result (retrieveMembersByPrefix)
suspend fun <T> Task<T>.await()

/* Event Waiter */

// Await specific event
suspend fun <T : GenericEvent> JDA.await(filter: (T) -> Boolean = { true })
// Await specific event
suspend fun <T : GenericEvent> ShardManager.await(filter: (T) -> Boolean = { true })
// Await message from specific channel (filter by user and/or filter function)
suspend fun MessageChannel.awaitMessage(author: User? = null, filter: (Message) -> Boolean = { true }): Message

// Flow representation for PaginationAction
fun <T, M: PaginationAction<T, M>> M.asFlow(): Flow<T>

Delegates

This library implements delegate properties which can be used to safely keep references of JDA entities such as users/channels. These delegates can be used with the ref() extension function:

class Foo(guild: Guild) {
    val guild : Guild by guild.ref()
}

You can also use the SLF4J delegate to initialize loggers.

object Listener : ListenerAdapter() {
    private val log by SLF4J 

    override fun onMessageReceived(event: MessageReceivedEvent) {
        log.info("[{}] {}: {}", event.channel.name, event.author.asTag, event.message.contentDisplay)
    }
}

Embed- and MessageBuilders

This library also provides some useful builder alternatives which can be used instead of the default MessageBuilder and EmbedBuilder from JDA.

You can see both builders in builders.kt.

Example

val embed = Embed(title="Hello Friend", description="Goodbye Friend")

Or the builder function style:

val embed = Embed {
    title = "Hello Friend"
    description = "Goodbye Friend"
    field {
        name = "How good is this example?"
        value = "5 :star:"
        inline = false
    }
    timestamp = Instant.now()
    color = 0xFF0000
}

Command and SelectMenu Builders

jda.updateCommands {
    slash("ban", "Ban a user") {
        option<User>("user", "The user to ban", true)
        option<String>("reason", "Why to ban this user")
        option<Int>("duration", "For how long to ban this user") {
            choice("1 day", 1)
            choice("1 week", 7)
            choice("1 month", 31)
        }
    }

    slash("mod", "Moderation commands") {
        subcommand("ban", "Ban a user") {
            option<User>("user", "The user to ban", true)
            option<String>("reason", "Why to ban this user")
            option<Int>("duration", "For how long to ban this user") {
                choice("1 day", 1)
                choice("1 week", 7)
                choice("1 month", 31)
            }
        }

        subcommand("prune", "Prune messages") {
            option<Int>("amount", "The amount to delete from 2-100, default 50")
        }
    }
}.queue()

jda.upsertCommand("prune", "Prune messages") {
    option<Int>("amount", "The amount to delete from 2-100, default 50")
}.queue()

val menu = SelectMenu("menu:class") {
    option("Frost Mage", "mage-frost", emoji=FROST_SPEC, default=true)
    option("Fire Mage", "mage-fire", emoji=FIRE_SPEC)
    option("Arcane Mage", "mage-arcane", emoji=ARCANE_SPEC)
}

Buttons

jda.upsertCommand("ban", "ban a user") {
    option<Member>("member", "The member to ban", true)
    option<String>("reason", "The ban reason")
}.queue()

jda.onCommand("ban") { event ->
    if (event.user.asTag != "Minn#6688") return@onCommand
    val guild = event.guild!!
    val member = event.getOption("member")?.asUser!!
    val reason = event.getOption("reason")?.asString

    // Buttons will timeout after 15 minutes by default
    val accept = jda.button(label = "Accept", style = SUCCESS, user = event.user) {
        guild.ban(member, 0, reason).queue()
        it.editMessage("${event.user.asTag} banned ${member.asTag}")
            .setActionRows() // remove buttons from message
            .queue()
    }
    val deny = jda.button(label = "Deny", style = DANGER, user = event.user) { butt ->
        butt.hook.deleteOriginal().queue() // automatically acknowledged if callback does not do it
    }

    event.reply_("Are you sure?")
        .addActionRow(accept, deny) // send your buttons
        .queue()
}

// or a global listener
jda.onButton("accept") { event ->
    event.reply("You accepted :)").queue()
}

Sending Messages

This library also adds some more kotlin idiomatic message send/edit extensions which rely on named parameters. These named parameters also support defaults, which can be modified by SendDefaults and MessageEditDefaults.

In order to avoid overload conflicts with methods from JDA, some functions may use a suffixed _ such as reply_ or editMessage_. This is simply done to prevent you from accidentally calling the wrong overload which doesn't use the defaults of this library. If you don't care about that, you can simply add an import alias with import dev.minn.jda.ktx.message.reply_ as reply.

Example:

SendDefaults.ephemeral = true // <- all reply_ calls set ephemeral=true by default
MessageEditDefaults.replace = false // <- only apply explicitly set parameters (default behavior)
jda.onCommand("ban") { event ->
    if (!event.member.hasPermission(Permission.BAN_MEMBERS))
        return@onCommand event.reply_("You can't do that!").queue()
    
    event.reply_("Are you sure?", components=danger("ban", "Yes!").into())
    val interaction = event.user.awaitButton("ban")
    val user = event.getOption("target")!!.asUser
    event.guild!!.ban(user, 0).queue()
    interaction.editMessage_("Successfully banned user", components=emptyList()).queue()
}

Download

Gradle

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

dependencies {
    implementation("net.dv8tion:JDA:${JDA_VERSION}")
    implementation("com.github.minndevelopment:jda-ktx:${COMMIT}")
}

Maven

<repository>
    <id>jitpack</id>
    <name>jitpack</name>
    <url>https://jitpack.io/</url>
</repository>
<dependency>
  <groupId>net.dv8tion</groupId>
  <artifactId>JDA</artifactId>
  <version>$JDA_VERSION</version>
</dependency>
<dependency>
  <groupId>com.github.minndevelopment</groupId>
  <artifactId>jda-ktx</artifactId>
  <version>$COMMIT</version>
</dependency>
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].