Skip to content

Commit

Permalink
feat: improvements in event bypass, gradle fix
Browse files Browse the repository at this point in the history
  • Loading branch information
yaansz committed Aug 25, 2024
1 parent 8794bdb commit d8a67d6
Show file tree
Hide file tree
Showing 14 changed files with 106 additions and 36 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up JDK
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'

- name: Build with Gradle
uses: gradle/gradle-build-action@v2
uses: gradle/gradle-build-action@v3
with:
arguments: build
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ test {
useJUnitPlatform()
}

sourceCompatibility = JavaVersion.VERSION_20
targetCompatibility = JavaVersion.VERSION_20
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
21 changes: 9 additions & 12 deletions src/main/java/com/softawii/curupira/example/controller/Foo.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.interactions.DiscordLocale;
import net.dv8tion.jda.api.utils.messages.MessagePollData;

@DiscordController(value = "bar", description = "foo foo foo", parent = "foo", permissions = {Permission.ADMINISTRATOR},
resource = "i18n", locales = {DiscordLocale.PORTUGUESE_BRAZILIAN})
Expand All @@ -26,29 +27,25 @@ public class Foo {
// }

@DiscordCommand(name = "qux", description = "qux qux qux")
public MessageEmbed qux(JDA jda,
LocalizationManager localization,
@RequestInfo Member member,
@LocaleType DiscordLocale locale,
@DiscordParameter(name = "title", description = "embed title") String title,
@DiscordParameter(name = "description", description = "embed description") String description) {
public MessagePollData qux(JDA jda,
LocalizationManager localization,
@RequestInfo Member member,
@LocaleType DiscordLocale locale,
@DiscordParameter(name = "title", description = "embed title") String title,
@DiscordParameter(name = "description", description = "embed description") String description) {

String titleMessage = localization.getLocalizedString("foo.bar.qux.embed.title", locale, title, member.getNickname());
String descriptionMessage = localization.getLocalizedString("foo.bar.qux.embed.description", locale, member.getEffectiveName(), jda.getSelfUser().getEffectiveName());

return new EmbedBuilder()
.setTitle(titleMessage)
.setDescription(descriptionMessage)
.addField("Field 1", description, false)
.build();
return MessagePollData.builder(titleMessage).addAnswer("yes").addAnswer("no").build();
}

@DiscordCommand(name = "charlie", description = "charlie charlie charlie")
public TextLocaleResponse charlie(
@RequestInfo Member member,
@DiscordParameter(name = "poll", description = "pool name") String name) {

throw new NullPointerException("This is a test exception");
throw new NullPointerException("test");
// return new TextLocaleResponse("foo.bar.charlie.response.ok", name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

import java.lang.reflect.InvocationTargetException;

@DiscordExceptions(packages = "com.softawii.curupira.example")
@DiscordExceptions
public class FooExceptionHandler {

private static final Logger LOGGER = LoggerFactory.getLogger(FooExceptionHandler.class);

@DiscordException(NullPointerException.class)
@DiscordException(Throwable.class)
public void handle(Throwable exception, Interaction interaction, LocalizationManager localization, @LocaleType DiscordLocale locale) {
LOGGER.error("An error occurred 2, info, exception: {}, user id: {}, user name: {}", exception, interaction.getUser().getIdLong(), interaction.getUser().getName());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
String description() default "";
boolean hidden() default false;
// Protection properties
// TODO: Owners Only
// TODO: V2.1 Owners Only
Permission[] permissions() default {};
DiscordEnvironment environment() default DiscordEnvironment.SERVER;
// I8n properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@
OptionType type() default OptionType.UNKNOWN;
boolean autoComplete() default false;
// TODO: Add choice support
// TODO: Add range support (arg1, arg2, arg3, etc.)
// TODO: V2.1 Add range support (arg1, arg2, arg3, etc.)
}
40 changes: 37 additions & 3 deletions src/main/java/com/softawii/curupira/v2/core/CurupiraBoot.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
import com.softawii.curupira.v2.core.exception.ExceptionMapper;
import com.softawii.curupira.v2.integration.ContextProvider;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.*;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.EntitySelectInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
Expand Down Expand Up @@ -39,9 +44,38 @@ public CurupiraBoot(@NotNull JDA jda, @NotNull ContextProvider context, boolean
}

@Override
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
this.logger.debug("Slash command interaction received. Event: {}", event);
public void onGenericCommandInteraction(@NotNull GenericCommandInteractionEvent event) {
this.logger.debug("Command interaction received. Event: {}", event);
this.mapper.onCommandInteractionReceived(event);
}

@Override
public void onModalInteraction(@NotNull ModalInteractionEvent event) {
// TODO: implement
super.onModalInteraction(event);
}

@Override
public void onButtonInteraction(@NotNull ButtonInteractionEvent event) {
// TODO: implement
super.onButtonInteraction(event);
}

@Override
public void onStringSelectInteraction(@NotNull StringSelectInteractionEvent event) {
// TODO: implement
super.onStringSelectInteraction(event);
}

@Override
public void onEntitySelectInteraction(@NotNull EntitySelectInteractionEvent event) {
// TODO: implement
super.onEntitySelectInteraction(event);
}

@Override
public void onCommandAutoCompleteInteraction(@NotNull CommandAutoCompleteInteractionEvent event) {
// TODO: implement
super.onCommandAutoCompleteInteraction(event);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import com.softawii.curupira.v2.annotations.DiscordController;
import com.softawii.curupira.v2.annotations.DiscordParameter;
import com.softawii.curupira.v2.api.TextLocaleResponse;
import com.softawii.curupira.v2.core.exception.MissingPermissionsException;
import com.softawii.curupira.v2.enums.DiscordEnvironment;
import com.softawii.curupira.v2.localization.LocalizationManager;
import com.softawii.curupira.v2.parser.DiscordToJavaParser;
import com.softawii.curupira.v2.parser.JavaToDiscordParser;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.events.interaction.command.GenericCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.DiscordLocale;
import net.dv8tion.jda.api.interactions.commands.CommandInteractionPayload;
Expand All @@ -24,23 +27,28 @@
import java.util.List;

class CommandHandler {
private static final ChannelType[] PRIVATE_CHANNELS = {
ChannelType.PRIVATE,
ChannelType.GROUP
};

private static final Logger logger = LoggerFactory.getLogger(CommandHandler.class);
private final JDA jda;
private final Object instance;
private final Method method;
// i18n
private final LocalizationManager localization;
private final DiscordLocale defaultLocale;
private final DiscordEnvironment environment;

private List<OptionData> options;
private boolean ephemeral;

public CommandHandler(JDA jda, Object instance, Method method, LocalizationFunction localization, DiscordLocale defaultLocale) {
public CommandHandler(JDA jda, Object instance, Method method, LocalizationFunction localization, DiscordLocale defaultLocale, DiscordEnvironment environment) {
this.jda = jda;
this.method = method;
this.instance = instance;
this.defaultLocale = defaultLocale;
this.localization = new LocalizationManager(localization, defaultLocale);
this.environment = environment;

register();
}
Expand Down Expand Up @@ -120,6 +128,13 @@ private Object[] getParameters(CommandInteractionPayload event) {
}

public void execute(GenericCommandInteractionEvent event) throws InvocationTargetException, IllegalAccessException {
// Guild Only: Discord don't allow to execute commands in DMs
// Both: no need to check if the command is available in the guild
// Private Only: Discord don't check this
if(environment == DiscordEnvironment.PRIVATE && !List.of(PRIVATE_CHANNELS).contains(event.getChannelType())) {
throw new MissingPermissionsException();
}

Object result = method.invoke(instance, getParameters(event));
// something to reply
if(result != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import net.dv8tion.jda.api.events.interaction.command.GenericCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.DiscordLocale;
import net.dv8tion.jda.api.interactions.commands.CommandInteractionPayload;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
Expand Down Expand Up @@ -108,13 +109,13 @@ private void scanClass(Class clazz) {

for(Method method : methods) {
this.logger.info("Found method: {}", method.getName());
CommandHandler handler = scanMethod(method, localization, defaultLocale);
CommandHandler handler = scanMethod(method, localization, defaultLocale, controllerInfo.environment());
registerCommand(handler, controllerInfo, method.getAnnotation(DiscordCommand.class), localization);
}
}

private CommandHandler scanMethod(Method method, LocalizationFunction localization, DiscordLocale defaultLocale) {
return new CommandHandler(jda, context.getInstance(method.getDeclaringClass()), method, localization, defaultLocale);
private CommandHandler scanMethod(Method method, LocalizationFunction localization, DiscordLocale defaultLocale, DiscordEnvironment environment) {
return new CommandHandler(jda, context.getInstance(method.getDeclaringClass()), method, localization, defaultLocale, environment);
}

private void registerCommand(CommandHandler handler, DiscordController controllerInfo, DiscordCommand commandInfo, LocalizationFunction localization) {
Expand Down Expand Up @@ -161,14 +162,13 @@ public void onCommandInteractionReceived(GenericCommandInteractionEvent event) {
if(commands.containsKey(event.getFullCommandName())) {
CommandHandler handler = commands.get(event.getFullCommandName());
try {
// TODO: Validate Environment
handler.execute(event);
} catch (InvocationTargetException | IllegalAccessException e) {
exceptionMapper.handle(handler.getControllerClass(), e, event, handler.getLocalization());
}
} else {
this.logger.error("Command not found: {}", event.getFullCommandName());
event.reply("Command not found").queue();
event.reply("Command not found").setEphemeral(true).queue();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.softawii.curupira.v2.core.exception;

public class CommandNotFoundException extends RuntimeException {
public CommandNotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public ExceptionHandler(Object instance) {
this.instance = instance;
this.handlers = new HashMap<>();
scanMethods();
checkMinimumRequirements();
}

private void scanMethods() {
Expand All @@ -45,6 +46,18 @@ private void scanMethods() {
}
}

private void checkMinimumRequirements() {
// only allow a class with a generic exception handler
if(handlers.isEmpty()) {
throw new RuntimeException("No exception handlers found");
}

// only allow a class with a generic exception handler
if(!handlers.containsKey(Throwable.class)) {
throw new RuntimeException("You need to provide a Throwable handler in " + this.instance.getClass().getName());
}
}

private Method getHandler(Class<?> exception) {
Method handler = handlers.get(exception);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.softawii.curupira.v2.core.exception;

public class MissingPermissionsException extends RuntimeException {
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

public class DiscordToJavaParser {

// TODO: Refactor this method to use a switch statement or a map to avoid the if-else chain
// TODO: V2.? Refactor this method to use a switch statement or a map to avoid the if-else chain
public static Object getParameterFromEvent(Interaction event, Parameter parameter, LocalizationManager localization) {
if(LocalizationManager.class.isAssignableFrom(parameter.getType())) {
return localization;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

public class JavaToDiscordParser {

// TODO: Refactor this method to use a switch statement or a map to avoid the if-else chain
// TODO: V2.? Refactor this method to use a switch statement or a map to avoid the if-else chain
public static OptionType getTypeFromClass(Class clazz) {
if (clazz.equals(String.class)) {
return OptionType.STRING;
Expand All @@ -45,7 +45,7 @@ public static OptionType getTypeFromClass(Class clazz) {
throw new RuntimeException("Type not supported");
}

// TODO: I don't known how to refactor this method to avoid the if-else chain, maybe in the future I will find a way
// TODO: V2.? I don't known how to refactor this method to avoid the if-else chain, maybe in the future I will find a way
public static void responseFromCommandEvent(GenericCommandInteractionEvent event, Object result, boolean ephemeral) {
if(result instanceof String response) {
event.reply(response).setEphemeral(ephemeral).queue();
Expand Down

0 comments on commit d8a67d6

Please sign in to comment.