fix guild settings, add extra stuff

master
Julius de Jeu 2018-11-05 17:41:18 +01:00
parent e1a9341b2e
commit 02dde3ee71
11 changed files with 208 additions and 69 deletions

View File

@ -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 {

View File

@ -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()

View File

@ -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<UnityCommand>.catMap(): Map<String, List<UnityCommand>> {
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<String>()
command.add(javaBin)
command.add("-jar")
command.add(currentJar.path)
val builder = ProcessBuilder(command)
builder.start()
System.exit(0)
}

View File

@ -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!")

View File

@ -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

View File

@ -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 {

View File

@ -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<Long, GuildSettings>()
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()*/
}

View File

@ -74,4 +74,7 @@ class UnityCommandEvent(
val author: User
get() = event.author
val hasArgs: Boolean
get() = args.isNotBlank()
}

View File

@ -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(

View File

@ -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
}
}

View File

@ -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<String> = mutableListOf()) {
data class GuildSettings(
val prefixes: MutableList<String> = mutableListOf(),
val muted: MutableMap<LocalDateTime, MutableList<MuteInfo>> = mutableMapOf()
) {
fun getPrefixes(): MutableCollection<String> {
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<Role>)
fun <A> Map<LocalDateTime, A>.getBefore(test: LocalDateTime = LocalDateTime.now()): List<A> =
this.filter { it.key.isBefore(test) }.map { it.value }
fun <A> MutableMap<LocalDateTime, MutableList<A>>.put(a: LocalDateTime, b: A) {
if (this[a] == null) {
this[a] = mutableListOf()
}
this[a]!! += b
}