Skip to content

Commit

Permalink
🚀 Reworked reply and edit effect to work with interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsTheSky committed Apr 21, 2024
1 parent 7c8644e commit 6158404
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
import ch.njol.skript.util.AsyncEffect;
import ch.njol.util.Kleenean;
import info.itsthesky.disky.DiSky;
import info.itsthesky.disky.api.events.specific.InteractionEvent;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.interactions.InteractionHook;
import net.dv8tion.jda.api.interactions.components.ComponentInteraction;
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import net.dv8tion.jda.api.utils.messages.MessageEditBuilder;
import org.bukkit.event.Event;
Expand All @@ -37,7 +39,7 @@ public class EditMessage extends AsyncEffect {
static {
Skript.registerEffect(
EditMessage.class,
"edit [the] [message] %message/interactionhook% (with|to show) %string/messagecreatebuilder/embedbuilder%"
"edit [the] [message] %message% (with|to show) %string/messagecreatebuilder/embedbuilder%"
);
}

Expand Down Expand Up @@ -71,17 +73,23 @@ else if (message instanceof EmbedBuilder)
final MessageEditBuilder editBuilder = new MessageEditBuilder().applyCreateData(builder.build());

try {
if (target instanceof Message)
// Basically, here we check if it's an interaction event, if that event holds a ComponentInteraction,
// and also if the provided message's ID is the original message of the interaction.
// ==> Why? In interactions, we have to edit the interaction itself, and not the message.
if (e instanceof InteractionEvent
&& ((InteractionEvent) e).getInteractionEvent().getInteraction() instanceof ComponentInteraction
&& ((ComponentInteraction) ((InteractionEvent) e).getInteractionEvent().getInteraction()).getMessageId().equals(((Message) target).getId()))
((ComponentInteraction) ((InteractionEvent) e).getInteractionEvent().getInteraction()).editMessage(editBuilder.build()).complete();

else if (target instanceof Message)
((Message) target).editMessage(editBuilder.build()).complete();
else
((InteractionHook) target).editOriginal(editBuilder.build()).complete();
} catch (Exception ex) {
DiSky.getErrorHandler().exception(e, ex);
}
}

@Override
public @NotNull String toString(@Nullable Event e, boolean debug) {
return "edit the message/hook " + exprTarget.toString(e, debug) + " with " + exprMessage.toString(e, debug);
return "edit the message/interaction " + exprTarget.toString(e, debug) + " with " + exprMessage.toString(e, debug);
}
}
100 changes: 64 additions & 36 deletions src/main/java/info/itsthesky/disky/elements/effects/ReplyWith.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
package info.itsthesky.disky.elements.effects;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.Changer;
import ch.njol.skript.config.Node;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser;
import ch.njol.skript.lang.Variable;
import ch.njol.skript.util.AsyncEffect;
import ch.njol.util.Kleenean;
import info.itsthesky.disky.DiSky;
import info.itsthesky.disky.api.events.specific.InteractionEvent;
import info.itsthesky.disky.api.events.specific.MessageEvent;
import info.itsthesky.disky.api.skript.SpecificBotEffect;
import info.itsthesky.disky.core.Bot;
import info.itsthesky.disky.core.SkriptUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.entities.sticker.Sticker;
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
import net.dv8tion.jda.api.requests.RestAction;
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import net.dv8tion.jda.api.utils.messages.MessageEditData;
import net.dv8tion.jda.api.utils.messages.MessagePollBuilder;
import org.bukkit.event.Event;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static info.itsthesky.disky.api.skript.EasyElement.containsInterfaces;
import static info.itsthesky.disky.api.skript.EasyElement.parseSingle;

