Righto, like 7 updates in one commit

Moved categories around a bit
Moved help command
Added custom command client
Began per guild settings stuff
Added :fr00d: emoji on code blocks
Incremented version
master
Julius de Jeu 2018-10-29 15:28:58 +01:00
parent ff29659882
commit 784aa3617d
10 changed files with 488 additions and 121 deletions

View File

@ -7,7 +7,7 @@ import net.dv8tion.jda.core.hooks.ListenerAdapter
object Events : ListenerAdapter() { object Events : ListenerAdapter() {
override fun onMessageReceived(event: MessageReceivedEvent) { 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() val e = event.message.guild.getEmotesByName("fr00d", true).firstOrNull()
if (e != null) if (e != null)
event.message.addReaction(e).queue() event.message.addReaction(e).queue()

View File

@ -1,7 +1,5 @@
package nl.voidcorp.dbot 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.jdaudp.NativeAudioSendFactory
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager 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.EmbedBuilder
import net.dv8tion.jda.core.JDA import net.dv8tion.jda.core.JDA
import net.dv8tion.jda.core.JDABuilder 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.WebhookClient
import net.dv8tion.jda.webhook.WebhookClientBuilder import net.dv8tion.jda.webhook.WebhookClientBuilder
import nl.voidcorp.dbot.commands.* import nl.voidcorp.dbot.commands.*
import nl.voidcorp.dbot.music.initMusic
import nl.voidcorp.dbot.storage.GitlabWebhook import nl.voidcorp.dbot.storage.GitlabWebhook
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File import java.io.File
import java.io.FileReader import java.io.FileReader
import java.time.LocalDateTime
val playerManager = DefaultAudioPlayerManager() val playerManager = DefaultAudioPlayerManager()
val cb = CommandClientBuilder()
val log = LoggerFactory.getLogger("UnityBot") val log = LoggerFactory.getLogger("UnityBot")
@ -90,72 +84,27 @@ fun main(args: Array<String>) {
ctx.status(200).result("OK") 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) commands.addAll(helloCommand, pingCommand, helpCommand)
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)
}
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() initMusic()
initFun() 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 custom = UnityCommandClient("!")
val client = cb.build() custom.addCommands(commands)
bot = JDABuilder(args[0]).addEventListener(client).addEventListener(nl.voidcorp.dbot.Events).setAudioSendFactory(NativeAudioSendFactory()).build() custom.version = "1.4"
bot = JDABuilder(args[0]).addEventListener(custom).addEventListener(nl.voidcorp.dbot.Events).setAudioSendFactory(NativeAudioSendFactory()).build()
} }
lateinit var bot: JDA lateinit var bot: JDA

View File

@ -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<String> = listOf("bot"), val roles: List<String> = 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")

View File

@ -1,6 +1,13 @@
package nl.voidcorp.dbot.commands package nl.voidcorp.dbot.commands
import net.dv8tion.jda.core.EmbedBuilder
import net.dv8tion.jda.core.MessageBuilder 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 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() 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())
}

View File

@ -1,7 +1,6 @@
package nl.voidcorp.dbot.commands package nl.voidcorp.dbot.commands
import com.github.salomonbrys.kotson.fromJson import com.github.salomonbrys.kotson.fromJson
import com.jagrosh.jdautilities.command.Command
import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.EmbedBuilder
import nl.voidcorp.dbot.addAll import nl.voidcorp.dbot.addAll
import nl.voidcorp.dbot.commands import nl.voidcorp.dbot.commands
@ -10,17 +9,8 @@ import nl.voidcorp.dbot.random
import nl.voidcorp.dbot.storage.XKCD import nl.voidcorp.dbot.storage.XKCD
import java.time.LocalDateTime 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 burl = "https://xkcd.com/"
val eurl = "/info.0.json" val eurl = "/info.0.json"
val eb = EmbedBuilder().setTimestamp(LocalDateTime.now()).setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl) 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()) 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 url = "https://aws.random.cat/meow"
val eb = EmbedBuilder().setTimestamp(LocalDateTime.now()).setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl) val eb = EmbedBuilder().setTimestamp(LocalDateTime.now()).setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl)
.setColor(event.selfMember.color) .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 url = "https://random.dog/woof.json"
val eb = EmbedBuilder().setTimestamp(LocalDateTime.now()).setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl) val eb = EmbedBuilder().setTimestamp(LocalDateTime.now()).setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl)
.setColor(event.selfMember.color) .setColor(event.selfMember.color)

View File

