From 28dd85db0b317ef41ccd0dcb34aab32bf545c3e5 Mon Sep 17 00:00:00 2001 From: Julius de Jeu Date: Mon, 5 Nov 2018 22:10:19 +0100 Subject: [PATCH] add role command remove code block fraud thingie --- src/main/kotlin/nl/voidcorp/dbot/Events.kt | 2 +- src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt | 7 +- .../voidcorp/dbot/commands/AdminCommands.kt | 29 +++++++ .../nl/voidcorp/dbot/commands/Commands.kt | 84 ++++++++++++++++++- .../kotlin/nl/voidcorp/dbot/commands/GSM.kt | 48 +++++++++++ .../nl/voidcorp/dbot/commands/UnityCommand.kt | 6 +- .../dbot/commands/UnityCommandClient.kt | 77 +++-------------- .../kotlin/nl/voidcorp/dbot/music/Music.kt | 34 +++++--- .../nl/voidcorp/dbot/storage/GuildSettings.kt | 4 +- 9 files changed, 198 insertions(+), 93 deletions(-) create mode 100644 src/main/kotlin/nl/voidcorp/dbot/commands/GSM.kt diff --git a/src/main/kotlin/nl/voidcorp/dbot/Events.kt b/src/main/kotlin/nl/voidcorp/dbot/Events.kt index 9354760..b008251 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") or event.message.contentRaw.contains(Regex("`(\\w+|\\s+|\\W)+`"))) + if ((event.message.contentStripped.toLowerCase().contains("fraud")) and (event.author != event.jda.selfUser) ) { val e = event.message.guild.getEmotesByName("fr00d", true).firstOrNull() diff --git a/src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt b/src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt index 35fc883..69af13f 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/UnityBot.kt @@ -9,7 +9,6 @@ import net.dv8tion.jda.core.JDABuilder import nl.voidcorp.dbot.commands.* import nl.voidcorp.dbot.music.initMusic import org.slf4j.LoggerFactory -import kotlin.concurrent.thread val playerManager = DefaultAudioPlayerManager() @@ -25,7 +24,7 @@ fun main(args: Array) { playerManager.registerSourceManager(SoundCloudAudioSourceManager(true)) - commands.addAll(helloCommand, pingCommand, helpCommand) + commands.addAll(helloCommand, pingCommand, helpCommand, joinRoleCommand, removeRoleCommand) initMusic() @@ -41,9 +40,9 @@ fun main(args: Array) { bot = JDABuilder(args[0]).addEventListener(custom).addEventListener(nl.voidcorp.dbot.Events) .setAudioSendFactory(NativeAudioSendFactory()).build() - Runtime.getRuntime().addShutdownHook(thread(start = false) { + /*Runtime.getRuntime().addShutdownHook(thread(start = false) { custom.shutdown() - }) + })*/ } diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/AdminCommands.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/AdminCommands.kt index 6e4992f..3d091db 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/AdminCommands.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/AdminCommands.kt @@ -11,6 +11,7 @@ fun initAdmin() { commands += SetPrefix commands += ListPrefixes commands += RemovePrefix + commands += AddRoleCommand /*commands += MuteCommand commands += LuaExec*/ } @@ -71,6 +72,34 @@ object MuteCommand : UnityCommand("mute", "Mutes a member of this guild", AdminC } ) +object AddRoleCommand : UnityCommand( + "addrole", + "Add a role to the Role picker", + AdminCategory, + howTo = "addrole Rolename,rolekey", + exec = { ce -> + val args = ce.args.split(",").map { it.trim() } + if (args.size != 2) { + ce.reply("Ehm, that is not how this is supposed to work, the args have to be `Rolename,rolekey`\nWith Rolename the actual name in discord and rolekey the key you want to assign.") + + } else { + val gs = GSM.getSettings(ce.guild) + val role = ce.guild.getRolesByName(args[0], true).firstOrNull() + val key = args[1] + if (role == null) { + ce.reply("Ehm, that is not how this is supposed to work, the args have to be `Rolename,rolekey`\nWith Rolename the actual name in discord and rolekey the key you want to assign.") + ce.reply("Also, the discord role you provided is not existing?") + } else { + if (gs.roleMap.containsKey(key)) { + ce.reply("First remove the key $key and then add it again, this is to prevent accidental overrides...") + } else { + gs.roleMap[key] = role.idLong + ce.reply("Added role ${role.name} with key `$key`") + } + } + } + }) + object LuaExec : UnityCommand("luaexec", "Executes a bit of lua code", AdminCategory, exec = { ce -> ce.message.delete().queue() diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt index 85b78c5..f065d77 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/Commands.kt @@ -4,6 +4,7 @@ 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 net.dv8tion.jda.core.managers.GuildController import nl.voidcorp.dbot.catMap import nl.voidcorp.dbot.commands import nl.voidcorp.dbot.emptyOr @@ -13,7 +14,7 @@ import java.time.temporal.ChronoUnit import kotlin.random.Random -val helloCommand = UnityCommand("hello", "Say hello to Andy!", aliases = *arrayOf()) { +val helloCommand = UnityCommand("hello", "Say hello to Andy!") { val i = Random.nextInt(10) if (i > 8) { it.reply("Can you speak up or I'll throw you a microphone") @@ -24,7 +25,7 @@ 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 -> + UnityCommand("ping", help = "Check the bot's ping", aliases = mutableListOf("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() @@ -36,6 +37,8 @@ val replies = val helpCommand = UnityCommand("help", "Guess what?", category = object : UnityCategory("hidden") { override fun test(ce: UnityCommandEvent): Boolean { + 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 val s = (ce.channelType == ChannelType.TEXT) and (ce.textChannel!!.name.toLowerCase().run { contains("bot") or (ce.guild.textChannels.none { it.name.contains( @@ -56,7 +59,7 @@ val helpCommand = val prefix = GSM.getSettings(event.guild).primaryPrefix eb.setTitle(greeting) - .appendDescription("My name is ${event.selfMember.effectiveName}, and I am definitely the best Discord bot around!\n\nUse `${prefix}help command` for a chance that I have more info about a command!") + .appendDescription("My name is OttoBot, and I am definitely the best Discord bot around!\n\nUse `${prefix}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()) @@ -89,7 +92,11 @@ val helpCommand = .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) + eb.addField( + "Usage", + "`${GSM.getSettings(event.guild).primaryPrefix}${cmd.howTo.emptyOr(cmd.name)}`", + true + ) val cat = cmd.category if (cat.roles.isNotEmpty()) eb.addField("Roles", cat.roles.joinToString { "`$it`" }, true) @@ -109,3 +116,72 @@ val helpCommand = } +val joinRoleCommand = UnityCommand( + "role", + "Join the role specified, use without parameters for a list!", + aliases = mutableListOf("joinrole", "jr") +) { ce -> + val gm = GSM.getSettings(ce.guild) + val eb = EmbedBuilder().setColor(ce.selfMember.color) + .setFooter("Requested by ${ce.member.effectiveName}", ce.author.effectiveAvatarUrl) + .setTimestamp(LocalDateTime.now()) + if (!ce.hasArgs) { + val field = MessageEmbed.Field( + "Roles", + gm.roleMap.entries.map { it.key to ce.guild.getRoleById(it.value)!! }.joinToString { "`${it.first}`: ${it.second.name}" }, + false + ) + eb.addField(field) + eb.setTitle("Here's a list of all this servers roles, ${ce.member.effectiveName}!") + } else { + if (!gm.roleMap.containsKey(ce.args)) { + eb.setTitle("There was an error") + eb.setDescription("This role does not exist?\nUse `${gm.primaryPrefix}joinrole` to find the available roles!") + } else { + val id = gm.roleMap[ce.args]!! + val r = ce.guild.getRoleById(id)!! + GuildController(ce.guild).addSingleRoleToMember(ce.member, r).queue() + eb.setTitle("Have fun with your new role!") + eb.setDescription("I have given you the role ${r.name}!") + } + } + ce.reply(eb.build()) +} + +val removeRoleCommand = + UnityCommand("removerole", "Remove the role specified, if you have it!", aliases = mutableListOf("rr")) { ce -> + val gm = GSM.getSettings(ce.guild) + val eb = EmbedBuilder().setColor(ce.selfMember.color) + .setFooter("Requested by ${ce.member.effectiveName}", ce.author.effectiveAvatarUrl) + .setTimestamp(LocalDateTime.now()) + if (!ce.hasArgs) { + val roles = gm.roleMap.map { it.key to ce.guild.getRoleById(it.value)!! } + .filter { ce.member.roles.contains(it.second) } + + val field = MessageEmbed.Field( + "Roles", + roles.joinToString { "`${it.first}`: ${it.second.name}" }, + false + ) + eb.addField(field) + eb.setTitle("Here's a list of all your removable roles, ${ce.member.effectiveName}!") + } else { + if (!gm.roleMap.containsKey(ce.args)) { + eb.setTitle("There was an error") + eb.setDescription("This role does not exist?\nUse `${gm.primaryPrefix}removerole` to find the removable roles!") + } else { + val id = gm.roleMap[ce.args]!! + val r = ce.guild.getRoleById(id)!! + + if (ce.member.roles.contains(r)) { + GuildController(ce.guild).removeSingleRoleFromMember(ce.member, r).queue() + eb.setTitle("Have fun (?) without the role?") + eb.setDescription("I have removed the role ${r.name}!") + } else { + eb.setTitle("Yeah this wont work don't you think?") + eb.setDescription("You need to have the role you are trying to remove to be able to remove it...\nHonestly what did you expect?") + } + } + } + ce.reply(eb.build()) + } \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/GSM.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/GSM.kt new file mode 100644 index 0000000..4c71889 --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/GSM.kt @@ -0,0 +1,48 @@ +package nl.voidcorp.dbot.commands + +import com.github.salomonbrys.kotson.fromJson +import net.dv8tion.jda.core.entities.Guild +import nl.voidcorp.dbot.gson +import nl.voidcorp.dbot.storage.GuildSettings +import java.io.File +import kotlin.concurrent.fixedRateTimer + + +object GSM { + private val f = File("settings.json") + private var lastHC = -1 + private val gmap = mutableMapOf() + + 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) { + } + + } + fixedRateTimer("FileSaveThing", period = 1000 * 30, initialDelay = 1000 * 30) { + if (lastHC != gmap.hashCode()) { + lastHC = gmap.hashCode() + val br = f.bufferedWriter() + gson.toJson(gmap, br) + br.close() + } + } + + } +} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommand.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommand.kt index 19b35ea..206b91b 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommand.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommand.kt @@ -13,7 +13,7 @@ enum class CooldownType { open class UnityCommand( val name: String, val help: String = "", val category: UnityCategory = GeneralCategory, - val arguments: String = "", vararg val aliases: String = arrayOf(), val howTo: String = "", + val arguments: String = "", val aliases: MutableList = mutableListOf(), val howTo: String = "", val cooldown: Int = 0, val cooldownType: CooldownType = CooldownType.USER, val exec: (event: UnityCommandEvent) -> Unit ) /*: Command()*/ { @@ -58,10 +58,10 @@ open class UnityCommand( class UnityMusicCommand( name: String, help: String = "", category: UnityCategory = MusicCategory, - arguments: String = "", vararg aliases: String = arrayOf(name.first().toString()), + arguments: String = "", aliases: MutableList = mutableListOf(name.first().toString()), howTo: String = "", val mExec: (event: UnityCommandEvent, scheduler: TrackScheduler) -> Unit -) : UnityCommand(name, help, category, arguments, *aliases, howTo = howTo, exec = {}) { +) : UnityCommand(name, help, category, arguments, aliases, howTo = howTo, exec = {}) { override fun execute(event: UnityCommandEvent) { val scheduler = if (guildMusicMap.containsKey(event.guild.idLong)) guildMusicMap[event.guild.idLong]!! else { val channel = event.guild.voiceChannels.firstOrNull { it.members.contains(event.member) } diff --git a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt index 4229d58..699c82b 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/commands/UnityCommandClient.kt @@ -1,6 +1,5 @@ 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 @@ -10,61 +9,14 @@ 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.concurrent.fixedRateTimer import kotlin.math.absoluteValue -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 { - 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) { - } - } - fixedRateTimer("FileSaveThing", period = 1000 * 30) { - if (lastHC != gmap.hashCode()) { - lastHC = gmap.hashCode() - val br = f.bufferedWriter() - gson.toJson(gmap, br) - br.close() - } - } - } - - fun shutdown() { - gson.toJson(gmap, f.bufferedWriter()) - } -} - data class UnityCommandClient( private val prefix: String, private val commands: MutableList = mutableListOf() @@ -107,11 +59,6 @@ data class UnityCommandClient( return "" } - private val ses = ScheduledThreadPoolExecutor(8) - - fun getScheduleExecutor(): ScheduledExecutorService = ses - - fun getWarning(): String = "⚠️" fun addCommand(command: UnityCommand) { @@ -153,12 +100,6 @@ data class UnityCommandClient( fun getCommandUses(name: String): Int = usageMap[name] ?: 0 - fun shutdown() { - ses.shutdown() - GSM.shutdown() - } - - fun usesLinkedDeletion(): Boolean = false fun getTextualPrefix(): String = prefix @@ -181,12 +122,14 @@ data class UnityCommandClient( 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() + if (event.textChannel.name.contains("bot")) { + 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) { @@ -219,8 +162,8 @@ data class UnityCommandClient( } } - if (commandString != null) - //starts with valid prefix + if ((commandString != null) && (commandString.command.isNotBlank())) + //starts with valid prefix and is not blank { if ((event.channel.type == ChannelType.PRIVATE) or event.textChannel.canTalk()) { var command: UnityCommand?// this will be null if it's not a command diff --git a/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt b/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt index 79ef897..22d5e67 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/music/Music.kt @@ -25,8 +25,8 @@ fun initMusic() { val queueCommand = UnityMusicCommand( - "queue", - aliases = *arrayOf("q"), + "play", + aliases = mutableListOf("p", "queue", "q"), help = "Use this command to queue a song, if you don't add a link it will search on youtube with the specified arguments\n\nExecute with no arguments to view the current queue!", howTo = "q [link]" ) { event, scheduler -> @@ -67,7 +67,7 @@ fun initMusic() { val ytCommand = UnityMusicCommand( "youtube", - aliases = *arrayOf("yt"), + aliases = mutableListOf("yt"), help = "Search YouTube for a song!", howTo = "youtube " ) { event, scheduler -> @@ -102,7 +102,7 @@ fun initMusic() { val soundcloudCommand = UnityMusicCommand( "soundcloud", help = "Play a song via SoundCloud!", - aliases = *arrayOf("sc"), + aliases = mutableListOf("sc"), howTo = "sc " ) { event, scheduler -> if (event.args.isEmpty()) { @@ -135,9 +135,9 @@ fun initMusic() { } val playCommand = UnityMusicCommand( - "play", + "fplay", "Force this song to be the next!", - aliases = *arrayOf("p"), + aliases = mutableListOf("fp"), howTo = "play ", category = MusicCategoryPrivate ) { event, scheduler -> @@ -152,6 +152,8 @@ fun initMusic() { override fun trackLoaded(track: AudioTrack) { scheduler.insertFront(track, event.member) + if (!scheduler.isQueueEmpty()) + scheduler.skip() } override fun noMatches() { @@ -173,7 +175,7 @@ fun initMusic() { val skipCommand = UnityCommand( "fskip", help = "Force skips the current song, admin only", - aliases = *arrayOf("fs", "ffs"), + aliases = mutableListOf("fs", "ffs"), category = MusicCategoryPrivate ) { event -> val scheduler = guildMusicMap[event.guild.idLong] @@ -187,7 +189,7 @@ fun initMusic() { val voteSkipCommand = UnityMusicCommand( "vskip", help = "Starts a vote to skip the current song", - aliases = *arrayOf("voteskip", "skip", "vs", "s") + aliases = mutableListOf("voteskip", "skip", "vs", "s") ) { event, scheduler -> val ss = scheduler.shouldSkip() @@ -201,7 +203,7 @@ fun initMusic() { val npCommand = UnityMusicCommand( "nowplaying", - aliases = *arrayOf("np"), + aliases = mutableListOf("np"), help = "Show the currently playing song" ) { event, scheduler -> if (!scheduler.isSongPlaying()) { @@ -215,7 +217,7 @@ fun initMusic() { val attachmentPlay = UnityMusicCommand( "attachment", help = "Play any attached song, if it is in a normal format that is...\n\n`just drag and drop the song on your Discord window and in the optional comment add !attach(ment)`", - aliases = *arrayOf("attach") + aliases = mutableListOf("attach") ) { event, scheduler -> val attach = event.message.attachments.firstOrNull() if (attach == null) { @@ -277,8 +279,11 @@ fun getLinkFromSearch( } override fun trackLoaded(track: AudioTrack) { - if (shouldInsertFront) + if (shouldInsertFront) { scheduler.insertFront(track, event.member) + if (!scheduler.isQueueEmpty()) + scheduler.skip() + } else scheduler.queue(track, event.member) /*event.reply( @@ -296,9 +301,12 @@ fun getLinkFromSearch( override fun playlistLoaded(playlist: AudioPlaylist) { if (!playlist.isSearchResult) for (t in playlist.tracks) { - if (shouldInsertFront) + if (shouldInsertFront) { scheduler.insertFront(t, event.member) - else + if (!scheduler.isQueueEmpty()) + scheduler.skip() + + } else scheduler.queue(t, event.member) } else { diff --git a/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt b/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt index e3d5cbf..ced1a46 100644 --- a/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt +++ b/src/main/kotlin/nl/voidcorp/dbot/storage/GuildSettings.kt @@ -7,7 +7,8 @@ import java.time.LocalDateTime data class GuildSettings( val prefixes: MutableList = mutableListOf(), - val muted: MutableMap> = mutableMapOf() + val muted: MutableMap> = mutableMapOf(), + val roleMap: MutableMap = mutableMapOf() ) { fun getPrefixes(): MutableCollection { return prefixes @@ -16,6 +17,7 @@ data class GuildSettings( val primaryPrefix: String get() = prefixes.firstOrNull() ?: "!" + } fun Guild.settings(): GuildSettings {