package nl.voidcorp.dbot.commands import com.github.salomonbrys.kotson.fromJson 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.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.CommandString import nl.voidcorp.dbot.storage.GuildSettings import java.io.File import java.time.LocalDateTime import java.time.OffsetDateTime import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledThreadPoolExecutor import kotlin.math.absoluteValue val gmap = mutableMapOf() object GSM { private val f = File("settings.json") fun getSettings(it: Guild): GuildSettings { val res = gmap[it.idLong] return if (res != null) { res } else { val gm = GuildSettings() gmap[it.idLong] = gm gm } } fun init() { if (f.exists()) { try { val m = gson.fromJson>(f.readText()) gmap.putAll(m) } catch (ex: IllegalStateException) { } } } fun shutdown() { gson.toJson(gmap, f.bufferedWriter()) } } data class UnityCommandClient( private val prefix: String, private val commands: MutableList = mutableListOf() ) : ListenerAdapter() { private val cooldownMap = mutableMapOf() fun applyCooldown(name: String, seconds: Int) { cooldownMap[name] = LocalDateTime.now().plusSeconds(seconds.toLong()) } fun getRemainingCooldown(name: String): Int { val cd = cooldownMap[name] return if (cd == null) { 0 } else { (LocalDateTime.now().second - cd.second).absoluteValue } } fun isOnCooldown(name: String): Boolean { val cooldown: Boolean? = LocalDateTime.now().isBefore(cooldownMap[name] ?: LocalDateTime.MIN) return cooldown ?: false } fun cleanCooldowns() { for ((k, v) in cooldownMap) { if (v.isBefore(LocalDateTime.now())) { cooldownMap.remove(k) } } } fun getError(): String = "❌" fun getServerInvite(): String { return "" } private val ses = ScheduledThreadPoolExecutor(8) fun getScheduleExecutor(): ScheduledExecutorService = ses fun getWarning(): String = "⚠️" fun addCommand(command: UnityCommand) { commands.add(command) } fun addCommand(command: UnityCommand, index: Int) { commands.add(index, command) } fun addCommands(commands: List) { for (c in commands) { addCommand(c) } } private fun getSettings(guild: Guild): GuildSettings = GSM.getSettings(guild) private val start = OffsetDateTime.now() fun getStartTime(): OffsetDateTime = start fun getSuccess(): String = "✔️" private val usageMap = mutableMapOf() private operator fun MutableMap.plus(t: T) { val res = this[t] if (res != null) { this[t] = res + 1 } else { this[t] = 1 } } fun getCommandUses(name: String): Int = usageMap[name] ?: 0 fun shutdown() { ses.shutdown() GSM.shutdown() } fun usesLinkedDeletion(): Boolean = false fun getTextualPrefix(): String = prefix fun getTotalGuilds(): Int = bot.guilds.size val ownerId = "168743656738521088" fun getOwnerIdLong(): Long = ownerId.toLong() private fun splitOnPrefixLength(rawContent: String, length: Int): CommandString { val m = rawContent.substring(length).trim { it <= ' ' }.split("\\s+".toRegex(), 2) val cmds = if (m.size == 2) { CommandString(m[0], m[1]) } else { CommandString(m[0]) } return cmds } 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 commandString: CommandString? = null val rawContent = event.message.contentRaw val settings = getSettings(event.guild) //Check for mention if (rawContent.startsWith("<@" + event.jda.selfUser.id + ">") || rawContent.startsWith("<@!" + event.jda.selfUser.id + ">")) { commandString = splitOnPrefixLength(rawContent, rawContent.indexOf(">") + 1) } //check for default prefix if not overridden if (rawContent.startsWith(prefix) and settings.prefixes.isEmpty()) commandString = splitOnPrefixLength(rawContent, prefix.length) // Check for guild specific prefixes if (commandString == null) { val prefixes = settings.getPrefixes() for (prefix in prefixes) { if (commandString == null && rawContent.toLowerCase().startsWith(prefix.toLowerCase())) commandString = splitOnPrefixLength(rawContent, prefix.length) } } if (commandString != null) //starts with valid prefix { if ((event.channel.type == ChannelType.PRIVATE) or event.textChannel.canTalk()) { var command: UnityCommand?// this will be null if it's not a command command = commands.firstOrNull { it.name == commandString.command } if (command == null) { command = commands.firstOrNull { commandString.command in it.aliases } } if (command != null) { val cevent = UnityCommandEvent(event, commandString.args, this) /*if (cmdListener != null) cmdListener!!.onCommand(cevent, command)*/ usageMap + command.name try { command.run(cevent) } catch (ex: UnknownCommandError) { unknownCommandHandler(event, commandString.command) } return // Command is done } else { unknownCommandHandler(event, commandString.command) } } } } fun onException(t: Throwable) { val channel = bot.getPrivateChannelById("501009066479452170") channel.sendMessage("There was an error: ${t.message}").queue() } private val status = OnlineStatus.ONLINE var version = "?.?" set(value) { game = Game.watching("fraud and \uD83C\uDFB5 (v$value)") } private var game: 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, game ) // Start SettingsManager if necessary GSM.init() } }