@ -3,47 +3,12 @@ package nl.voidcorp.dbot.commands
import com.jagrosh.jdautilities.command.Command import com.jagrosh.jdautilities.command.Command
import com.jagrosh.jdautilities.command.CommandEvent import com.jagrosh.jdautilities.command.CommandEvent
import nl.voidcorp.dbot.music.TrackScheduler import nl.voidcorp.dbot.music.TrackScheduler
import nl.voidcorp.dbot.music.guildMusicMap
import nl.voidcorp.dbot.playerManager 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 = "", open class UnityCommand(name: String, help: String = "",
category: Category = generalCategory, category: UnityCategory = GeneralCategory,
arguments: String = "", vararg aliases: String = arrayOf(), val howTo: String = "", arguments: String = "", vararg aliases: String = arrayOf(), val howTo: String = "",
val exec: (event: CommandEvent) -> Unit) : Command() { val exec: (event: CommandEvent) -> Unit) : Command() {
init { init {
@ -54,11 +19,12 @@ open class UnityCommand(name: String, help: String = "",
super.aliases = aliases super.aliases = aliases
} }
override fun execute(event: CommandEvent) = exec(event) override fun execute(event: CommandEvent) = exec(event)
} }
class UnityMusicCommand(name: String, help: String = "", class UnityMusicCommand(name: String, help: String = "",
category: Category = musicCategory, category: UnityCategory = MusicCategory,
arguments: String = "", vararg aliases: String = arrayOf(name.first().toString()), arguments: String = "", vararg aliases: String = arrayOf(name.first().toString()),
howTo: String = "", howTo: String = "",
val mExec: (event: CommandEvent, scheduler: TrackScheduler) -> Unit) : UnityCommand(name, help, category, arguments, *aliases, howTo = howTo, exec = {}) { val mExec: (event: CommandEvent, scheduler: TrackScheduler) -> Unit) : UnityCommand(name, help, category, arguments, *aliases, howTo = howTo, exec = {}) {

View File

@ -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<Long, GuildSettings>()
object GSM : GuildSettingsManager<GuildSettings> {
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<Command> = mutableListOf()
) : CommandClient, ListenerAdapter() {
private val cooldownMap = mutableMapOf<String, OffsetDateTime>()
override fun applyCooldown(name: String, seconds: Int) {
cooldownMap[name] = OffsetDateTime.now().plusSeconds(seconds.toLong())
}
override fun <M : GuildSettingsManager<*>> getSettingsManager(): M? {
return null
}
override fun getError(): String = ""
override fun addAnnotatedModule(module: Any?) {
//NOP
}
override fun addAnnotatedModule(module: Any?, mapFunction: Function<Command, Int>?) {
//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 <T : Command> addCommands(commands: List<T>) {
for (c in commands) {
addCommand(c)
}
}
override fun <S : Any> 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<String, Int>()
override fun getCommandUses(command: Command): Int = usageMap[command.name] ?: 0
private operator fun <T> MutableMap<T, Int>.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<String> {
return arrayOf()
}
override fun getAltPrefix(): String? = null
override fun getPrefix(): String = prefix
override fun getCommands(): MutableList<Command> = 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<String?> {
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<String?>? = 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?) {
}
}

View File

@ -1,4 +1,4 @@
package nl.voidcorp.dbot.commands package nl.voidcorp.dbot.music
import com.jagrosh.jdautilities.command.CommandEvent import com.jagrosh.jdautilities.command.CommandEvent
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler 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 net.dv8tion.jda.core.audio.AudioSendHandler
import nl.voidcorp.dbot.addAll import nl.voidcorp.dbot.addAll
import nl.voidcorp.dbot.commands 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.log
import nl.voidcorp.dbot.music.TrackScheduler
import nl.voidcorp.dbot.playerManager 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 <url>") { event, scheduler -> val playCommand = UnityMusicCommand("play", "Force this song to be the next!", aliases = *arrayOf("p"), howTo = "play <url>", category = MusicCategoryPrivate) { event, scheduler ->
if (event.args.isEmpty()) { if (event.args.isEmpty()) {
event.reply("Please supply a song name or URL!") event.reply("Please supply a song name or URL!")
return@UnityMusicCommand 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] val scheduler = guildMusicMap[event.guild.idLong]
if (scheduler == null) { if (scheduler == null) {
event.reply("There is no music playing?") event.reply("There is no music playing?")

View File

@ -10,8 +10,6 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason
import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.EmbedBuilder
import net.dv8tion.jda.core.entities.* import net.dv8tion.jda.core.entities.*
import nl.voidcorp.dbot.commands.AudioPlayerSendHandler
import nl.voidcorp.dbot.commands.guildMusicMap
import nl.voidcorp.dbot.log import nl.voidcorp.dbot.log
import java.awt.Color import java.awt.Color
import java.time.LocalDateTime import java.time.LocalDateTime

View File

@ -0,0 +1,9 @@
package nl.voidcorp.dbot.storage
import com.jagrosh.jdautilities.command.GuildSettingsProvider
data class GuildSettings(val prefixes: MutableList<String> = mutableListOf("!")) : GuildSettingsProvider {
override fun getPrefixes(): MutableCollection<String> {
return prefixes
}
}