added conventions for templated commands, to reduce the amount of necessary configuration

added an exception, in case the command was missing the correct types of parameters (channel is required, no channel was found)
added fix text to exception handler, in case the message of an exception is null
fixed off-by-one error when searching the missing parameter
changed supported chanel from guildChannel to textChannel for posttarget
added slowmode command
This commit is contained in:
Sheldan
2020-03-18 21:06:27 +01:00
parent 9119d57108
commit ec21305725
21 changed files with 212 additions and 42 deletions

View File

@@ -53,11 +53,11 @@ public class Ban implements Command {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").type(Member.class).optional(false).build());
parameters.add(Parameter.builder().name("reason").type(String.class).optional(true).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().usageTemplate("ban_usage").longHelpTemplate("ban_long_help").build();
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("ban")
.module(Moderation.MODERATION)
.descriptionTemplate("ban_help_description")
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)

View File

@@ -50,11 +50,11 @@ public class Kick implements Command {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").type(Member.class).optional(false).build());
parameters.add(Parameter.builder().name("reason").type(String.class).optional(true).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().usageTemplate("kick_usage").longHelpTemplate("kick_long_help").build();
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("kick")
.module(Moderation.MODERATION)
.descriptionTemplate("kick_help_description")
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)

View File

@@ -0,0 +1,56 @@
package dev.sheldan.abstracto.moderation.command;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.HelpInfo;
import dev.sheldan.abstracto.command.execution.CommandConfiguration;
import dev.sheldan.abstracto.command.execution.CommandContext;
import dev.sheldan.abstracto.command.execution.Parameter;
import dev.sheldan.abstracto.command.execution.Result;
import dev.sheldan.abstracto.moderation.Moderation;
import dev.sheldan.abstracto.moderation.service.SlowModeService;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
@Component
public class SlowMode implements Command {
@Autowired
private SlowModeService slowModeService;
@Override
public Result execute(CommandContext commandContext) {
TextChannel channel;
long seconds = (Long) commandContext.getParameters().getParameters().get(0);
if(commandContext.getParameters().getParameters().size() == 2) {
channel = (TextChannel) commandContext.getParameters().getParameters().get(1);
if(commandContext.getGuild().getGuildChannelById(channel.getIdLong()) == null) {
throw new IllegalArgumentException("Given channel was not part of the current guild.");
}
} else {
channel = commandContext.getChannel();
}
slowModeService.setSlowMode(channel, Duration.ofSeconds(seconds));
return Result.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("seconds").type(Long.class).optional(false).build());
parameters.add(Parameter.builder().name("channel").type(TextChannel.class).optional(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("slowmode")
.module(Moderation.MODERATION)
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
}

View File

@@ -56,11 +56,11 @@ public class Warn implements Command {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("user").type(Member.class).optional(false).build());
parameters.add(Parameter.builder().name("reason").type(String.class).optional(true).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().usageTemplate("warn_usage").longHelpTemplate("long_help").build();
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("warn")
.module(Moderation.MODERATION)
.descriptionTemplate("warn_help_description")
.templated(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.AChannel;
import dev.sheldan.abstracto.core.service.Bot;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Duration;
@Component
@Slf4j
public class SlowModeServiceBean implements SlowModeService {
@Autowired
private Bot bot;
@Override
public void setSlowMode(TextChannel channel, Duration duration) {
long seconds = duration.getSeconds();
if(seconds > TextChannel.MAX_SLOWMODE) {
throw new IllegalArgumentException("Slow mode duration must be < " + TextChannel.MAX_SLOWMODE + " seconds.");
}
channel.getManager().setSlowmode((int) seconds).queue();
}
@Override
public void setSlowMode(AChannel channel, Duration duration) {
JDA jpaInstance = bot.getInstance();
Guild guild = jpaInstance.getGuildById(channel.getServer().getId());
if(guild != null) {
TextChannel textChannelById = guild.getTextChannelById(channel.getId());
if(textChannelById != null) {
this.setSlowMode(textChannelById, duration);
} else {
log.warn("Channel {} was not found in guild {} when trying to set a slow mode.", channel.getId(), channel.getServer().getId());
}
} else {
log.warn("Guild {} was not found when trying to set slow mode.", channel.getServer().getId());
}
}
}

View File

@@ -0,0 +1 @@
Sets the slow mode of the the current (or given channel) to the given seconds.

View File

@@ -0,0 +1 @@
The slowmode in channel ${channel.name} has been set to ${channel.slowMode} seconds.

View File

@@ -0,0 +1 @@
Sets the slow mode of the the current (or given channel) to the given seconds.

View File

@@ -0,0 +1,11 @@
package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.AChannel;
import net.dv8tion.jda.api.entities.TextChannel;
import java.time.Duration;
public interface SlowModeService {
void setSlowMode(TextChannel channel, Duration duration);
void setSlowMode(AChannel channel, Duration duration);
}

View File

@@ -7,6 +7,5 @@ import lombok.Getter;
public class HelpInfo {
private String usage;
private String longHelp;
private String longHelpTemplate;
private String usageTemplate;
private boolean templated;
}

View File

@@ -13,9 +13,9 @@ public class CommandConfiguration {
private String name;
private String module;
private String description;
private String descriptionTemplate;
private List<Parameter> parameters;
private boolean causesReaction;
private boolean templated;
private HelpInfo help;
public int getNecessaryParameterCount(){

View File

@@ -34,7 +34,7 @@ public class CommandManager implements CommandRegistry {
boolean paramCountFits = unParsedCommandParameter.getParameters().size() >= commandConfiguration.getNecessaryParameterCount();
boolean hasRemainderParameter = commandConfiguration.getParameters().stream().anyMatch(Parameter::isRemainder);
if(unParsedCommandParameter.getParameters().size() < commandConfiguration.getNecessaryParameterCount()) {
String nextParameterName = commandConfiguration.getParameters().get(commandConfiguration.getNecessaryParameterCount()).getName();
String nextParameterName = commandConfiguration.getParameters().get(commandConfiguration.getNecessaryParameterCount() - 1).getName();
throw new InsufficientParametersException("Insufficient parameters", o, nextParameterName);
}
parameterFit = paramCountFits || hasRemainderParameter;

View File

@@ -4,6 +4,8 @@ import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.PostCommandExecution;
import dev.sheldan.abstracto.command.execution.*;
import dev.sheldan.abstracto.command.meta.UnParsedCommandParameter;
import dev.sheldan.abstracto.commands.management.exception.IncorrectParameterException;
import dev.sheldan.abstracto.commands.management.exception.InsufficientParametersException;
import dev.sheldan.abstracto.core.management.ChannelManagementService;
import dev.sheldan.abstracto.core.management.ServerManagementService;
import dev.sheldan.abstracto.core.models.AChannel;
@@ -11,6 +13,7 @@ import dev.sheldan.abstracto.core.models.AServer;
import net.dv8tion.jda.api.entities.GuildChannel;
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.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,9 +21,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
@Service
public class CommandReceivedHandler extends ListenerAdapter {
@@ -84,25 +85,30 @@ public class CommandReceivedHandler extends ListenerAdapter {
public Parameters getParsedParameters(UnParsedCommandParameter unParsedCommandParameter, Command command, Message message){
List<Object> parsedParameters = new ArrayList<>();
int mentionedChannelsCount = 0;
int mentionedUserCount = 0;
for (int i = 0; i < unParsedCommandParameter.getParameters().size(); i++) {
Parameter param = command.getConfiguration().getParameters().get(i);
String value = unParsedCommandParameter.getParameters().get(i);
if(param.getType().equals(Integer.class)){
parsedParameters.add(Integer.parseInt(value));
} else if(param.getType().equals(Double.class)){
parsedParameters.add(Double.parseDouble(value));
} else if(param.getType().equals(GuildChannel.class)){
parsedParameters.add(message.getMentionedChannels().get(mentionedChannelsCount));
mentionedChannelsCount++;
} else if(param.getType().equals(Member.class)) {
parsedParameters.add(message.getMentionedMembers().get(mentionedUserCount));
mentionedUserCount++;
} else {
parsedParameters.add(value);
Iterator<TextChannel> channelIterator = message.getMentionedChannels().iterator();
Iterator<Member> memberIterator = message.getMentionedMembers().iterator();
for (int i = 0; i < unParsedCommandParameter.getParameters().size(); i++) {
Parameter param = command.getConfiguration().getParameters().get(i);
String value = unParsedCommandParameter.getParameters().get(i);
try {
if(param.getType().equals(Integer.class)){
parsedParameters.add(Integer.parseInt(value));
} else if(param.getType().equals(Double.class)){
parsedParameters.add(Double.parseDouble(value));
} else if(param.getType().equals(Long.class)){
parsedParameters.add(Long.parseLong(value));
} else if(param.getType().equals(TextChannel.class)){
parsedParameters.add(channelIterator.next());
} else if(param.getType().equals(Member.class)) {
parsedParameters.add(memberIterator.next());
} else {
parsedParameters.add(value);
}
} catch (NoSuchElementException e) {
throw new IncorrectParameterException("The passed parameters did not have the correct type.", command, param.getType(), param.getName());
}
}
}
return Parameters.builder().parameters(parsedParameters).build();
}
}

View File

@@ -0,0 +1,33 @@
package dev.sheldan.abstracto.commands.management.exception;
import dev.sheldan.abstracto.command.Command;
import dev.sheldan.abstracto.command.TemplatedException;
import java.util.HashMap;
public class IncorrectParameterException extends RuntimeException implements TemplatedException {
private Command command;
private String parameterName;
private Class clazz;
public IncorrectParameterException(String s, Command command, Class expected, String parameterName) {
super(s);
this.command = command;
this.parameterName = parameterName;
this.clazz = expected;
}
@Override
public String getTemplateName() {
return "incorrect_parameters";
}
@Override
public Object getTemplateModel() {
HashMap<String, Object> model = new HashMap<>();
model.put("parameterName", parameterName);
model.put("class", this.clazz);
return model;
}
}

View File

@@ -25,7 +25,7 @@ public class ExceptionPostExecution implements PostCommandExecution {
String text = templateService.renderTemplate(exception.getTemplateName(), exception.getTemplateModel());
commandContext.getChannel().sendMessage(text).queue();
} else {
commandContext.getChannel().sendMessage(result.getMessage()).queue();
commandContext.getChannel().sendMessage("Exception: " + result.getThrowable().getClass() + ": " + result.getMessage()).queue();
}
}
}

View File

@@ -0,0 +1 @@
The necessary parameters were not found. A '${class.simpleName}' was expected as '${parameterName}'. Consult help to see the correct syntax.

View File

@@ -10,9 +10,9 @@ import dev.sheldan.abstracto.core.management.PostTargetManagement;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildChannel;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
@@ -39,7 +39,7 @@ public class SetPostTargetCommand implements Command {
@Override
public CommandConfiguration getConfiguration() {
Parameter channel = Parameter.builder().name("channel").type(GuildChannel.class).description("The channel to post towards").build();
Parameter channel = Parameter.builder().name("channel").type(TextChannel.class).description("The channel to post towards").build();
Parameter postTargetName = Parameter.builder().name("name").type(String.class).description("The name of the post target to redirect").build();
List<Parameter> parameters = Arrays.asList(postTargetName, channel);
return CommandConfiguration.builder()

View File

@@ -61,20 +61,35 @@ public class Help implements Command {
CommandConfiguration commandConfiguration = command.getConfiguration();
sb.append(String.format("Command: **%s**", commandConfiguration.getName()));
sb.append("\n");
sb.append(String.format("Description: %s", getTemplateOrDefault(commandConfiguration.getDescriptionTemplate(), commandConfiguration.getDescription())));
String descriptionTemplate = getDescriptionTemplate(commandConfiguration.getName());
sb.append(String.format("Description: %s", getTemplateOrDefault(commandConfiguration, descriptionTemplate, commandConfiguration.getDescription())));
sb.append("\n");
HelpInfo helpObj = commandConfiguration.getHelp();
if(helpObj != null){
sb.append(String.format("Usage: %s", getTemplateOrDefault(helpObj.getUsageTemplate(), helpObj.getUsage())));
String usageTemplate = getUsageTemplate(commandConfiguration.getName());
sb.append(String.format("Usage: %s", getTemplateOrDefault(commandConfiguration, usageTemplate, helpObj.getUsage())));
sb.append("\n");
sb.append(String.format("Detailed help: %s", getTemplateOrDefault(helpObj.getLongHelpTemplate(), helpObj.getLongHelp())));
String longHelpTemplate = getLongHelpTemplate(commandConfiguration.getName());
sb.append(String.format("Detailed help: %s", getTemplateOrDefault(commandConfiguration, longHelpTemplate, helpObj.getLongHelp())));
sb.append("\n");
}
return sb.toString();
}
private String getTemplateOrDefault(String templateKey, String defaultText) {
if(templateKey == null) {
private String getDescriptionTemplate(String commandName) {
return commandName + "_description";
}
private String getUsageTemplate(String commandName) {
return commandName + "_usage";
}
private String getLongHelpTemplate(String commandName) {
return commandName + "_long_help";
}
private String getTemplateOrDefault(CommandConfiguration commandConfiguration, String templateKey, String defaultText) {
if(templateKey == null || !commandConfiguration.isTemplated()) {
return defaultText;
} else {
return templateService.renderTemplate(templateKey, null);

View File

@@ -37,11 +37,11 @@ public class Echo implements Command {
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("input").type(String.class).remainder(true).build());
HelpInfo helpInfo = HelpInfo.builder().usageTemplate("echo_usage").longHelpTemplate("echo_long_help").build();
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("echo")
.module("utility")
.descriptionTemplate("echo_description")
.templated(true)
.causesReaction(false)
.parameters(parameters)
.help(helpInfo)

View File

@@ -31,7 +31,7 @@ public class Ping implements Command {
return CommandConfiguration.builder()
.name("ping")
.module("utility")
.descriptionTemplate("ping_description")
.templated(true)
.causesReaction(false)
.build();
}