diff --git a/build.gradle b/build.gradle index 9b92b92..4bf0947 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,8 @@ dependencies { compile 'com.sedmelluq:lavaplayer:1.3.7' compile 'com.sedmelluq:jda-nas:1.0.6' compile 'khttp:khttp:0.1.0' + compile group: 'org.luaj', name: 'luaj-jse', version: '3.0.1' + } compileKotlin { diff --git a/src/main/kotlin/nl/voidcorp/dbot/Events.kt b/src/main/kotlin/nl/voidcorp/dbot/Events.kt index 9fa112f..9354760 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/Events.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/Events.kt @@ -14,18 +14,18 @@ object Events : ListenerAdapter() { if (e != null) event.message.addReaction(e).queue() } - /*if (event.message.channel.idLong == 499628388659625995) { + /*if (event.message.voiceChannel.idLong == 499628388659625995) { if (event.message.mentionedMembers.contains(event.guild.getMember(event.jda.selfUser)) and (event.message.author != event.jda.selfUser)) { if (event.message.contentStripped.toLowerCase().contains("hello")) { val i = Random.nextInt(10) if (i > 8) { - event.channel.sendMessage("Can you speak up or I'll throw you a microphone").queue() + event.voiceChannel.sendMessage("Can you speak up or I'll throw you a microphone").queue() } else { - event.channel.sendMessage("Hello, ${event.author.asMention}").queue() + event.voiceChannel.sendMessage("Hello, ${event.author.asMention}").queue() } } else { - event.channel.sendMessage("We'll discuss that later").queue() + event.voiceChannel.sendMessage("We'll discuss that later").queue() } } @@ -47,7 +47,7 @@ object Events : ListenerAdapter() { } }*/ - /*event.channel.getMessageById(499929881883181064).queue { + /*event.voiceChannel.getMessageById(499929881883181064).queue { it.editMessage("yote").queue() it.addReaction("\uD83C\uDFB5").queue() it.addReaction("\uD83D\uDCBE").queue() diff --git a/src/main/kotlin/nl/voidcorp/dbot/Util.kt b/src/main/kotlin/nl/voidcorp/dbot/Util.kt index d49228c..0a2b767 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/Util.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/Util.kt @@ -3,8 +3,7 @@ package nl.voidcorp.dbot import com.google.gson.Gson import com.google.gson.GsonBuilder import nl.voidcorp.dbot.commands.UnityCommand -import java.io.File -import java.util.* +import javax.script.ScriptEngineManager import kotlin.random.Random @@ -30,21 +29,12 @@ fun List.catMap(): Map> { fun String.emptyOr(other: String): String = if (this.isEmpty()) other else this -fun restartApplication() { - val javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java" - val currentJar = File(Events::class.java.protectionDomain.codeSource.location.toURI()) +val sem = ScriptEngineManager() +fun run(st: String, ret: String = "x", scriptEngine: String = "luaj"): Any { + val se = sem.getEngineByName(scriptEngine) + se.eval(st) + return se.get(ret) +} - /* is it a jar file? */ - if (!currentJar.name.endsWith(".jar")) - return - /* Build command: java -jar application.jar */ - val command = ArrayList() - command.add(javaBin) - command.add("-jar") - command.add(currentJar.path) - val builder = ProcessBuilder(command) - builder.start() - System.exit(0) -} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/AdminCommands.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/AdminCommands.kt index f159637..6e4992f 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/AdminCommands.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/AdminCommands.kt @@ -1,12 +1,18 @@ package nl.voidcorp.dbot.commands import nl.voidcorp.dbot.commands +import nl.voidcorp.dbot.storage.MuteInfo +import nl.voidcorp.dbot.storage.getBefore +import nl.voidcorp.dbot.storage.put import nl.voidcorp.dbot.storage.settings +import java.time.LocalDateTime fun initAdmin() { commands += SetPrefix commands += ListPrefixes commands += RemovePrefix + /*commands += MuteCommand + commands += LuaExec*/ } object SetPrefix : UnityCommand( @@ -32,5 +38,45 @@ object RemovePrefix : UnityCommand("removeprefix", "Removes a prefix", AdminCate } }) +object MuteCommand : UnityCommand("mute", "Mutes a member of this guild", AdminCategory, exec = { ce -> + println(ce.hasArgs) + println("`${ce.args}`") + val settings = ce.guild.settings() + if (ce.hasArgs) { + + val mentions = ce.message.mentionedMembers + if (mentions.isNotEmpty() and mentions.any { it.user != ce.author }) { + val muteTime = ce.args.split(">")[1].run { if (isBlank()) "10" else this }.trim() + ce.reply("The user `${mentions[0].effectiveName}` has been muted for `$muteTime` minutes!") + settings.muted.put( + LocalDateTime.now().plusMinutes(muteTime.toLong()), MuteInfo( + mentions[0].user.idLong, + mentions[0].roles + ) + ) + } + } else { + if (settings.muted.isNotEmpty()) { + ce.reply("The currently muted users are ${ce.guild.settings().muted.getBefore().map { list -> + list.map { mi -> + ce.guild.getMemberById( + mi.member + ) + }.joinToString { "`${it.effectiveName}`" } + }}") + } else { + ce.reply("There are no muted users!") + } + } +} +) + +object LuaExec : UnityCommand("luaexec", "Executes a bit of lua code", AdminCategory, exec = { ce -> + ce.message.delete().queue() + + val r = nl.voidcorp.dbot.run(ce.args, scriptEngine = "javascript") + ce.reply(r.toString()) +}) + object UnknownCommandError : Exception("yeet!") \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/Categories.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/Categories.kt index e3a4138..1d2afcc 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/Categories.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/Categories.kt @@ -42,7 +42,7 @@ open class UnityCategory( /* 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") + ce.reply("Non music commands can only be used in the ${ce.guild.getTextChannelsByName("bot", true).first().asMention} voiceChannel") } return test and check(ce)*/ @@ -61,17 +61,17 @@ object GeneralCategory : UnityCategory("general") 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!") + if (!res) ce.reply("Music commands are only supported in the ${ce.guild.getTextChannelsByName("music-bot", true).first().asMention} voiceChannel!") 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!") + if (!res) ce.reply("Music commands are only supported in the ${ce.guild.getTextChannelsByName("music", true).first().asMention} voiceChannel!") 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!") + if (!res) ce.reply("Music commands are only supported in the ${ce.guild.getTextChannelsByName("bot", true).first().asMention} voiceChannel!") res } else -> true @@ -112,7 +112,7 @@ val GeneralCategory = Command.Category("General commands") { ce -> 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") + ce.reply("Non music commands can only be used in the ${ce.guild.getTextChannelsByName("bot", true).first().asMention} voiceChannel") } test @@ -125,7 +125,7 @@ val GeneralCategory = Command.Category("General commands") { ce -> 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") + ce.reply("Non music commands can only be used in the ${ce.guild.getTextChannelsByName("bot", true).first().asMention} voiceChannel") } test diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt index 9956405..85b78c5 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt @@ -2,6 +2,7 @@ package nl.voidcorp.dbot.commands import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.MessageBuilder +import net.dv8tion.jda.core.entities.ChannelType import net.dv8tion.jda.core.entities.MessageEmbed import nl.voidcorp.dbot.catMap import nl.voidcorp.dbot.commands @@ -24,16 +25,30 @@ val helloCommand = UnityCommand("hello", "Say hello to Andy!", aliases = *arrayO val pingCommand = UnityCommand("ping", help = "Check the bot's ping", aliases = *arrayOf("pong"), cooldown = 10) { event -> - event.reply("Ping: ...") { m -> - val ping = event.message.creationTime.until(m.creationTime, ChronoUnit.MILLIS) - m.editMessage("Ping: " + ping + "ms | Websocket: " + event.jda.ping + "ms").queue() + event.reply("Ping: ...") { m -> + val ping = event.message.creationTime.until(m.creationTime, ChronoUnit.MILLIS) + 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 -> + UnityCommand("help", "Guess what?", category = object : UnityCategory("hidden") { + override fun test(ce: UnityCommandEvent): Boolean { + val s = (ce.channelType == ChannelType.TEXT) and (ce.textChannel!!.name.toLowerCase().run { + contains("bot") or (ce.guild.textChannels.none { + it.name.contains( + "music-bot" + ) + } and contains("music")) + }) + if (!s) { + ce.reply("This command can only be used in music and bot channels!") + } + return s + } + }) { event -> val greeting = replies.random().replace("%%", event.member.effectiveName) val eb = EmbedBuilder() when { diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt index fa77297..4229d58 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt @@ -19,6 +19,7 @@ import java.time.LocalDateTime import java.time.OffsetDateTime import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledThreadPoolExecutor +import kotlin.concurrent.fixedRateTimer import kotlin.math.absoluteValue @@ -26,10 +27,11 @@ val gmap = mutableMapOf() object GSM { private val f = File("settings.json") - + private var lastHC = -1 fun getSettings(it: Guild): GuildSettings { val res = gmap[it.idLong] + return if (res != null) { res } else { @@ -37,6 +39,7 @@ object GSM { gmap[it.idLong] = gm gm } + } fun init() { @@ -47,6 +50,14 @@ object GSM { } catch (ex: IllegalStateException) { } } + fixedRateTimer("FileSaveThing", period = 1000 * 30) { + if (lastHC != gmap.hashCode()) { + lastHC = gmap.hashCode() + val br = f.bufferedWriter() + gson.toJson(gmap, br) + br.close() + } + } } fun shutdown() { @@ -241,8 +252,9 @@ data class UnityCommandClient( } fun onException(t: Throwable) { - val channel = bot.getPrivateChannelById("501009066479452170") - channel.sendMessage("There was an error: ${t.message}").queue() + t.printStackTrace() + /*val voiceChannel = bot.getPrivateChannelById("501009066479452170") + voiceChannel.sendMessage("There was an error: ${t.message}").queue()*/ } diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandEvent.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandEvent.kt index 4a535d1..6caabf5 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandEvent.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandEvent.kt @@ -74,4 +74,7 @@ class UnityCommandEvent( val author: User get() = event.author + val hasArgs: Boolean + get() = args.isNotBlank() + } \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt b/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt index 63490fb..79ef897 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt @@ -10,7 +10,10 @@ 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.* +import nl.voidcorp.dbot.commands.MusicCategoryPrivate +import nl.voidcorp.dbot.commands.UnityCommand +import nl.voidcorp.dbot.commands.UnityCommandEvent +import nl.voidcorp.dbot.commands.UnityMusicCommand import nl.voidcorp.dbot.log import nl.voidcorp.dbot.playerManager @@ -168,10 +171,10 @@ fun initMusic() { val skipCommand = UnityCommand( - "skip", - help = "Skip the current song", - aliases = *arrayOf("s"), - category = MusicCategory + "fskip", + help = "Force skips the current song, admin only", + aliases = *arrayOf("fs", "ffs"), + category = MusicCategoryPrivate ) { event -> val scheduler = guildMusicMap[event.guild.idLong] if (scheduler == null) { @@ -181,6 +184,21 @@ fun initMusic() { } } + val voteSkipCommand = UnityMusicCommand( + "vskip", + help = "Starts a vote to skip the current song", + aliases = *arrayOf("voteskip", "skip", "vs", "s") + + ) { event, scheduler -> + val ss = scheduler.shouldSkip() + if (ss) { + event.reply("Vote passed, skipping song!") + scheduler.skip() + } else { + event.reply("Vote registered!") + } + } + val npCommand = UnityMusicCommand( "nowplaying", aliases = *arrayOf("np"), @@ -233,7 +251,16 @@ fun initMusic() { } - commands.addAll(playCommand, skipCommand, queueCommand, ytCommand, soundcloudCommand, npCommand, attachmentPlay) + commands.addAll( + playCommand, + skipCommand, + queueCommand, + ytCommand, + soundcloudCommand, + npCommand, + attachmentPlay, + voteSkipCommand + ) } fun getLinkFromSearch( diff --git a/src/main/kotlin/nl/voidcorp/dbot/music/TrackScheduler.kt b/src/main/kotlin/nl/voidcorp/dbot/music/TrackScheduler.kt index e772a5b..408a010 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/music/TrackScheduler.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/music/TrackScheduler.kt @@ -15,9 +15,10 @@ import java.awt.Color import java.time.LocalDateTime import java.util.* import kotlin.concurrent.timerTask +import kotlin.math.roundToInt -class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceChannel) : AudioEventAdapter() { +class TrackScheduler(val player: AudioPlayer, val guild: Guild, val voiceChannel: VoiceChannel) : AudioEventAdapter() { val musicChannel: TextChannel init { @@ -26,13 +27,13 @@ class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceCh val audio = guild.audioManager audio.sendingHandler = AudioPlayerSendHandler(player) - audio.openAudioConnection(channel) + audio.openAudioConnection(voiceChannel) musicChannel = guild.getTextChannelsByName("music-bot", true).firstOrNull() ?: (guild.getTextChannelsByName("music", true).firstOrNull() - ?: (guild.getTextChannelsByName("bot", true).firstOrNull() - ?: (guild.getTextChannelsByName("general", true).firstOrNull() - ?: guild.defaultChannel!!))) + ?: (guild.getTextChannelsByName("bot", true).firstOrNull() + ?: (guild.getTextChannelsByName("general", true).firstOrNull() + ?: guild.defaultChannel!!))) } @@ -44,6 +45,7 @@ class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceCh }*/ override fun onTrackEnd(player: AudioPlayer, track: AudioTrack, endReason: AudioTrackEndReason) { + pressedSkip++ if (q.isNotEmpty()) { player.playTrack(q.poll()) } else { @@ -117,7 +119,11 @@ class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceCh if (endReason != AudioTrackEndReason.REPLACED) { guildMusicMap.remove(guild.idLong) - musicChannel.sendMessage(EmbedBuilder().setColor(musicChannel.guild.selfMember.color).setTitle("I'm done here").setDescription("There are no more songs left in the queue.").setTimestamp(LocalDateTime.now()).build()).queue() + musicChannel.sendMessage( + EmbedBuilder().setColor(musicChannel.guild.selfMember.color).setTitle("I'm done here").setDescription( + "There are no more songs left in the queue." + ).setTimestamp(LocalDateTime.now()).build() + ).queue() Timer().schedule(timerTask { guild.audioManager.closeAudioConnection() @@ -132,42 +138,62 @@ class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceCh if (track is YoutubeAudioTrack) { if (track.userData is Member) return EmbedBuilder() - .setFooter("Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) - .user.effectiveAvatarUrl).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) - .setThumbnail("https://img.youtube.com/vi/${track.info.identifier}/hqdefault.jpg") - .setTimestamp(LocalDateTime.now()).setColor(Color.decode("#ff0000")).build() + .setFooter( + "Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) + .user.effectiveAvatarUrl + ).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) + .setThumbnail("https://img.youtube.com/vi/${track.info.identifier}/hqdefault.jpg") + .setTimestamp(LocalDateTime.now()).setColor(Color.decode("#ff0000")).build() } else if (track is SoundCloudAudioTrack) { val scsm = track.sourceManager as SoundCloudAudioSourceManager scsm.updateClientId() - val art = khttp.get("http://api.soundcloud.com/tracks/${track.info.identifier}?client_id=${scsm.clientId}", headers = mapOf("Content-Type" to "application/json")).jsonObject["artwork_url"].toString().replace("large", "t300x300") + val art = khttp.get( + "http://api.soundcloud.com/tracks/${track.info.identifier}?client_id=${scsm.clientId}", + headers = mapOf("Content-Type" to "application/json") + ).jsonObject["artwork_url"].toString().replace("large", "t300x300") if (track.userData is Member) return EmbedBuilder() - .setFooter("Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) - .user.effectiveAvatarUrl).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) - .setThumbnail(if (art == "null") null else art) - .setTimestamp(LocalDateTime.now()).setColor(Color.decode("#ff5500")).build() + .setFooter( + "Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) + .user.effectiveAvatarUrl + ).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) + .setThumbnail(if (art == "null") null else art) + .setTimestamp(LocalDateTime.now()).setColor(Color.decode("#ff5500")).build() } else if (track is HttpAudioTrack) { if (track.userData is Member) return EmbedBuilder() - .setFooter("Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) - .user.effectiveAvatarUrl).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) - .setTimestamp(LocalDateTime.now()).setColor(Color.decode("#005A9C")).build() + .setFooter( + "Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) + .user.effectiveAvatarUrl + ).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) + .setTimestamp(LocalDateTime.now()).setColor(Color.decode("#005A9C")).build() } return EmbedBuilder() - .setFooter("Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) - .user.effectiveAvatarUrl).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) - .setTimestamp(LocalDateTime.now()).setColor(musicChannel.guild.selfMember.color).build() + .setFooter( + "Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) + .user.effectiveAvatarUrl + ).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) + .setTimestamp(LocalDateTime.now()).setColor(musicChannel.guild.selfMember.color).build() } fun getTrackList(member: Member): MessageEmbed { - return EmbedBuilder().setTitle("Hey ${member.effectiveName}, here is the playlist").setTimestamp(LocalDateTime.now()).setColor(musicChannel.guild.selfMember.color) - .setFooter("Requested by ${member.effectiveName}", member.user.effectiveAvatarUrl).setDescription( - "**${player.playingTrack.info.title}**, requested by ${if (player.playingTrack.userData is Member) (player.playingTrack.userData as Member).effectiveName else "someone unknown..."} (*now playing*)\n" + - q.joinToString(separator = "\n") { "**${it.info.title}**, requested by ${if (it.userData is Member) (it.userData as Member).effectiveName else "someone unknown..."}" } - ).build() + return EmbedBuilder().setTitle("Hey ${member.effectiveName}, here is the playlist") + .setTimestamp(LocalDateTime.now()).setColor(musicChannel.guild.selfMember.color) + .setFooter("Requested by ${member.effectiveName}", member.user.effectiveAvatarUrl).setDescription( + "**${player.playingTrack.info.title}**, requested by ${if (player.playingTrack.userData is Member) (player.playingTrack.userData as Member).effectiveName else "someone unknown..."} (*now playing*)\n" + + q.joinToString(separator = "\n") { "**${it.info.title}**, requested by ${if (it.userData is Member) (it.userData as Member).effectiveName else "someone unknown..."}" } + ).build() + } + + var pressedSkip = 0 + + fun shouldSkip(): Boolean { + val half = (voiceChannel.members.size.run { this - 1 }.toDouble() / 2).roundToInt() + val press = ++pressedSkip + return press >= half } } diff --git a/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt b/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt index a9f6b6e..e3d5cbf 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt @@ -1,17 +1,35 @@ package nl.voidcorp.dbot.storage import net.dv8tion.jda.core.entities.Guild +import net.dv8tion.jda.core.entities.Role import nl.voidcorp.dbot.commands.GSM +import java.time.LocalDateTime -data class GuildSettings(val prefixes: MutableList = mutableListOf()) { +data class GuildSettings( + val prefixes: MutableList = mutableListOf(), + val muted: MutableMap> = mutableMapOf() +) { fun getPrefixes(): MutableCollection { return prefixes } val primaryPrefix: String get() = prefixes.firstOrNull() ?: "!" + } fun Guild.settings(): GuildSettings { return GSM.getSettings(this) +} + +data class MuteInfo(val member: Long, val roles: List) + +fun Map.getBefore(test: LocalDateTime = LocalDateTime.now()): List = + this.filter { it.key.isBefore(test) }.map { it.value } + +fun MutableMap>.put(a: LocalDateTime, b: A) { + if (this[a] == null) { + this[a] = mutableListOf() + } + this[a]!! += b } \ No newline at end of file