Skip to content

Commit

Permalink
add README, and also add UUIDs to SpecialEventsManager
Browse files Browse the repository at this point in the history
  • Loading branch information
dkim19375 committed May 21, 2021
1 parent 53f40f0 commit 7a22428
Show file tree
Hide file tree
Showing 18 changed files with 119 additions and 22 deletions.
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# dkim19375JDAUtils
A kotlin library for JDA to help to make discord bots easier!

**WARNING! UPDATES MAY INCLUDE API BREAKING CHANGES!
THE API IS STILL VERY NEW, RESULTING IN FREQUENT CHANGES**

### An example of using this library is with my bot UniG0 - https://github.com/dkim19375/UniG0

**NOTE: This might not be up-to-date, if these code snippets don't
work, please notify me!**

## Adding the dependency
```groovy
repositories {
maven { url = 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.dkim19375:dkim19375JDAUtils:VERSION'
}
```

## Setting up the bot
A class, that holds information such as the commands, needs to be
created. It extends `me.dkim19375.dkim19375JDAUtils.BotBase`.
To start the bot, you call BotBase#onStart.
It is recommended to make this your main class.
```kotlin
import me.dkim19375.dkim19375jdautils.BotBase

class Bot : BotBase() {
override val name = "Bot-Name"
override val token = "token-here"

init {
onStart()
}

override fun getPrefix(guild: String): String {
return "!"
}
}
```
Now, you can simply run the bot, invite the bot to a server,
then run `!help`!
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ package me.dkim19375.dkim19375jdautils

