Skip to content

Commit

Permalink
First pass on adding slash commamnds
Browse files Browse the repository at this point in the history
  • Loading branch information
duncte123 committed Jun 1, 2023
1 parent 60c386e commit e71b88d
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 6 deletions.
17 changes: 17 additions & 0 deletions bot/src/main/java/ml/duncte123/skybot/CommandManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import ml.duncte123.skybot.commands.utils.EnlargeCommand;
import ml.duncte123.skybot.commands.utils.RoleInfoCommand;
import ml.duncte123.skybot.commands.weeb.*;
import ml.duncte123.skybot.objects.SlashSupport;
import ml.duncte123.skybot.objects.command.*;
import ml.duncte123.skybot.objects.pairs.LongLongPair;
import ml.duncte123.skybot.utils.CommandUtils;
Expand All @@ -65,8 +66,10 @@
import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.exceptions.ErrorHandler;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.utils.data.DataObject;
import net.dv8tion.jda.internal.JDAImpl;
import org.slf4j.Logger;
Expand Down Expand Up @@ -703,6 +706,20 @@ private void addCommand(ICommand<CommandContext> command) {
this.commands.put(cmdName, command);
}

public List<SlashCommandData> getAllSlashCommands() {
return this.commands.values().stream()
.filter((cmd) -> cmd instanceof SlashSupport)
.map((cmd) -> (SlashSupport) cmd)
.map(SlashSupport::getSlashData)
.toList();
}

public void executeSlashCommand(SlashCommandInteractionEvent event) {
final SlashSupport command = (SlashSupport) this.getCommand(event.getName());

command.handleEvent(event, variables);
}

private static long calcTimeRemaining(long startTime) {
// Get the start time as an ZonedDateTime
final ZonedDateTime startTimeOffset = Instant.ofEpochSecond(startTime).atZone(ZoneOffset.UTC);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.message.*;
import net.dv8tion.jda.api.exceptions.ErrorHandler;
import net.dv8tion.jda.api.sharding.ShardManager;
Expand Down Expand Up @@ -305,6 +306,10 @@ protected void onGuildMessageReceived(MessageReceivedEvent event) {
});
}

protected void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
this.commandManager.executeSlashCommand(event);
}

