diff --git a/bot/src/main/java/ml/duncte123/skybot/CommandManager.java b/bot/src/main/java/ml/duncte123/skybot/CommandManager.java index 2f3f93924..f0ecf9c38 100644 --- a/bot/src/main/java/ml/duncte123/skybot/CommandManager.java +++ b/bot/src/main/java/ml/duncte123/skybot/CommandManager.java @@ -746,6 +746,19 @@ public List getAllSlashCommands() { } public void executeSlashCommand(SlashCommandInteractionEvent event) { + final String fullCommandName = event.getFullCommandName(); + + if (fullCommandName.startsWith("music")) { + final String musicName = fullCommandName.replace("music", "").trim(); + final MusicCommand command = (MusicCommand) this.getCommand(musicName); + + if (command != null) { + command.handleEvent(event, variables); + } + + return; + } + final SlashSupport command = (SlashSupport) this.getCommand(event.getName()); if (command != null) { diff --git a/bot/src/main/java/ml/duncte123/skybot/audio/AudioLoader.java b/bot/src/main/java/ml/duncte123/skybot/audio/AudioLoader.java index d2de56006..01bf9efef 100644 --- a/bot/src/main/java/ml/duncte123/skybot/audio/AudioLoader.java +++ b/bot/src/main/java/ml/duncte123/skybot/audio/AudioLoader.java @@ -24,14 +24,15 @@ import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; +import me.duncte123.botcommons.messaging.MessageConfig; import ml.duncte123.skybot.CommandManager; import ml.duncte123.skybot.commands.music.RadioCommand; import ml.duncte123.skybot.exceptions.LimitReachedException; import ml.duncte123.skybot.extensions.AudioTrackKt; import ml.duncte123.skybot.extensions.StringKt; +import ml.duncte123.skybot.objects.AudioData; import ml.duncte123.skybot.objects.RadioStream; import ml.duncte123.skybot.objects.TrackUserData; -import ml.duncte123.skybot.objects.command.CommandContext; import net.dv8tion.jda.api.entities.MessageEmbed; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -40,21 +41,20 @@ import java.util.Optional; import static me.duncte123.botcommons.messaging.EmbedUtils.embedMessage; -import static me.duncte123.botcommons.messaging.MessageUtils.sendEmbed; import static me.duncte123.botcommons.messaging.MessageUtils.sendMsg; public class AudioLoader implements AudioLoadResultHandler { - private final CommandContext ctx; + private final AudioData data; private final long requester; private final GuildMusicManager mng; private final boolean announce; private final String trackUrl; private final boolean isPatron; - public AudioLoader(CommandContext ctx, GuildMusicManager mng, boolean announce, String trackUrl, boolean isPatron) { - this.ctx = ctx; - this.requester = ctx.getAuthor().getIdLong(); + public AudioLoader(AudioData data, GuildMusicManager mng, boolean announce, String trackUrl, boolean isPatron) { + this.data = data; + this.requester = data.getUserId(); this.mng = mng; this.announce = announce; this.trackUrl = trackUrl; @@ -68,8 +68,12 @@ public void trackLoaded(AudioTrack track) { final TrackScheduler scheduler = this.mng.getScheduler(); if (!this.isPatron && !scheduler.canQueue()) { - sendMsg(this.ctx, String.format("Could not queue track because limit of %d tracks has been reached.\n" + - "Consider supporting us on patreon to queue up unlimited songs.", TrackScheduler.MAX_QUEUE_SIZE)); + sendMsg(new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setMessage(String.format("Could not queue track because limit of %d tracks has been reached.\n" + + "Consider supporting us on patreon to queue up unlimited songs.", TrackScheduler.MAX_QUEUE_SIZE)) + .build()); return; } @@ -85,24 +89,40 @@ public void trackLoaded(AudioTrack track) { uri = info.uri; } - final String title = getSteamTitle(track, info.title, this.ctx.getCommandManager()); + final String title = getSteamTitle(track, info.title, this.data.getVariables().getCommandManager()); final String msg = "Adding to queue: [" + StringKt.abbreviate(title, 500) + "](" + uri + ')'; - sendEmbed(this.ctx, - embedMessage(msg) - .setThumbnail(AudioTrackKt.getImageUrl(track, true)) + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setEmbeds(embedMessage(msg) + .setThumbnail(AudioTrackKt.getImageUrl(track, true))) + .build() ); } } catch (LimitReachedException e) { - sendMsg(this.ctx, String.format("You exceeded the maximum queue size of %s tracks", e.getSize())); + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setMessage(String.format("You exceeded the maximum queue size of %s tracks", e.getSize())) + .build() + ); } } @Override public void playlistLoaded(AudioPlaylist playlist) { if (playlist.getTracks().isEmpty()) { - sendEmbed(this.ctx, embedMessage("Error: This playlist is empty.")); + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setEmbeds(embedMessage("Error: This playlist is empty.")) + .build() + ); return; } @@ -145,28 +165,55 @@ public void playlistLoaded(AudioPlaylist playlist) { playlist.getName() ); - sendEmbed(this.ctx, embedMessage(msg)); + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setEmbeds(embedMessage(msg)) + .build() + ); } } catch (LimitReachedException e) { if (this.announce) { - sendMsg(this.ctx, String.format("The first %s tracks from %s have been queued up\n" + - "Consider supporting us on patreon to queue up unlimited songs.", e.getSize(), playlist.getName())); + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setMessage(String.format("The first %s tracks from %s have been queued up\n" + + "Consider supporting us on patreon to queue up unlimited songs.", e.getSize(), playlist.getName())) + .build() + ); } + } } @Override public void noMatches() { if (this.announce) { - sendEmbed(this.ctx, embedMessage("Nothing found by *" + StringKt.abbreviate(this.trackUrl, MessageEmbed.VALUE_MAX_LENGTH) + '*')); + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setEmbeds(embedMessage("Nothing found by *" + StringKt.abbreviate(this.trackUrl, MessageEmbed.VALUE_MAX_LENGTH) + '*')) + .build() + ); } } @Override public void loadFailed(FriendlyException exception) { if (exception.getCause() != null && exception.getCause() instanceof final LimitReachedException cause) { - sendMsg(this.ctx, String.format("%s, maximum of %d tracks exceeded", cause.getMessage(), cause.getSize())); + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setMessage( + String.format("%s, maximum of %d tracks exceeded", cause.getMessage(), cause.getSize()) + ) + .build() + ); return; } @@ -176,8 +223,16 @@ public void loadFailed(FriendlyException exception) { } if (exception.getMessage().endsWith("Playback on other websites has been disabled by the video owner.")) { - sendEmbed(this.ctx, embedMessage("Could not play: " + this.trackUrl - + "\nExternal playback of this video was blocked by YouTube.")); + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setEmbeds( + embedMessage("Could not play: " + this.trackUrl + + "\nExternal playback of this video was blocked by YouTube.") + ) + .build() + ); return; } @@ -187,8 +242,16 @@ public void loadFailed(FriendlyException exception) { root = exception; } - sendEmbed(this.ctx, embedMessage("Could not play: " + StringKt.abbreviate(root.getMessage(), MessageEmbed.VALUE_MAX_LENGTH) - + "\nIf this happens often try another link or join our [discord server](https://duncte.bot/server) to get help!")); + sendMsg( + new MessageConfig.Builder() + .setChannel(this.data.getChannel()) + .replyTo(this.data.getReplyToMessage()) + .setEmbeds( + embedMessage("Could not play: " + StringKt.abbreviate(root.getMessage(), MessageEmbed.VALUE_MAX_LENGTH) + + "\nIf this happens often try another link or join our [discord server](https://duncte.bot/server) to get help!") + ) + .build() + ); } diff --git a/bot/src/main/java/ml/duncte123/skybot/objects/command/Command.java b/bot/src/main/java/ml/duncte123/skybot/objects/command/Command.java index f161e34b9..b64808b9e 100644 --- a/bot/src/main/java/ml/duncte123/skybot/objects/command/Command.java +++ b/bot/src/main/java/ml/duncte123/skybot/objects/command/Command.java @@ -186,7 +186,7 @@ public String getExtraInfo(String prefix) { @Override public String toString() { - return "Command[" + this.name + ']'; + return "Command[" + this.getName() + ']'; } @Override diff --git a/bot/src/main/java/ml/duncte123/skybot/objects/command/CommandContext.java b/bot/src/main/java/ml/duncte123/skybot/objects/command/CommandContext.java index 6c07ea5f4..e07d80320 100644 --- a/bot/src/main/java/ml/duncte123/skybot/objects/command/CommandContext.java +++ b/bot/src/main/java/ml/duncte123/skybot/objects/command/CommandContext.java @@ -24,6 +24,7 @@ import ml.duncte123.skybot.*; import ml.duncte123.skybot.database.AbstractDatabase; import ml.duncte123.skybot.entities.jda.DunctebotGuild; +import ml.duncte123.skybot.objects.AudioData; import ml.duncte123.skybot.objects.api.DuncteApis; import ml.duncte123.skybot.objects.apis.BlargBot; import ml.duncte123.skybot.objects.apis.alexflipnote.Alexflipnote; @@ -170,6 +171,17 @@ public List getMentionedArg(int index) { return FinderUtils.searchMembers(this.getArgs().get(index), this); } + public AudioData getAudioData() { + return new AudioData( + this.getJDAGuild().getIdLong(), + this.getAuthor().getIdLong(), + this.getChannel().getIdLong(), + this.getMessage().getIdLong(), + this.getJDA(), + this.variables + ); + } + // --------------- Reaction processing methods --------------- // public ReactionHandler getReactionHandler() { @@ -219,6 +231,10 @@ public DunctebotGuild getGuild() { return this.duncteBotGuild; } + public long getGuildId() { + return this.getGuild().getIdLong(); + } + public Guild getJDAGuild() { return this.event.getGuild(); } diff --git a/bot/src/main/java/ml/duncte123/skybot/utils/AudioUtils.java b/bot/src/main/java/ml/duncte123/skybot/utils/AudioUtils.java index 01c61e26e..32bfd3987 100644 --- a/bot/src/main/java/ml/duncte123/skybot/utils/AudioUtils.java +++ b/bot/src/main/java/ml/duncte123/skybot/utils/AudioUtils.java @@ -38,6 +38,7 @@ import ml.duncte123.skybot.audio.GuildMusicManager; import ml.duncte123.skybot.audio.sourcemanagers.DBAudioRef; import ml.duncte123.skybot.audio.sourcemanagers.spotify.SpotifyAudioSourceManager; +import ml.duncte123.skybot.objects.AudioData; import ml.duncte123.skybot.objects.command.CommandContext; import ml.duncte123.skybot.objects.config.DunctebotConfig; import net.dv8tion.jda.api.entities.Guild; @@ -91,9 +92,15 @@ public BasicAudioPlaylist searchYoutube(String query) { return null; } + @Deprecated public Future loadAndPlay(final CommandContext ctx, final String trackUrlRaw, final boolean announce) { - final boolean isPatron = CommandUtils.isUserTagPatron(ctx.getAuthor()); + return loadAndPlay(ctx.getAudioData(), trackUrlRaw, announce); + } + + public Future loadAndPlay(final AudioData data, final String trackUrlRaw, + final boolean announce) { + final boolean isPatron = CommandUtils.isUserTagPatron(data.getUserId()); // final boolean isPatron = false; final String trackUrl; @@ -104,14 +111,15 @@ public Future loadAndPlay(final CommandContext ctx, final String trackUrlR trackUrl = trackUrlRaw; } - final GuildMusicManager mng = getMusicManager(ctx.getJDAGuild()); - final AudioLoader loader = new AudioLoader(ctx, mng, announce, trackUrl, isPatron); + final GuildMusicManager mng = getMusicManager(data.getGuildId()); + final AudioLoader loader = new AudioLoader(data, mng, announce, trackUrl, isPatron); final DBAudioRef reference = new DBAudioRef(trackUrl, null, isPatron); return getPlayerManager().loadItemOrdered(mng, reference, loader); } // transition period + @Deprecated public GuildMusicManager getMusicManager(Guild guild) { return getMusicManager(guild.getIdLong()); } diff --git a/bot/src/main/java/ml/duncte123/skybot/utils/CommandUtils.java b/bot/src/main/java/ml/duncte123/skybot/utils/CommandUtils.java index 37dc3d5d8..dac04eba0 100644 --- a/bot/src/main/java/ml/duncte123/skybot/utils/CommandUtils.java +++ b/bot/src/main/java/ml/duncte123/skybot/utils/CommandUtils.java @@ -188,7 +188,11 @@ private static boolean isPatron(@Nonnull User user, @Nullable CommandContext ctx } public static boolean isUserTagPatron(@Nonnull User user) { - return TAG_PATRONS.contains(user.getIdLong()) || isDev(user); + return isUserTagPatron(user.getIdLong()); + } + + public static boolean isUserTagPatron(long userId) { + return TAG_PATRONS.contains(userId) || isDev(userId); } private static boolean isPatron(@Nonnull User user, @Nullable CommandContext ctx, boolean reply) { diff --git a/bot/src/main/kotlin/ml/duncte123/skybot/commands/music/PlayCommand.kt b/bot/src/main/kotlin/ml/duncte123/skybot/commands/music/PlayCommand.kt index dbe6aeb78..e77bd8296 100644 --- a/bot/src/main/kotlin/ml/duncte123/skybot/commands/music/PlayCommand.kt +++ b/bot/src/main/kotlin/ml/duncte123/skybot/commands/music/PlayCommand.kt @@ -23,6 +23,7 @@ import me.duncte123.botcommons.messaging.MessageUtils import me.duncte123.botcommons.messaging.MessageUtils.sendMsg import ml.duncte123.skybot.Variables import ml.duncte123.skybot.extensions.isNSFW +import ml.duncte123.skybot.objects.AudioData import ml.duncte123.skybot.objects.command.CommandContext import ml.duncte123.skybot.objects.command.MusicCommand import ml.duncte123.skybot.utils.AirUtils @@ -48,7 +49,7 @@ open class PlayCommand(private val skipParsing: Boolean = false) : MusicCommand( return } - val mng = ctx.audioUtils.getMusicManager(ctx.guild) + val mng = ctx.audioUtils.getMusicManager(ctx.guildId) val player = mng.player val scheduler = mng.scheduler @@ -134,7 +135,7 @@ open class PlayCommand(private val skipParsing: Boolean = false) : MusicCommand( return } - ctx.audioUtils.loadAndPlay(ctx, toPlay, true) + ctx.audioUtils.loadAndPlay(ctx.audioData, toPlay, true) } private fun handlePlay(toPlay: String, variables: Variables, event: SlashCommandInteractionEvent) { @@ -143,10 +144,10 @@ open class PlayCommand(private val skipParsing: Boolean = false) : MusicCommand( return } - event.deferReply().queue() + // need to wait for this to send actually + event.reply("Loading your track!").complete() - // TODO: get rid of CTX - // variables.audioUtils.loadAndPlay(ctx, toPlay, true) + variables.audioUtils.loadAndPlay(AudioData.fromSlash(event, variables), toPlay, true) } override fun getSubData(): SubcommandData { @@ -168,7 +169,7 @@ open class PlayCommand(private val skipParsing: Boolean = false) : MusicCommand( } if (skipParsing) { - handlePlay(toPlay, variables, event) // TODO + handlePlay(toPlay, variables, event) return } diff --git a/bot/src/main/kotlin/ml/duncte123/skybot/objects/AudioData.kt b/bot/src/main/kotlin/ml/duncte123/skybot/objects/AudioData.kt new file mode 100644 index 000000000..00e644263 --- /dev/null +++ b/bot/src/main/kotlin/ml/duncte123/skybot/objects/AudioData.kt @@ -0,0 +1,46 @@ +/* + * Skybot, a multipurpose discord bot + * Copyright (C) 2017 Duncan "duncte123" Sterken & Ramid "ramidzkh" Khan & Maurice R S "Sanduhr32" + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package ml.duncte123.skybot.objects + +import ml.duncte123.skybot.Variables +import net.dv8tion.jda.api.JDA +import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent + +data class AudioData( + val guildId: Long, + val userId: Long, + val channelId: Long, + val replyToMessage: Long, + val jda: JDA, + val variables: Variables +) { + fun getChannel() = jda.getChannelById(MessageChannelUnion::class.java, channelId)!! + + companion object { + fun fromSlash(event: SlashCommandInteractionEvent, variables: Variables): AudioData = AudioData( + event.guild!!.idLong, + event.user.idLong, + event.channel.idLong, + event.hook.retrieveOriginal().complete().idLong, + event.jda, + variables + ) + } +}