import me.dkim19375.dkim19375jdautils.annotation.API
import me.dkim19375.dkim19375jdautils.command.Command
import me.dkim19375.dkim19375jdautils.command.CommandType
import me.dkim19375.dkim19375jdautils.command.HelpCommand
import me.dkim19375.dkim19375jdautils.command.OTHER_TYPE
import me.dkim19375.dkim19375jdautils.event.CustomListener
import me.dkim19375.dkim19375jdautils.event.EventListener
import me.dkim19375.dkim19375jdautils.managers.SpecialEventsManager
Expand All @@ -19,17 +20,17 @@ import kotlin.system.exitProcess
* @constructor Create a bot base, should be the main class of your bot
*/
@API
@Suppress("LeakingThis")
abstract class BotBase {
abstract val name: String
abstract val token: String
open val customListener: CustomListener = object : CustomListener() {}
open val intents = mutableSetOf(GatewayIntent.GUILD_MESSAGE_REACTIONS, GatewayIntent.DIRECT_MESSAGE_REACTIONS)

lateinit var jda: JDA
val commandTypes = mutableSetOf<CommandType>()
val commands = mutableSetOf<Command>()
val commandTypes = mutableSetOf(OTHER_TYPE)
val commands = mutableSetOf(HelpCommand(this))

@Suppress("LeakingThis")
@API
val eventsManager: SpecialEventsManager = SpecialEventsManager(this)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ package me.dkim19375.dkim19375jdautils.managers
import me.dkim19375.dkim19375jdautils.BotBase
import me.dkim19375.dkim19375jdautils.annotation.API
import me.dkim19375.dkim19375jdautils.data.Whitelist
import me.dkim19375.dkim19375jdautils.util.EventType
import me.dkim19375.dkim19375jdautils.util.getMessageId
import me.dkim19375.dkim19375jdautils.util.getUserId
import me.dkim19375.dkim19375jdautils.util.*
import net.dv8tion.jda.api.entities.*
import net.dv8tion.jda.api.events.Event
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent
import net.dv8tion.jda.api.events.message.priv.react.PrivateMessageReactionAddEvent
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent
import net.dv8tion.jda.api.hooks.ListenerAdapter
import net.dv8tion.jda.api.requests.RestAction
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executors
import java.util.concurrent.Future
Expand All @@ -29,20 +28,45 @@ import kotlin.reflect.KClass
open class SpecialEventsManager(private val bot: BotBase) : ListenerAdapter() {
private val executor = Executors.newSingleThreadExecutor()

private val events = mutableListOf<(Event) -> Future<Pair<Boolean, Boolean>>>()
private val singleEvents = mutableMapOf<Type, MutableList<(Event) -> Future<Pair<Boolean, Boolean>>>>()
@API
val events = mutableMapOf<UUID, (Event) -> Future<Pair<Boolean, Boolean>>>()

@API
val singleEvents = mutableMapOf<Type, MutableMap<UUID, (Event) -> Future<Pair<Boolean, Boolean>>>>()

override fun onGuildMessageReactionAdd(event: GuildMessageReactionAddEvent) = onEvent(Type.REACTION_ADD, event)
override fun onPrivateMessageReactionAdd(event: PrivateMessageReactionAddEvent) = onEvent(Type.REACTION_ADD, event)
override fun onMessageReactionAdd(event: MessageReactionAddEvent) = onEvent(Type.REACTION_ADD, event)

@API
fun getTask(uuid: UUID): ((Event) -> Future<Pair<Boolean, Boolean>>)? {
events[uuid]?.let {
return it
}
for (map in singleEvents.values) {
for ((newUUID, event) in map) {
if (newUUID == uuid) {
return event
}
}
}
return null
}

@API
@Synchronized
fun removeTask(uuid: UUID) {
events.remove(uuid)
singleEvents.forEach { (_, map) -> map.remove(uuid) }
}

@Synchronized
protected open fun onEvent(@Suppress("SameParameterValue") type: Type, event: Event) {
events.toList().forEach { e ->
executor.submit {
val result = e(event).get()
val result = e.second(event).get()
if (result.second && result.first) {
events.removeIf { it === e }
events.removeIf { uuid, _ -> uuid == e.first }
}
}
}
Expand All @@ -52,13 +76,13 @@ open class SpecialEventsManager(private val bot: BotBase) : ListenerAdapter() {
}
for (expression in list.toList()) {
executor.submit {
val result = expression(event).get()
val result = expression.second(event).get()
if (result.first) {
list.removeIf { it === expression }
list.removeIf { uuid, _ -> uuid == expression.first }
}
}
}
if (singleEvents.getOrDefault(otherType, mutableListOf()).isEmpty()) {
if (singleEvents.getOrDefault(otherType, mutableMapOf()).isEmpty()) {
singleEvents.remove(otherType)
}
}
Expand Down Expand Up @@ -92,7 +116,7 @@ open class SpecialEventsManager(private val bot: BotBase) : ListenerAdapter() {
open fun onReactionAdd(
permanent: Boolean,
eventType: EventType,
action: (Event, Guild?, MessageReaction.ReactionEmote, MessageChannel, User, Message, Member?) -> Boolean,
action: (Event, Guild?, MessageReaction.ReactionEmote, MessageChannel, User, Message, Member?, UUID) -> Boolean,
requiredMessage: Long = 0,
requiredChannel: Long = 0,
requiredGuild: Long = 0,
Expand All @@ -102,8 +126,10 @@ open class SpecialEventsManager(private val bot: BotBase) : ListenerAdapter() {
removeSelfIfNoPerms: Boolean = false,
reaction: MessageReaction.ReactionEmote? = null,
debug: Boolean = false
) {
@Suppress("DuplicatedCode") val actionVar: (Event) -> Future<Pair<Boolean, Boolean>> = actionLabel@{ event ->
): UUID {
val combined = events.keys.plus(singleEvents.values.map { a -> a.keys }.combine())
val uuid = combined.getRandomUUID()
val actionVar: (Event) -> Future<Pair<Boolean, Boolean>> = actionLabel@{ event ->
val future = CompletableFuture<Pair<Boolean, Boolean>>()
if (debug) {
println("called ------------")
Expand Down Expand Up @@ -226,7 +252,7 @@ open class SpecialEventsManager(private val bot: BotBase) : ListenerAdapter() {
future.complete(
Pair(
first = true,
second = !action(event, guild, emoji, channel, user, msg, member)
second = !action(event, guild, emoji, channel, user, msg, member, uuid)
)
)
return@removeNoPermsLabel true
Expand Down Expand Up @@ -276,11 +302,11 @@ open class SpecialEventsManager(private val bot: BotBase) : ListenerAdapter() {
println("added to variables")
}
if (permanent) {
events.add(actionVar)
return
events[uuid] = actionVar
return uuid
}
singleEvents.getOrPut(Type.REACTION_ADD)
{ mutableListOf() }.add(actionVar)
singleEvents.getOrPut(Type.REACTION_ADD) { mutableMapOf() }[uuid] = actionVar
return uuid
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package me.dkim19375.dkim19375jdautils.util
import me.dkim19375.dkim19375jdautils.BotBase
import me.dkim19375.dkim19375jdautils.command.Command
import me.dkim19375.dkim19375jdautils.command.CommandType
import java.util.*

fun Iterable<String>.containsIgnoreCase(find: String): Boolean = getIgnoreCase(find) != null
fun Iterable<String>.getIgnoreCase(find: String): String? = firstOrNull { it.equals(find, ignoreCase = true) }
Expand All @@ -22,4 +23,29 @@ fun Set<Command>.getOfType(type: CommandType): Set<Command> {
}
}
return ofType
}
fun <K, V> MutableMap<K, V>.removeIf(filter: (K, V) -> Boolean) {
for ((k, v) in toMap()) {
if (filter(k, v)) {
remove(k)
}
}
}

fun Collection<UUID>.getRandomUUID(): UUID {
while (true) {
val uuid = UUID.randomUUID()
if (contains(uuid)) {
continue
}
return uuid
}
}

fun <T> Collection<Collection<T>>.combine(): List<T> {
val new = mutableListOf<T>()
for (item in this) {
new.addAll(item)
}
return new
}

0 comments on commit 7a22428

Please sign in to comment.