private boolean invokeAutoResponse(List<CustomCommand> autoResponses, String[] split, MessageReceivedEvent event) {
final String stripped = event.getMessage().getContentStripped().toLowerCase();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import ml.duncte123.skybot.web.WebSocketClient;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.events.GenericEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.message.MessageBulkDeleteEvent;
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
Expand Down Expand Up @@ -62,6 +63,8 @@ public void onEvent(@Nonnull GenericEvent event) {
this.onGuildMessageUpdate(messageUpdate);
} else if (event instanceof MessageReceivedEvent messageReceived) {
this.onGuildMessageReceived(messageReceived);
} else if (event instanceof SlashCommandInteractionEvent slashEvent) {
this.onSlashCommandInteraction(slashEvent);
} else if (event instanceof MessageDeleteEvent delete) {
this.onGuildMessageDelete(delete);
} else if (event instanceof MessageBulkDeleteEvent bulkDelete) {
Expand Down Expand Up @@ -95,6 +98,12 @@ private void onReady(ReadyEvent event) {

// Load the patrons here so that they are loaded once
GuildUtils.loadAllPatrons(variables.getDatabase());

// Nice first attempt :)
/*jda.getGuildById(191245668617158656L)
.updateCommands()
.addCommands(this.commandManager.getAllSlashCommands())
.queue();*/
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,22 @@

package ml.duncte123.skybot.commands.utils

import me.duncte123.botcommons.commands.ICommandContext
import me.duncte123.botcommons.messaging.MessageUtils.sendMsg
import ml.duncte123.skybot.Variables
import ml.duncte123.skybot.extensions.escapeMarkDown
import ml.duncte123.skybot.objects.command.Command
import ml.duncte123.skybot.objects.SlashCommandContext
import ml.duncte123.skybot.objects.SlashSupport
import ml.duncte123.skybot.objects.command.CommandCategory
import ml.duncte123.skybot.objects.command.CommandContext
import ml.duncte123.skybot.utils.AirUtils.shortenUrl
import ml.duncte123.skybot.utils.TwemojiParser
import ml.duncte123.skybot.utils.TwemojiParser.stripVariants
import net.dv8tion.jda.api.entities.emoji.CustomEmoji
import net.dv8tion.jda.api.interactions.commands.OptionType
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData

class EmoteCommand : Command() {
class EmoteCommand : SlashSupport() {
init {
this.category = CommandCategory.UTILS
this.name = "emote"
Expand Down Expand Up @@ -60,10 +65,10 @@ class EmoteCommand : Command() {
return
}

normalEmoteMentioned(ctx, stripVariants(arg))
normalEmoteMentioned(ctx, ctx.variables, stripVariants(arg))
}

private fun customEmoteMentioned(ctx: CommandContext, emote: CustomEmoji) {
private fun customEmoteMentioned(ctx: ICommandContext, emote: CustomEmoji) {
val name = emote.name
val id = emote.id
val url = emote.imageUrl
Expand All @@ -79,7 +84,7 @@ class EmoteCommand : Command() {
)
}

private fun normalEmoteMentioned(ctx: CommandContext, emote: String) {
private fun normalEmoteMentioned(ctx: ICommandContext, variables: Variables, emote: String) {
val joinedHex = StringBuilder()
val message = buildString {
appendLine("Emoji/char info for ${emote.escapeMarkDown()}:")
Expand Down Expand Up @@ -109,7 +114,7 @@ class EmoteCommand : Command() {
val emojiUrl = TwemojiParser.parseOne(emote)

if (emojiUrl != null) {
val shortUrl = shortenUrl(emojiUrl, ctx.config.apis.googl, ctx.variables.jackson).execute()
val shortUrl = shortenUrl(emojiUrl, variables.config.apis.googl, variables.jackson).execute()

appendLine("Image url (shortened): <$shortUrl>")
}
Expand All @@ -126,4 +131,34 @@ class EmoteCommand : Command() {
private fun Int.getName() = Character.getName(this)
private fun Char.toHex() = this.code.toHex()
private fun String.ensureFourHex() = "0000$this".substring(this.length.coerceAtMost(4))

override fun configureSlashSupport(baseData: SlashCommandData) {
baseData.addOption(
OptionType.STRING,
"emote",
"The emote to show information about",
true
)
}

override fun handleSlash(ctx: SlashCommandContext) {
val emote = ctx.event.getOption("emote")!!

val mentionedEmotes = emote.mentions.customEmojis

if (mentionedEmotes.isNotEmpty()) {
customEmoteMentioned(ctx, mentionedEmotes[0])
return
}

val arg = emote.asString

// ¯\_(ツ)_/¯
if (arg.codePoints().count() > 10) {
sendMsg(ctx, "Invalid emote or input is too long")
return
}

normalEmoteMentioned(ctx, ctx.variables, stripVariants(arg))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/

package ml.duncte123.skybot.objects

import me.duncte123.botcommons.commands.ICommandContext
import ml.duncte123.skybot.Variables
import net.dv8tion.jda.api.entities.Message
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
import net.dv8tion.jda.api.events.message.MessageReceivedEvent

class SlashCommandContext(val event: SlashCommandInteractionEvent, private val msg: Message, val variables: Variables) : ICommandContext {

override fun isFromGuild() = event.isFromGuild

override fun getChannel() = event.channel

override fun getJDA() = event.jda

override fun getMessage() = msg

override fun getEvent(): MessageReceivedEvent {
TODO("Not yet implemented")
}
}
50 changes: 50 additions & 0 deletions bot/src/main/kotlin/ml/duncte123/skybot/objects/SlashSupport.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/

package ml.duncte123.skybot.objects

import ml.duncte123.skybot.Variables
import ml.duncte123.skybot.objects.command.CommandCategory
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
import net.dv8tion.jda.api.interactions.commands.build.Commands
import ml.duncte123.skybot.objects.command.Command as SkyCommand
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData

abstract class SlashSupport : SkyCommand() {
protected abstract fun configureSlashSupport(baseData: SlashCommandData)

fun getSlashData(): SlashCommandData {
val base = Commands.slash(name, getHelp("", "/"))
.setGuildOnly(true)
.setNSFW(category == CommandCategory.NSFW)

configureSlashSupport(base)

return base
}

fun handleEvent(event: SlashCommandInteractionEvent, variables: Variables) {
event.deferReply(false).queue { hook ->
hook.retrieveOriginal().queue { message ->
handleSlash(SlashCommandContext(event, message, variables))
}
}
}

protected abstract fun handleSlash(ctx: SlashCommandContext)
}

0 comments on commit e71b88d

Please sign in to comment.