diff --git a/src/main/kotlin/nl/voidcorp/discord/Loader.kt b/src/main/kotlin/nl/voidcorp/discord/Loader.kt index 74900e5..867cbf6 100644 --- a/src/main/kotlin/nl/voidcorp/discord/Loader.kt +++ b/src/main/kotlin/nl/voidcorp/discord/Loader.kt @@ -2,15 +2,12 @@ package nl.voidcorp.discord import com.sedmelluq.discord.lavaplayer.source.bandcamp.BandcampAudioSourceManager import com.sedmelluq.discord.lavaplayer.source.beam.BeamAudioSourceManager -import com.sedmelluq.discord.lavaplayer.source.http.HttpAudioSourceManager import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager import com.sedmelluq.discord.lavaplayer.source.twitch.TwitchStreamAudioSourceManager import com.sedmelluq.discord.lavaplayer.source.vimeo.VimeoAudioSourceManager -import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioSourceManager import net.dv8tion.jda.api.entities.Activity +import net.dv8tion.jda.api.hooks.ListenerAdapter import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder -import nl.voidcorp.discord.events.CommandListener -import nl.voidcorp.discord.events.OttoListener import nl.voidcorp.discord.music.CustomYoutubeSourceManager import nl.voidcorp.discord.music.PlayerManager import nl.voidcorp.discord.storage.ConfigStore @@ -18,13 +15,13 @@ import org.springframework.stereotype.Service @Service -class Loader(listener: CommandListener, playerManager: PlayerManager, store: ConfigStore, otto: OttoListener) { +class Loader(listeners: List, playerManager: PlayerManager, store: ConfigStore) { init { val token = System.getenv("DISCORD_TOKEN") ?: throw RuntimeException("'DISCORD_TOKEN' not set!") val builder = DefaultShardManagerBuilder(token) - builder.addEventListeners(otto, listener) + builder.addEventListeners(listeners) jda = builder.build() jda.setActivityProvider { diff --git a/src/main/kotlin/nl/voidcorp/discord/commands/management/SetLogChannelCommand.kt b/src/main/kotlin/nl/voidcorp/discord/commands/management/SetLogChannelCommand.kt new file mode 100644 index 0000000..8664163 --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/discord/commands/management/SetLogChannelCommand.kt @@ -0,0 +1,44 @@ +package nl.voidcorp.discord.commands.management + +import nl.voidcorp.discord.command.* +import nl.voidcorp.discord.storage.GuildStore +import org.springframework.stereotype.Service + +@Service +class SetLogChannelCommand : Command( + "setlogchannel", + "Sets the logging channel", + "setlogchannel #channel", + CommandLevel.MODERATOR, + listOf("loghere", "slc"), + CommandSource.GUILD, + CommandGroup.ADMIN +) { + val regex = "(?:<#?)?(\\d+)>?".toRegex() + + override fun handle(event: CommandMessage): CommandResult { + val guild = repo.findByGuildId(event.guild!!.idLong) ?: GuildStore(event.guild.idLong) + if (event.params.drop(1).isEmpty()) { + val logs = "The log channel is " + event.guild.getTextChannelById(guild.loggingChannel ?: -1) + .let { if (it != null) "<#${it.id}>" else "Not set" } + event.reply(logs) + return CommandResult.SUCCESS + } + val l = mutableListOf() + for (p in event.params.drop(1)) { + val res = regex.matchEntire(p) + if (res != null && res.groupValues.size == 2) { + if (event.guild.getTextChannelById(res.groupValues[1]) != null) { + guild.loggingChannel = res.groupValues[1].toLong() + val channel = event.guild.getTextChannelById(res.groupValues[1])!! + l += channel.id + } else event.reply("There is no channel with id `${res.groupValues[1]}`") + } + } + repo.save(guild) + if (l.isNotEmpty()) + event.reply(l.joinToString(prefix = "The logging channel is: ") { "<#$it>" }) + + return CommandResult.SUCCESS + } +} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/events/LogListener.kt b/src/main/kotlin/nl/voidcorp/discord/events/LogListener.kt new file mode 100644 index 0000000..28e53ac --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/discord/events/LogListener.kt @@ -0,0 +1,70 @@ +package nl.voidcorp.discord.events + +import net.dv8tion.jda.api.EmbedBuilder +import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent +import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent +import net.dv8tion.jda.api.hooks.ListenerAdapter +import nl.voidcorp.discord.jda +import nl.voidcorp.discord.storage.GuildRepo +import nl.voidcorp.discord.storage.GuildStore +import nl.voidcorp.discord.storage.MessageRepo +import nl.voidcorp.discord.storage.MessageStore +import org.springframework.stereotype.Service +import java.awt.Color +import java.time.Clock +import java.time.LocalDateTime + +@Service +class LogListener(val repo: GuildRepo, val msg: MessageRepo) : ListenerAdapter() { + + private enum class EventType { + EDIT, + DELET + } + + override fun onGuildMessageReceived(event: GuildMessageReceivedEvent) { + msg.save(MessageStore(event.messageIdLong, event.message.contentRaw, event.guild.idLong, event.author.idLong)) + } + + override fun onGuildMessageUpdate(event: GuildMessageUpdateEvent) { + val past = msg.findByMsgId(event.messageIdLong) ?: MessageStore( + event.messageIdLong, + event.message.contentRaw, + event.guild.idLong, + event.author.idLong + ) + if (event.message.contentRaw != past.text) { + past.past.add(past.text) + past.text = event.message.contentRaw + } + msg.save(past) + sendMessageModification(past, EventType.EDIT) + } + + override fun onGuildMessageDelete(event: GuildMessageDeleteEvent) { + val past = + msg.findByMsgId(event.messageIdLong) ?: MessageStore( + event.messageIdLong, + "~~deleted~~", + event.guild.idLong, + -1 + ) + past.deleted = true + msg.save(past) + sendMessageModification(past, EventType.DELET) + } + + private fun sendMessageModification(st: MessageStore, type: EventType) { + val store = repo.findByGuildId(st.guildId) ?: GuildStore(st.guildId) + if (store.loggingChannel != null) { + val embedBuilder = EmbedBuilder().addField("Message", st.text, false) + .addField("Past", st.past.joinToString("\n"), true) + .addField("Sender", jda.getUserById(st.authorId)?.asTag ?: "someone#-1", true) + .setTitle(type.toString()).setTimestamp(LocalDateTime.now(Clock.systemUTC())) + .setColor(if (type == EventType.EDIT) Color.GREEN.brighter() else Color.RED.darker()) + jda.getTextChannelById(store.loggingChannel ?: -1)?.sendMessage(embedBuilder.build())?.queue() + } + msg.deleteInBatch(msg.findByNowBefore(LocalDateTime.now().minusDays(2))) + } +} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/storage/GuildStore.kt b/src/main/kotlin/nl/voidcorp/discord/storage/GuildStore.kt index 1cb300c..522826c 100644 --- a/src/main/kotlin/nl/voidcorp/discord/storage/GuildStore.kt +++ b/src/main/kotlin/nl/voidcorp/discord/storage/GuildStore.kt @@ -18,6 +18,7 @@ data class GuildStore( var prefix: String = "?", @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) var botChannels: MutableList = mutableListOf(), @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) var musicChannels: MutableList = mutableListOf(), + var loggingChannel: Long? = null, @Id @GeneratedValue var id: Long? = null diff --git a/src/main/kotlin/nl/voidcorp/discord/storage/MessageRepo.kt b/src/main/kotlin/nl/voidcorp/discord/storage/MessageRepo.kt new file mode 100644 index 0000000..526744d --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/discord/storage/MessageRepo.kt @@ -0,0 +1,9 @@ +package nl.voidcorp.discord.storage + +import org.springframework.data.jpa.repository.JpaRepository +import java.time.LocalDateTime + +interface MessageRepo : JpaRepository { + fun findByMsgId(id: Long): MessageStore? + fun findByNowBefore(time: LocalDateTime): List +} \ No newline at end of file diff --git a/src/main/kotlin/nl/voidcorp/discord/storage/MessageStore.kt b/src/main/kotlin/nl/voidcorp/discord/storage/MessageStore.kt new file mode 100644 index 0000000..c238953 --- /dev/null +++ b/src/main/kotlin/nl/voidcorp/discord/storage/MessageStore.kt @@ -0,0 +1,22 @@ +package nl.voidcorp.discord.storage + +import org.hibernate.annotations.LazyCollection +import org.hibernate.annotations.LazyCollectionOption +import java.time.LocalDateTime +import javax.persistence.ElementCollection +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.Id + +@Entity +data class MessageStore( + val msgId: Long, var text: String, + val guildId: Long, val authorId: Long, + @ElementCollection @LazyCollection(LazyCollectionOption.FALSE) val past: MutableList = mutableListOf(), + val now: LocalDateTime = LocalDateTime.now(), + var deleted: Boolean = false, + @Id + @GeneratedValue + var id: Long? = null +) { +} \ No newline at end of file