diff --git a/Dockerfile b/Dockerfile index 16cc7dd3..04c26a0f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:11 +FROM eclipse-temurin:11-jre-jammy RUN groupadd -r -g 999 ukulele && useradd -rd /opt/ukulele -g ukulele -u 999 -ms /bin/bash ukulele COPY --chown=ukulele:ukulele build/libs/ukulele.jar /opt/ukulele/ukulele.jar USER ukulele diff --git a/build.gradle.kts b/build.gradle.kts index f93f421b..92ed8ad4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,17 +14,18 @@ java.sourceCompatibility = JavaVersion.VERSION_11 repositories { mavenCentral() + flatDir { + dirs("lib") + } maven { url = uri("https://m2.dv8tion.net/releases") } maven { url = uri("https://jitpack.io") } + maven { url = uri("https://maven.lavalink.dev/releases") } } dependencies { - // The 4.x version of JDA specifically needs a UDP fix from this commit: - // https://github.com/DV8FromTheWorld/JDA/commit/39ba0c2682ad99dbec88240cb8ea9d1ff7162ae9 - // The snapshot version published in jitpack has this, so it is utilized for now. - // Eventually, a full upgrade to JDA 5.x will be necessary. - implementation("com.github.DV8FromTheWorld:JDA:legacy~v4-SNAPSHOT") - implementation("dev.arbjerg:lavaplayer:1.5.0") + implementation("com.github.DV8FromTheWorld:JDA:v5.0.0-beta.23") + implementation("dev.arbjerg:lavaplayer:2.2.2") + implementation("dev.lavalink.youtube:v2:1.8.3") implementation("org.springframework.boot:spring-boot-starter-data-r2dbc") runtimeOnly("com.h2database:h2") diff --git a/docker-compose.yml b/docker-compose.yml index ba1cfd20..e9ab7e69 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,8 +2,9 @@ version: "3.7" services: ukulele: - image: ghcr.io/freyacodes/ukulele:master - restart: always + container_name: ukulele + image: ghcr.io/jocull/ukulele:jda-5 + restart: unless-stopped environment: CONFIG_DATABASE: ./db/database # Database location overwrite so mounting works volumes: diff --git a/src/main/kotlin/dev/arbjerg/ukulele/audio/LavaplayerConfig.kt b/src/main/kotlin/dev/arbjerg/ukulele/audio/LavaplayerConfig.kt index ef065f60..ab452d6a 100644 --- a/src/main/kotlin/dev/arbjerg/ukulele/audio/LavaplayerConfig.kt +++ b/src/main/kotlin/dev/arbjerg/ukulele/audio/LavaplayerConfig.kt @@ -1,19 +1,25 @@ package dev.arbjerg.ukulele.audio +import com.sedmelluq.discord.lavaplayer.container.MediaContainerRegistry import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers +import dev.lavalink.youtube.YoutubeAudioSourceManager import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class LavaplayerConfig { - @Bean fun playerManager(): AudioPlayerManager { val apm = DefaultAudioPlayerManager() - AudioSourceManagers.registerRemoteSources(apm) + + // Add the new YoutubeAudioSourceManager + apm.registerSourceManager(YoutubeAudioSourceManager(true)) + + // Then add the rest, while excluding the legacy `YoutubeAudioSourceManager` + AudioSourceManagers.registerRemoteSources(apm, MediaContainerRegistry.DEFAULT_REGISTRY, com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioSourceManager::class.java) + return apm } - -} \ No newline at end of file +} diff --git a/src/main/kotlin/dev/arbjerg/ukulele/audio/Player.kt b/src/main/kotlin/dev/arbjerg/ukulele/audio/Player.kt index 9a485451..174fc5ca 100644 --- a/src/main/kotlin/dev/arbjerg/ukulele/audio/Player.kt +++ b/src/main/kotlin/dev/arbjerg/ukulele/audio/Player.kt @@ -12,7 +12,7 @@ import dev.arbjerg.ukulele.config.BotProps import dev.arbjerg.ukulele.data.GuildProperties import dev.arbjerg.ukulele.data.GuildPropertiesService import net.dv8tion.jda.api.audio.AudioSendHandler -import net.dv8tion.jda.api.entities.TextChannel +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.stereotype.Component @@ -125,7 +125,7 @@ class Player(val beans: Beans, guildProperties: GuildProperties) : AudioEventAda override fun onTrackStart(player: AudioPlayer, track: AudioTrack) { if (beans.botProps.announceTracks) { - lastChannel?.sendMessage(beans.nowPlayingCommand.buildEmbed(track))?.queue() + lastChannel?.sendMessageEmbeds(beans.nowPlayingCommand.buildEmbed(track))?.queue() } } diff --git a/src/main/kotlin/dev/arbjerg/ukulele/command/HelpCommand.kt b/src/main/kotlin/dev/arbjerg/ukulele/command/HelpCommand.kt index 193a5329..ee198a84 100644 --- a/src/main/kotlin/dev/arbjerg/ukulele/command/HelpCommand.kt +++ b/src/main/kotlin/dev/arbjerg/ukulele/command/HelpCommand.kt @@ -3,7 +3,9 @@ package dev.arbjerg.ukulele.command import dev.arbjerg.ukulele.features.HelpContext import dev.arbjerg.ukulele.jda.Command import dev.arbjerg.ukulele.jda.CommandContext -import net.dv8tion.jda.api.MessageBuilder +import net.dv8tion.jda.api.entities.MessageEmbed +import net.dv8tion.jda.api.utils.MarkdownUtil +import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder import org.springframework.stereotype.Component @Component @@ -12,14 +14,15 @@ class HelpCommand : Command("help") { if (argumentText.isNotBlank()) { replyHelp(beans.commandManager[argumentText.trim()] ?: command) } else { - val msg = MessageBuilder() - .append("Available commands:") - .appendCodeBlock(buildString { + val msg = MessageCreateBuilder() + .addContent("Available commands:") + .addContent(MarkdownUtil.codeblock(buildString { beans.commandManager.getCommands().forEach { appendLine((listOf(it.name) + it.aliases).joinToString()) } - }, "") - .append("\nUse \"${trigger} \" to see more details.") + })) + .addContent("\nUse \"${trigger} \" to see more details.") + replyMsg(msg.build()) } } diff --git a/src/main/kotlin/dev/arbjerg/ukulele/features/HelpContext.kt b/src/main/kotlin/dev/arbjerg/ukulele/features/HelpContext.kt index 83da31b4..43b918da 100644 --- a/src/main/kotlin/dev/arbjerg/ukulele/features/HelpContext.kt +++ b/src/main/kotlin/dev/arbjerg/ukulele/features/HelpContext.kt @@ -2,7 +2,8 @@ package dev.arbjerg.ukulele.features import dev.arbjerg.ukulele.jda.Command import dev.arbjerg.ukulele.jda.CommandContext -import net.dv8tion.jda.api.MessageBuilder +import net.dv8tion.jda.api.utils.MarkdownUtil +import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder class HelpContext(private val commandContext: CommandContext, private val command: Command) { private val lines = mutableListOf() @@ -20,7 +21,7 @@ class HelpContext(private val commandContext: CommandContext, private val comman lines.add("# " + text.trim()) } - fun buildMessage() = MessageBuilder() - .appendCodeBlock(lines.joinToString(separator = "\n"), "md") - .build() + fun buildMessage() = MessageCreateBuilder() + .addContent(MarkdownUtil.codeblock("md", lines.joinToString(separator = "\n"))) + .build() } \ No newline at end of file diff --git a/src/main/kotlin/dev/arbjerg/ukulele/jda/CommandContext.kt b/src/main/kotlin/dev/arbjerg/ukulele/jda/CommandContext.kt index 09e2b17b..2dcd0054 100644 --- a/src/main/kotlin/dev/arbjerg/ukulele/jda/CommandContext.kt +++ b/src/main/kotlin/dev/arbjerg/ukulele/jda/CommandContext.kt @@ -9,19 +9,20 @@ import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.Member import net.dv8tion.jda.api.entities.Message import net.dv8tion.jda.api.entities.MessageEmbed -import net.dv8tion.jda.api.entities.TextChannel +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel +import net.dv8tion.jda.api.utils.messages.MessageCreateData import org.springframework.stereotype.Component class CommandContext( - val beans: Beans, - val guildProperties: GuildProperties, - val guild: Guild, - val channel: TextChannel, - val invoker: Member, - val message: Message, - val command: Command, - val prefix: String, - /** Prefix + command name */ + val beans: Beans, + val guildProperties: GuildProperties, + val guild: Guild, + val channel: TextChannel, + val invoker: Member, + val message: Message, + val command: Command, + val prefix: String, + /** Prefix + command name */ val trigger: String ) { @Component @@ -44,12 +45,12 @@ class CommandContext( channel.sendMessage(msg).queue() } - fun replyMsg(msg: Message) { + fun replyMsg(msg: MessageCreateData) { channel.sendMessage(msg).queue() } fun replyEmbed(embed: MessageEmbed) { - channel.sendMessage(embed).queue() + channel.sendMessage(MessageCreateData.fromEmbeds(embed)).queue() } fun replyHelp(forCommand: Command = command) { diff --git a/src/main/kotlin/dev/arbjerg/ukulele/jda/CommandManager.kt b/src/main/kotlin/dev/arbjerg/ukulele/jda/CommandManager.kt index 8d244e34..d89eb295 100644 --- a/src/main/kotlin/dev/arbjerg/ukulele/jda/CommandManager.kt +++ b/src/main/kotlin/dev/arbjerg/ukulele/jda/CommandManager.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.launch import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.Member import net.dv8tion.jda.api.entities.Message -import net.dv8tion.jda.api.entities.TextChannel +import net.dv8tion.jda.api.entities.channel.concrete.TextChannel import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.stereotype.Service diff --git a/src/main/kotlin/dev/arbjerg/ukulele/jda/EventHandler.kt b/src/main/kotlin/dev/arbjerg/ukulele/jda/EventHandler.kt index fd9705ce..6e9316d6 100644 --- a/src/main/kotlin/dev/arbjerg/ukulele/jda/EventHandler.kt +++ b/src/main/kotlin/dev/arbjerg/ukulele/jda/EventHandler.kt @@ -1,8 +1,8 @@ package dev.arbjerg.ukulele.jda -import net.dv8tion.jda.api.events.ReadyEvent +import net.dv8tion.jda.api.entities.channel.ChannelType import net.dv8tion.jda.api.events.StatusChangeEvent -import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent +import net.dv8tion.jda.api.events.message.MessageReceivedEvent import net.dv8tion.jda.api.hooks.ListenerAdapter import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -13,9 +13,11 @@ class EventHandler(private val commandManager: CommandManager) : ListenerAdapter private val log: Logger = LoggerFactory.getLogger(EventHandler::class.java) - override fun onGuildMessageReceived(event: GuildMessageReceivedEvent) { + override fun onMessageReceived(event: MessageReceivedEvent) { if (event.isWebhookMessage || event.author.isBot) return - commandManager.onMessage(event.guild, event.channel, event.member!!, event.message) + if (event.channelType != ChannelType.TEXT) return + + commandManager.onMessage(event.guild, event.channel.asTextChannel(), event.member!!, event.message) } override fun onStatusChange(event: StatusChangeEvent) { diff --git a/src/main/kotlin/dev/arbjerg/ukulele/jda/JdaConfig.kt b/src/main/kotlin/dev/arbjerg/ukulele/jda/JdaConfig.kt index 3d707223..2f5beb0f 100644 --- a/src/main/kotlin/dev/arbjerg/ukulele/jda/JdaConfig.kt +++ b/src/main/kotlin/dev/arbjerg/ukulele/jda/JdaConfig.kt @@ -6,9 +6,9 @@ import net.dv8tion.jda.api.sharding.ShardManager import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import net.dv8tion.jda.api.requests.GatewayIntent.* -import net.dv8tion.jda.api.requests.restaction.MessageAction import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder import net.dv8tion.jda.api.utils.cache.CacheFlag +import net.dv8tion.jda.api.utils.messages.MessageRequest import javax.security.auth.login.LoginException import kotlin.concurrent.thread @@ -16,7 +16,7 @@ import kotlin.concurrent.thread class JdaConfig { init { - MessageAction.setDefaultMentions(emptyList()) + MessageRequest.setDefaultMentions(emptyList()) } @Bean @@ -26,20 +26,21 @@ class JdaConfig { val intents = listOf( - GUILD_VOICE_STATES, - GUILD_MESSAGES, - GUILD_BANS, - DIRECT_MESSAGES + GUILD_VOICE_STATES, + GUILD_MESSAGES, + GUILD_BANS, + DIRECT_MESSAGES, + MESSAGE_CONTENT ) val builder = DefaultShardManagerBuilder.create(botProps.token, intents) - .disableCache(CacheFlag.ACTIVITY, CacheFlag.EMOTE, CacheFlag.CLIENT_STATUS) - .setBulkDeleteSplittingEnabled(false) - .setEnableShutdownHook(false) - .setAutoReconnect(true) - .setShardsTotal(botProps.shards) - .addEventListeners(eventHandler) - .setActivity(activity) + .disableCache(CacheFlag.ACTIVITY, CacheFlag.EMOJI, CacheFlag.CLIENT_STATUS) + .setBulkDeleteSplittingEnabled(false) + .setEnableShutdownHook(false) + .setAutoReconnect(true) + .setShardsTotal(botProps.shards) + .addEventListeners(eventHandler) + .setActivity(activity) val shardManager: ShardManager try {