@Name("Reply With")
@Description({"Reply with a specific message to the channel where a message-event was triggered.",
"It can also be used to acknowledge & reply to an interaction, such as button click or slash command.",
Expand All @@ -38,7 +46,7 @@
"wait a second",
"edit {_msg} to show \"... world!\""})
@Since("4.4.0")
public class ReplyWith extends SpecificBotEffect<Object> {
public class ReplyWith extends AsyncEffect {

static {
Skript.registerEffect(
Expand All @@ -47,44 +55,47 @@ public class ReplyWith extends SpecificBotEffect<Object> {
);
}

private Node node;
private Expression<Object> exprMessage;
private Expression<Message> exprReference;
private Expression<Object> exprResult;
private boolean hidden;

@Override
public boolean initEffect(Expression<?>[] expressions, int i, Kleenean kleenean, SkriptParser.ParseResult parseResult) {
public boolean init(Expression<?>[] expressions, int i, Kleenean kleenean, SkriptParser.ParseResult parseResult) {
if (!containsInterfaces(MessageEvent.class)) {
Skript.error("The effect reply effect can only be used in a message event.");
return false;
}

node = getParser().getNode();
hidden = parseResult.expr.startsWith("reply with hidden");
exprMessage = (Expression<Object>) expressions[0];
exprReference = (Expression<Message>) expressions[1];
setChangedVariable((Variable<Object>) expressions[2]);
exprResult = (Expression<Object>) expressions[2];

return true;
return exprResult == null || Changer.ChangerUtils.acceptsChange(exprResult, Changer.ChangeMode.SET, Message.class);
}

@Override
public void runEffect(@NotNull Event e, @NotNull Bot bot) {
public void execute(@NotNull Event e) {
final Object message = parseSingle(exprMessage, e);
final Message reference = parseSingle(exprReference, e);
if (message == null) {
restart();
if (message == null)
return;
}

@Nullable RestAction<Message> messageRestAction = null;
@Nullable RestAction<?> otherRestAction = null;

if (message instanceof Sticker) {
final MessageEvent event = (MessageEvent) e;
if (!(event.getMessageChannel() instanceof GuildMessageChannel)) {
Skript.error("You can't reply with a sticker in a guild channel!");
SkriptUtils.error(node, "You can't reply with a sticker in a guild channel!");
return;
}
((GuildMessageChannel) event.getMessageChannel()).sendStickers((Sticker) message).setMessageReference(reference).queue(this::restart, ex -> {
DiSky.getErrorHandler().exception(e, ex);
restart();
});
messageRestAction =((GuildMessageChannel) event.getMessageChannel())
.sendStickers((Sticker) message)
.setMessageReference(reference);
} else {
final MessageCreateBuilder builder;
if (message instanceof MessageCreateBuilder)
Expand All @@ -94,48 +105,65 @@ else if (message instanceof EmbedBuilder)
else
builder = new MessageCreateBuilder().setContent((String) message);

if (!builder.isValid()) {
SkriptUtils.error(node, "The provided message is not valid!");
return;
}

if (e instanceof InteractionEvent) {
final InteractionEvent event = (InteractionEvent) e;
if (!(event.getInteractionEvent().getInteraction() instanceof IReplyCallback)) {
Skript.error("You are trying to reply to an interaction that is not a reply callback.");
restart();
SkriptUtils.error(node,"You are trying to reply or defer an interaction that is not a reply callback!");
return;
}

final IReplyCallback callback = (IReplyCallback) event.getInteractionEvent().getInteraction();

if (DeferInteraction.WAITING_INTERACTIONS.contains(callback.getHook().getInteraction().getIdLong())) {
DeferInteraction.WAITING_INTERACTIONS.remove(callback.getHook().getInteraction().getIdLong());
callback.getHook().editOriginal(MessageEditData.fromCreateData(builder.build())).queue(this::restart, ex -> {
DiSky.getErrorHandler().exception(e, ex);
restart();
});
return;
messageRestAction = callback.getHook().editOriginal(MessageEditData.fromCreateData(builder.build()));
} else {
if (event.getInteractionEvent().getInteraction().isAcknowledged()) {
SkriptUtils.error(node,"You are trying to reply or defer an interaction that has already been acknowledged!");
return;
}

otherRestAction = callback.reply(builder.build()).setEphemeral(hidden);
}
} else {
final MessageEvent event = (MessageEvent) e;
messageRestAction = event.getMessageChannel().sendMessage(builder.build()).setMessageReference(reference);
}
}

if (event.getInteractionEvent().getInteraction().isAcknowledged()) {
Skript.error("You are trying to reply or defer an interaction that has already been acknowledged!");
restart();
return;
}
if (messageRestAction != null) {

callback.reply(builder.build()).setEphemeral(hidden).queue(this::restart, ex -> {
DiSky.getErrorHandler().exception(e, ex);
restart();
});
final Message result;
try {
result = messageRestAction.complete();
} catch (Exception ex) {
DiSky.getErrorHandler().exception(e, ex);
return;
}

} else {
final MessageEvent event = (MessageEvent) e;
event.getMessageChannel().sendMessage(builder.build()).setMessageReference(reference).queue(this::restart, ex -> {
DiSky.getErrorHandler().exception(e, ex);
restart();
});
if (exprResult != null)
exprResult.change(e, new Message[] {result}, Changer.ChangeMode.SET);
}

if (otherRestAction != null) {
try {
otherRestAction.complete();
} catch (Exception ex) {
DiSky.getErrorHandler().exception(e, ex);
}
}
}

@Override
public @NotNull String toString(@Nullable Event e, boolean debug) {
return null;
return "reply with " + exprMessage.toString(e, debug) + (hidden ? " hidden" : "")
+ (exprReference != null ? " with reference " + exprReference.toString(e, debug) : "")
+ (exprResult != null ? " and store it in " + exprResult.toString(e, debug) : "");
}

}

0 comments on commit 6158404

Please sign in to comment.