diff --git a/src/main/kotlin/nl/voidcorp/dbot/Events.kt b/src/main/kotlin/nl/voidcorp/dbot/Events.kt index 20f9531..044f074 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/Events.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/Events.kt @@ -7,7 +7,7 @@ import net.dv8tion.jda.core.hooks.ListenerAdapter object Events : ListenerAdapter() { override fun onMessageReceived(event: MessageReceivedEvent) { - if (event.message.contentStripped.toLowerCase().contains("fraud")) { + if (event.message.contentStripped.toLowerCase().contains("fraud") or event.message.contentRaw.contains(Regex("`(\\w+|\\s+|\\W)+`"))) { val e = event.message.guild.getEmotesByName("fr00d", true).firstOrNull() if (e != null) event.message.addReaction(e).queue() diff --git a/src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt b/src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt index 0874b8f..bed1d34 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt @@ -1,7 +1,5 @@ package nl.voidcorp.dbot -import com.jagrosh.jdautilities.command.CommandClientBuilder -import com.jagrosh.jdautilities.command.CommandListener import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager @@ -13,21 +11,17 @@ import io.javalin.json.ToJsonMapper import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.JDA import net.dv8tion.jda.core.JDABuilder -import net.dv8tion.jda.core.entities.Game -import net.dv8tion.jda.core.entities.MessageEmbed -import net.dv8tion.jda.core.events.message.MessageReceivedEvent import net.dv8tion.jda.webhook.WebhookClient import net.dv8tion.jda.webhook.WebhookClientBuilder import nl.voidcorp.dbot.commands.* +import nl.voidcorp.dbot.music.initMusic import nl.voidcorp.dbot.storage.GitlabWebhook import org.slf4j.LoggerFactory import java.io.File import java.io.FileReader -import java.time.LocalDateTime val playerManager = DefaultAudioPlayerManager() -val cb = CommandClientBuilder() val log = LoggerFactory.getLogger("UnityBot") @@ -90,72 +84,27 @@ fun main(args: Array) { ctx.status(200).result("OK") } - cb.setOwnerId("168743656738521088") - cb.setPrefix("!") - cb.setAlternativePrefix("+") - commands.addAll(helloCommand, pingCommand) - cb.setGame(Game.watching("fraud and \uD83C\uDFB5 (v1.3)")) - val replies = listOf("Hello %%", "Why hello there %%!", "Hello there %%", "General %%. You are a bold one", "A wild %% appeared!") - cb.setHelpConsumer { event -> - val greeting = replies.random().replace("%%", event.member.effectiveName) - val eb = EmbedBuilder() - when { - event.args.isEmpty() -> { - eb.setTitle(greeting) - .appendDescription("My name is ${event.selfMember.effectiveName}, and I am definitely the best Discord bot around!\n\nUse `!help command` for a chance that I have more info about a command!") - .setColor(event.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) - val m = commands.catMap() - for (e in m.entries) { - val f = MessageEmbed.Field(e.key, e.value.joinToString(separator = "\n", postfix = "\n") { "`!${it.name}`" }, true) - eb.addField(f) - } - eb.setThumbnail(event.selfUser.effectiveAvatarUrl) - } - commands.any { it.name == event.args } -> { - val cmd = commands.first { it.name == event.args } - eb.setTitle("**!${cmd.name}**") - .appendDescription(cmd.help) - .setColor(event.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) - if (cmd.aliases.isNotEmpty()) eb.addField("Aliases", cmd.aliases.joinToString { "`$it`" }, false) - eb.addField("Usage", "`!${cmd.howTo.emptyOr(cmd.name)}`", false) + commands.addAll(helloCommand, pingCommand, helpCommand) + + + - } - event.args == "help" -> { - eb.setTitle(greeting) - .appendDescription("Haha, very funny ${event.member.effectiveName}") - .setColor(event.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) - } - else -> { - eb.setTitle(greeting) - .appendDescription("I honestly have no idea what the command `${event.args}` does...") - .setColor(event.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) - } - } - event.reply(eb.build()) - } initMusic() initFun() - cb.setListener(object : CommandListener { - override fun onNonCommandMessage(event: MessageReceivedEvent) { - val msg = event.message.contentRaw - if (msg.startsWith('!') or msg.startsWith('+')) { - val eb = EmbedBuilder().setTitle("Something went wrong...") - .addField("Unknown command: `${msg.substring(1)}`", "I don't know this command...", false) - .setColor(event.guild.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) - event.textChannel.sendMessage(eb.build()).queue() - } - } - }) - cb.addCommands(*commands.toTypedArray()) - val client = cb.build() - bot = JDABuilder(args[0]).addEventListener(client).addEventListener(nl.voidcorp.dbot.Events).setAudioSendFactory(NativeAudioSendFactory()).build() + val custom = UnityCommandClient("!") + custom.addCommands(commands) + custom.version = "1.4" + + + bot = JDABuilder(args[0]).addEventListener(custom).addEventListener(nl.voidcorp.dbot.Events).setAudioSendFactory(NativeAudioSendFactory()).build() + } lateinit var bot: JDA diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/Categories.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/Categories.kt new file mode 100644 index 0000000..459dedd --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/Categories.kt @@ -0,0 +1,109 @@ +package nl.voidcorp.dbot.commands + +import com.jagrosh.jdautilities.command.Command +import com.jagrosh.jdautilities.command.CommandEvent +import net.dv8tion.jda.core.entities.ChannelType +import net.dv8tion.jda.core.entities.TextChannel + +open class UnityCategory(name: String, + val channels: List = listOf("bot"), val roles: List = listOf(), + val errorMessage: (TextChannel) -> String = { "This command can only be used in ${it.asMention}." }, + val check: (CommandEvent) -> Boolean = { true }) : Command.Category(name) { + override fun test(ce: CommandEvent): Boolean { + /*if (ce.member.hasPermission(Permission.ADMINISTRATOR)) return true*/ + if (ce.member.roles.firstOrNull { it.name.equals("admin", true) } != null) return true + if (channels.all { ce.guild.getTextChannelsByName(it, true).firstOrNull() == null }) return true + if (channels.isEmpty()) return true + + lateinit var ch: TextChannel + for (channel in channels.map { ce.guild.getTextChannelsByName(it, true).firstOrNull() }) { + if (channel != null) { + ch = channel + } + } + return if (ce.channelType == ChannelType.PRIVATE) { + true + } else { + if (ce.textChannel != ch) { + ce.reply(errorMessage(ch)) + false + } else { + if (roles.isNotEmpty()) { + val rnames = ce.member.roles.map { it.name } + if (roles.intersect(rnames).isEmpty()) { + ce.reply("You need one of these roles to execute this command: ${roles.joinToString { "`$it`" }}") + return false + } + } + check(ce) + } + } + /* + val test = ce.textChannel.name.contains("bot") + if (!test) { + ce.reply("Non music commands can only be used in the ${ce.guild.getTextChannelsByName("bot", true).first().asMention} channel") + } + + return test and check(ce)*/ + } +} + +object GeneralCategory : UnityCategory("general") + +/*val MusicCategory = Command.Category("Music Commands") { ce -> + if (ce.member.roles.firstOrNull { it.name.equals("admin", true) } != null) return@Category true + + val botExists = ce.guild.getTextChannelsByName("bot", true).firstOrNull() != null + val musicExists = ce.guild.getTextChannelsByName("music", true).firstOrNull() != null + val musicBotExists = ce.guild.getTextChannelsByName("music-bot", true).firstOrNull() != null + when { + musicBotExists -> { + val res = ce.textChannel.name == "music-bot" + + if (!res) ce.reply("Music commands are only supported in the ${ce.guild.getTextChannelsByName("music-bot", true).first().asMention} channel!") + res + } + musicExists -> { + val res = ce.textChannel.name == "music" + if (!res) ce.reply("Music commands are only supported in the ${ce.guild.getTextChannelsByName("music", true).first().asMention} channel!") + res + } + botExists -> { + val res = ce.textChannel.name == "bot" + if (!res) ce.reply("Music commands are only supported in the ${ce.guild.getTextChannelsByName("bot", true).first().asMention} channel!") + res + } + else -> true + } + +}*/ + +object MusicCategory : UnityCategory("Music Commands", listOf("bot", "music", "music-bot"), errorMessage = { "Music commands can only be used in ${it.asMention}!" }) +object MusicCategoryPrivate : UnityCategory("Music Commands", listOf("bot", "music", "music-bot"), listOf("admin"), { "Music commands can only be used in ${it.asMention}!" }) + +/* +val GeneralCategory = Command.Category("General commands") { ce -> + if (ce.member.roles.firstOrNull { it.name.equals("admin", true) } != null) return@Category true + if (ce.guild.getTextChannelsByName("bot", true).firstOrNull() == null) return@Category true + val test = ce.textChannel.name.contains("bot") + if (!test) { + ce.reply("Non music commands can only be used in the ${ce.guild.getTextChannelsByName("bot", true).first().asMention} channel") + } + + test +}*/ + + +/*val FunCategory = Command.Category("Fun Commands") { ce -> + if (ce.member.roles.firstOrNull { it.name.equals("admin", true) } != null) return@Category true + + if (ce.guild.getTextChannelsByName("bot", true).firstOrNull() == null) return@Category true + val test = ce.textChannel.name.contains("bot") + if (!test) { + ce.reply("Non music commands can only be used in the ${ce.guild.getTextChannelsByName("bot", true).first().asMention} channel") + } + + test +}*/ + +object FunCategory : UnityCategory("Fun commands") \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt index ea53053..01f5caf 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt @@ -1,6 +1,13 @@ package nl.voidcorp.dbot.commands +import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.MessageBuilder +import net.dv8tion.jda.core.entities.MessageEmbed +import nl.voidcorp.dbot.catMap +import nl.voidcorp.dbot.commands +import nl.voidcorp.dbot.emptyOr +import nl.voidcorp.dbot.random +import java.time.LocalDateTime import java.time.temporal.ChronoUnit @@ -15,4 +22,51 @@ val pingCommand = UnityCommand("ping", help = "Check the bot's ping", aliases = m.editMessage("Ping: " + ping + "ms | Websocket: " + event.jda.ping + "ms").queue() } } +val replies = listOf("Hello %%", "Why hello there %%!", "Hello there %%", "General %%. You are a bold one", "A wild %% appeared!") + +val helpCommand = UnityCommand("help", "Guess what?"/*, category = UnityCategory("Yeet", channels = listOf())*/) { event -> + val greeting = replies.random().replace("%%", event.member.effectiveName) + val eb = EmbedBuilder() + when { + event.args.isEmpty() -> { + eb.setTitle(greeting) + .appendDescription("My name is ${event.selfMember.effectiveName}, and I am definitely the best Discord bot around!\n\nUse `!help command` for a chance that I have more info about a command!") + .setColor(event.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) + val m = commands.catMap() + for (e in m.entries) { + val f = MessageEmbed.Field(e.key, e.value.asSequence().filter { it.name != "help" }.joinToString(separator = "\n", postfix = "\n") { "`!${it.name}`" }, true) + eb.addField(f) + } + eb.setThumbnail(event.selfUser.effectiveAvatarUrl) + } + event.args == "help" -> { + eb.setTitle("Ha Ha") + .appendDescription("Ha ha, very funny ${event.member.effectiveName}") + .setColor(event.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) + } + commands.any { it.name == event.args } -> { + val cmd = commands.first { it.name == event.args } + eb.setTitle("**!${cmd.name}**") + .appendDescription(cmd.help) + .setColor(event.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) + if (cmd.aliases.isNotEmpty()) eb.addField("Aliases", cmd.aliases.joinToString { "`$it`" }, true) + eb.addField("Usage", "`!${cmd.howTo.emptyOr(cmd.name)}`", true) + val cat = cmd.category + if (cat is UnityCategory) { + if (cat.roles.isNotEmpty()) + eb.addField("Roles", cat.roles.joinToString { "`$it`" }, true) + } + + } + + else -> { + eb.setTitle(greeting) + .appendDescription("I honestly have no idea what the command `${event.args}` does...") + .setColor(event.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) + } + + } + event.reply(eb.build()) + +} diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/FunCommands.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/FunCommands.kt index f147b7d..31d0b5b 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/FunCommands.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/FunCommands.kt @@ -1,7 +1,6 @@ package nl.voidcorp.dbot.commands import com.github.salomonbrys.kotson.fromJson -import com.jagrosh.jdautilities.command.Command import net.dv8tion.jda.core.EmbedBuilder import nl.voidcorp.dbot.addAll import nl.voidcorp.dbot.commands @@ -10,17 +9,8 @@ import nl.voidcorp.dbot.random import nl.voidcorp.dbot.storage.XKCD import java.time.LocalDateTime -val funCategory = Command.Category("Fun Commands") { - if (it.guild.getTextChannelsByName("bot", true).firstOrNull() == null) return@Category true - val test = it.textChannel.name.contains("bot") - if (!test) { - it.reply("Non music commands can only be used in the ${it.guild.getTextChannelsByName("bot", true).first().asMention} channel") - } - test -} - -val xkcd = UnityCommand("xkcd", help = "Fetch an xkcd comic, either a random one, or a specific one if specified", category = funCategory, arguments = "the comic number (optional)") { event -> +val xkcd = UnityCommand("xkcd", help = "Fetch an xkcd comic, either a random one, or a specific one if specified", category = FunCategory, arguments = "the comic number (optional)") { event -> val burl = "https://xkcd.com/" val eurl = "/info.0.json" val eb = EmbedBuilder().setTimestamp(LocalDateTime.now()).setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl) @@ -49,7 +39,7 @@ val xkcd = UnityCommand("xkcd", help = "Fetch an xkcd comic, either a random one event.reply(eb.build()) } -val cat = UnityCommand("cat", help = "Get a random cat image!", category = funCategory) { event -> +val cat = UnityCommand("cat", help = "Get a random cat image!", category = FunCategory) { event -> val url = "https://aws.random.cat/meow" val eb = EmbedBuilder().setTimestamp(LocalDateTime.now()).setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl) .setColor(event.selfMember.color) @@ -59,7 +49,7 @@ val cat = UnityCommand("cat", help = "Get a random cat image!", category = funCa } -val dog = UnityCommand("dog", help = "Get a random dog image!", category = funCategory) { event -> +val dog = UnityCommand("dog", help = "Get a random dog image!", category = FunCategory) { event -> val url = "https://random.dog/woof.json" val eb = EmbedBuilder().setTimestamp(LocalDateTime.now()).setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl) .setColor(event.selfMember.color) diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommand.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommand.kt index f08d790..f021d64 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommand.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommand.kt @@ -3,47 +3,12 @@ package nl.voidcorp.dbot.commands import com.jagrosh.jdautilities.command.Command import com.jagrosh.jdautilities.command.CommandEvent import nl.voidcorp.dbot.music.TrackScheduler +import nl.voidcorp.dbot.music.guildMusicMap import nl.voidcorp.dbot.playerManager -val musicCategory = Command.Category("Music Commands") { - val botExists = it.guild.getTextChannelsByName("bot", true).firstOrNull() != null - val musicExists = it.guild.getTextChannelsByName("music", true).firstOrNull() != null - val musicBotExists = it.guild.getTextChannelsByName("music-bot", true).firstOrNull() != null - when { - musicBotExists -> { - val res = it.textChannel.name == "music-bot" - - if (!res) it.reply("Music commands are only supported in the ${it.guild.getTextChannelsByName("music-bot", true).first().asMention} channel!") - res - } - musicExists -> { - val res = it.textChannel.name == "music" - if (!res) it.reply("Music commands are only supported in the ${it.guild.getTextChannelsByName("music", true).first().asMention} channel!") - res - } - botExists -> { - val res = it.textChannel.name == "bot" - if (!res) it.reply("Music commands are only supported in the ${it.guild.getTextChannelsByName("bot", true).first().asMention} channel!") - res - } - else -> true - } - -} - -val generalCategory = Command.Category("General commands") { - if (it.guild.getTextChannelsByName("bot", true).firstOrNull() == null) return@Category true - val test = it.textChannel.name.contains("bot") - if (!test) { - it.reply("Non music commands can only be used in the ${it.guild.getTextChannelsByName("bot", true).first().asMention} channel") - } - - test - -} open class UnityCommand(name: String, help: String = "", - category: Category = generalCategory, + category: UnityCategory = GeneralCategory, arguments: String = "", vararg aliases: String = arrayOf(), val howTo: String = "", val exec: (event: CommandEvent) -> Unit) : Command() { init { @@ -54,11 +19,12 @@ open class UnityCommand(name: String, help: String = "", super.aliases = aliases } + override fun execute(event: CommandEvent) = exec(event) } class UnityMusicCommand(name: String, help: String = "", - category: Category = musicCategory, + category: UnityCategory = MusicCategory, arguments: String = "", vararg aliases: String = arrayOf(name.first().toString()), howTo: String = "", val mExec: (event: CommandEvent, scheduler: TrackScheduler) -> Unit) : UnityCommand(name, help, category, arguments, *aliases, howTo = howTo, exec = {}) { diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt new file mode 100644 index 0000000..68473b4 --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt @@ -0,0 +1,289 @@ +package nl.voidcorp.dbot.commands + +import com.github.salomonbrys.kotson.fromJson +import com.jagrosh.jdautilities.command.* +import net.dv8tion.jda.core.EmbedBuilder +import net.dv8tion.jda.core.OnlineStatus +import net.dv8tion.jda.core.entities.ChannelType +import net.dv8tion.jda.core.entities.Game +import net.dv8tion.jda.core.entities.Guild +import net.dv8tion.jda.core.entities.Message +import net.dv8tion.jda.core.events.ReadyEvent +import net.dv8tion.jda.core.events.message.MessageReceivedEvent +import net.dv8tion.jda.core.hooks.ListenerAdapter +import nl.voidcorp.dbot.bot +import nl.voidcorp.dbot.gson +import nl.voidcorp.dbot.log +import nl.voidcorp.dbot.storage.GuildSettings +import java.io.File +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.util.* +import java.util.concurrent.ScheduledExecutorService +import java.util.concurrent.ScheduledThreadPoolExecutor +import java.util.function.Function + + +val gmap = mutableMapOf() + +object GSM : GuildSettingsManager { + private val f = File("settings.json") + + override fun getSettings(it: Guild): GuildSettings { + val res = gmap[it.idLong] + return if (res != null) { + res + } else { + val gm = GuildSettings() + gmap[it.idLong] = gm + gm + } + } + + override fun init() { + if (f.exists()) { + gmap.putAll(gson.fromJson(f.readText())) + } + } + + override fun shutdown() { + gson.toJson(gmap, f.bufferedWriter()) + } +} + +data class UnityCommandClient(private val prefix: String, + private val commands: MutableList = mutableListOf() +) : CommandClient, ListenerAdapter() { + private val cooldownMap = mutableMapOf() + override fun applyCooldown(name: String, seconds: Int) { + cooldownMap[name] = OffsetDateTime.now().plusSeconds(seconds.toLong()) + } + + override fun > getSettingsManager(): M? { + return null + } + + override fun getError(): String = "❌" + + override fun addAnnotatedModule(module: Any?) { + //NOP + } + + override fun addAnnotatedModule(module: Any?, mapFunction: Function?) { + //NOP + } + + override fun getServerInvite(): String? { + return null + } + + private val ses = ScheduledThreadPoolExecutor(8) + + override fun getScheduleExecutor(): ScheduledExecutorService = ses + + override fun cleanCooldowns() { + for ((k, v) in cooldownMap) { + if (v.isBefore(OffsetDateTime.now())) { + cooldownMap.remove(k) + } + } + } + + override fun getWarning(): String = "⚠️" + + override fun addCommand(command: Command) { + commands.add(command) + } + + override fun addCommand(command: Command, index: Int) { + commands.add(index, command) + } + + fun addCommands(commands: List) { + for (c in commands) { + addCommand(c) + } + } + + override fun getSettingsFor(guild: Guild): S? = null + + private fun getSettings(guild: Guild): GuildSettings = GSM.getSettings(guild) + + private var cmdListener: CommandListener? = null + override fun setListener(listener: CommandListener) { + cmdListener = listener + } + + private val start = OffsetDateTime.now() + override fun getStartTime(): OffsetDateTime = start + + + override fun getListener(): CommandListener? = cmdListener + + override fun getSuccess(): String = "✔️" + + private val usageMap = mutableMapOf() + + override fun getCommandUses(command: Command): Int = usageMap[command.name] ?: 0 + + private operator fun MutableMap.plus(t: T) { + val res = this[t] + if (res != null) { + this[t] = res + 1 + } else { + this[t] = 1 + } + } + + override fun getCommandUses(name: String): Int = usageMap[name] ?: 0 + + + override fun getCooldown(name: String): OffsetDateTime? = cooldownMap[name] + + + override fun getHelpWord(): String = "help" + + override fun shutdown() { + ses.shutdown() + GSM.shutdown() + } + + override fun removeCommand(name: String) { + commands.removeIf { it.name == name } + } + + override fun usesLinkedDeletion(): Boolean = false + + override fun getTextualPrefix(): String = prefix + + override fun getTotalGuilds(): Int = bot.guilds.size + + override fun getRemainingCooldown(name: String): Int { + val cd = cooldownMap[name] + return if (cd == null) { + 0 + } else { + (OffsetDateTime.now().toEpochSecond() - cd.toEpochSecond()).toInt() + } + + } + + override fun getCoOwnerIds(): Array { + return arrayOf() + } + + override fun getAltPrefix(): String? = null + + + override fun getPrefix(): String = prefix + + override fun getCommands(): MutableList = commands + + override fun getCoOwnerIdsLong(): LongArray = coOwnerIds.toList().map { it.toLong() }.toLongArray() + + override fun getOwnerId(): String = "168743656738521088" + override fun getOwnerIdLong(): Long = ownerId.toLong() + + private fun splitOnPrefixLength(rawContent: String, length: Int): Array { + return Arrays.copyOf(rawContent.substring(length).trim { it <= ' ' }.split("\\s+".toRegex(), 2).toTypedArray(), 2) + } + + + var unknownCommandHandler: (MessageReceivedEvent, String?) -> Unit = { event, command -> + val eb = EmbedBuilder().setTitle("Something went wrong...") + .addField("Unknown command: `$command`", "I don't know this command...", false) + .setColor(event.guild.selfMember.color).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl).setTimestamp(LocalDateTime.now()) + event.textChannel.sendMessage(eb.build()).queue() + } + + override fun onMessageReceived(event: MessageReceivedEvent) { + if (event.author.isBot) + return + + var parts: Array? = null + val rawContent = event.message.contentRaw + + val settings = getSettings(event.guild) + + + //Check for mention + if (settings.prefixes.isEmpty()) { + if (rawContent.startsWith("<@" + event.jda.selfUser.id + ">") || rawContent.startsWith("<@!" + event.jda.selfUser.id + ">")) { + parts = splitOnPrefixLength(rawContent, rawContent.indexOf(">") + 1) + } + } + + //check for default prefix if not overridden + if (rawContent.startsWith(prefix) and settings.prefixes.isEmpty()) + parts = splitOnPrefixLength(rawContent, rawContent.indexOf(prefix)) + + // Check for guild specific prefixes + if (parts == null) { + val prefixes = settings.getPrefixes() + for (prefix in prefixes) { + if (parts == null && rawContent.toLowerCase().startsWith(prefix.toLowerCase())) + parts = splitOnPrefixLength(rawContent, prefix.length) + } + } + + if (parts != null) + //starts with valid prefix + { + + if ((event.channel.type == ChannelType.PRIVATE) or event.textChannel.canTalk()) { + val name = parts[0] + val args = if (parts[1] == null) "" else parts[1] + var command: Command? // this will be null if it's not a command + command = commands.firstOrNull { it.name == name } + if (command == null) { + command = commands.firstOrNull { name in it.aliases } + } + + + if (command != null) { + val cevent = CommandEventOverride(event, args, this) + + if (cmdListener != null) + cmdListener!!.onCommand(cevent, command) + usageMap + command.name + command.run(cevent) + return // Command is done + } else { + unknownCommandHandler(event, name) + } + } + } + + + } + + private val status = OnlineStatus.ONLINE + var version = "?.?" + + private val game = Game.watching("fraud and \uD83C\uDFB5 (v$version)") + + override fun onReady(event: ReadyEvent) { + + if (!event.jda.selfUser.isBot) { + log.error("This bot can't run as a client!") + return + } + event.jda.presence.setPresence(status, + when { + game == null -> null + "default" == game.name -> Game.playing("Type ${prefix}help") + else -> game + }) + + // Start SettingsManager if necessary + GSM.init() + } + + +} + +class CommandEventOverride(event: MessageReceivedEvent, args: String?, client: UnityCommandClient) : CommandEvent(event, args, client) { + override fun linkId(message: Message?) { + + } +} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/Music.kt b/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt similarity index 96% rename from src/main/kotlin/nl/voidcorp/dbot/commands/Music.kt rename to src/main/kotlin/nl/voidcorp/dbot/music/Music.kt index 97a70c2..cf1a294 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/Music.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt @@ -1,4 +1,4 @@ -package nl.voidcorp.dbot.commands +package nl.voidcorp.dbot.music import com.jagrosh.jdautilities.command.CommandEvent import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler @@ -11,8 +11,11 @@ import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame import net.dv8tion.jda.core.audio.AudioSendHandler import nl.voidcorp.dbot.addAll import nl.voidcorp.dbot.commands +import nl.voidcorp.dbot.commands.UnityCommand +import nl.voidcorp.dbot.commands.UnityMusicCommand +import nl.voidcorp.dbot.commands.MusicCategory +import nl.voidcorp.dbot.commands.MusicCategoryPrivate import nl.voidcorp.dbot.log -import nl.voidcorp.dbot.music.TrackScheduler import nl.voidcorp.dbot.playerManager @@ -117,7 +120,7 @@ fun initMusic() { }) } - val playCommand = UnityMusicCommand("play", "Force this song to be the next!", aliases = *arrayOf("p"), howTo = "play ") { event, scheduler -> + val playCommand = UnityMusicCommand("play", "Force this song to be the next!", aliases = *arrayOf("p"), howTo = "play ", category = MusicCategoryPrivate) { event, scheduler -> if (event.args.isEmpty()) { event.reply("Please supply a song name or URL!") return@UnityMusicCommand @@ -147,7 +150,7 @@ fun initMusic() { } - val skipCommand = UnityCommand("skip", help = "Skip the current song", aliases = *arrayOf("s"), category = musicCategory) { event -> + val skipCommand = UnityCommand("skip", help = "Skip the current song", aliases = *arrayOf("s"), category = MusicCategory) { event -> val scheduler = guildMusicMap[event.guild.idLong] if (scheduler == null) { event.reply("There is no music playing?") diff --git a/src/main/kotlin/nl/voidcorp/dbot/music/TrackScheduler.kt b/src/main/kotlin/nl/voidcorp/dbot/music/TrackScheduler.kt index 4eb8770..e772a5b 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/music/TrackScheduler.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/music/TrackScheduler.kt @@ -10,8 +10,6 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.entities.* -import nl.voidcorp.dbot.commands.AudioPlayerSendHandler -import nl.voidcorp.dbot.commands.guildMusicMap import nl.voidcorp.dbot.log import java.awt.Color import java.time.LocalDateTime diff --git a/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt b/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt new file mode 100644 index 0000000..6154f2f --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt @@ -0,0 +1,9 @@ +package nl.voidcorp.dbot.storage + +import com.jagrosh.jdautilities.command.GuildSettingsProvider + +data class GuildSettings(val prefixes: MutableList = mutableListOf("!")) : GuildSettingsProvider { + override fun getPrefixes(): MutableCollection { + return prefixes + } +} \ No newline at end of file