Skip to content

Commit

Permalink
add Alias Roll command (#438)
Browse files Browse the repository at this point in the history
  • Loading branch information
twonirwana authored Feb 6, 2024
1 parent 884fbfb commit 615d0ec
Show file tree
Hide file tree
Showing 32 changed files with 927 additions and 81 deletions.
4 changes: 4 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,10 @@ For example `/r expression:3d6` will simply roll 3d6 and post the result without
The result of the dice will be summed up per default.
The output can be configured with the `channel_config` command.

==== Alias Roll

Alias Roll, used with the command `/a`, is variant of the direct roll which shows the list of available alias in the autocomplete. It is still possible roll normal dice expression or extend the alias. For example if there is an alias with the name `attack` it is possible to roll `attack +5`. Alias can be added and removed with the <<Channel Config>> command.

=== Hidden Direct Roll

image:image/hiddenDircetRoll.webp[image]
Expand Down
2 changes: 2 additions & 0 deletions bot/src/main/java/de/janno/discord/bot/Bot.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import de.janno.discord.bot.command.countSuccesses.CountSuccessesCommand;
import de.janno.discord.bot.command.customDice.CustomDiceCommand;
import de.janno.discord.bot.command.customParameter.CustomParameterCommand;
import de.janno.discord.bot.command.directRoll.AliasRollCommand;
import de.janno.discord.bot.command.directRoll.DirectRollCommand;
import de.janno.discord.bot.command.directRoll.HiddenDirectRollCommand;
import de.janno.discord.bot.command.directRoll.ValidationCommand;
Expand Down Expand Up @@ -65,6 +66,7 @@ public static void main(final String[] args) throws Exception {
DiscordConnectorImpl.createAndStart(
List.of(customDiceCommand,
new DirectRollCommand(persistenceManager, cachingDiceEvaluator),
new AliasRollCommand(persistenceManager, cachingDiceEvaluator),
new HiddenDirectRollCommand(persistenceManager, cachingDiceEvaluator),
new ValidationCommand(persistenceManager, cachingDiceEvaluator),
new ChannelConfigCommand(persistenceManager),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ protected Collection<CommandDefinitionOption> additionalCommandOptions() {
}

@Override
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest autoCompleteRequest, @NonNull Locale userLocale) {
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest autoCompleteRequest, @NonNull Locale userLocale, long channelId, long userId) {
return BaseCommandOptions.autoCompleteColorOption(autoCompleteRequest, userLocale);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public ChannelConfigCommand(PersistenceManager persistenceManager) {
}

@Override
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest autoCompleteRequest, @NonNull Locale userLocale) {
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest autoCompleteRequest, @NonNull Locale userLocale, long channelId, long userId) {
return BaseCommandOptions.autoCompleteColorOption(autoCompleteRequest, userLocale);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package de.janno.discord.bot.command.directRoll;

import com.google.common.base.Strings;
import de.janno.discord.bot.I18n;
import de.janno.discord.bot.command.channelConfig.Alias;
import de.janno.discord.bot.command.channelConfig.AliasHelper;
import de.janno.discord.bot.dice.CachingDiceEvaluator;
import de.janno.discord.bot.dice.DiceEvaluatorAdapter;
import de.janno.discord.bot.persistance.PersistenceManager;
import de.janno.discord.connector.api.AutoCompleteAnswer;
import de.janno.discord.connector.api.AutoCompleteRequest;
import de.janno.discord.connector.api.message.EmbedOrMessageDefinition;
import de.janno.discord.connector.api.slash.CommandDefinition;
import de.janno.discord.connector.api.slash.CommandDefinitionOption;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
public class AliasRollCommand extends DirectRollCommand {

public static final String ROLL_COMMAND_ID = "a";

public AliasRollCommand(PersistenceManager persistenceManager, CachingDiceEvaluator cachingDiceEvaluator) {
super(persistenceManager, cachingDiceEvaluator, "alias_or_expression");
}

@Override
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest option, @NonNull Locale userLocale, long channelId, long userId) {
List<Alias> channelAlias = AliasHelper.getChannelAlias(channelId, persistenceManager);
List<Alias> userAlias = AliasHelper.getUserChannelAlias(channelId, userId, persistenceManager);

Map<String, Alias> combinedAlias = channelAlias.stream().collect(Collectors.toMap(Alias::getName, Function.identity()));
userAlias.forEach(a -> combinedAlias.put(a.getName(), a)); //user alias overwrite channel alias
if (combinedAlias.isEmpty() && Strings.isNullOrEmpty(option.getFocusedOptionValue())) {
return List.of(new AutoCompleteAnswer(I18n.getMessage("a.autoComplete.missingAlias", userLocale), "help"));
}
List<AutoCompleteAnswer> filteredAlias = combinedAlias.values().stream()
.filter(p -> Strings.isNullOrEmpty(option.getFocusedOptionValue()) || p.getName().toLowerCase().contains(option.getFocusedOptionValue().toLowerCase()))
.sorted(Comparator.comparing(Alias::getName))
.map(p -> new AutoCompleteAnswer(p.getName(), p.getName()))
.collect(Collectors.toList());
if (filteredAlias.isEmpty()) {
return List.of(); //no autocomplete so the user can enter his own expression
}
return filteredAlias;
}

@Override
public @NonNull String getCommandId() {
return ROLL_COMMAND_ID;
}

@Override
public @NonNull CommandDefinition getCommandDefinition() {
return CommandDefinition.builder()
.name(getCommandId())
.nameLocales(I18n.allNoneEnglishMessagesNames("a.name"))
.description(I18n.getMessage("a.description", Locale.ENGLISH))
.descriptionLocales(I18n.allNoneEnglishMessagesDescriptions("a.description"))
.option(CommandDefinitionOption.builder()
.name(expressionOptionName)
.nameLocales(I18n.allNoneEnglishMessagesNames("a.expression.name"))
.description(I18n.getMessage("a.description", Locale.ENGLISH))
.descriptionLocales(I18n.allNoneEnglishMessagesDescriptions("a.description"))
.required(true)
.autoComplete(true)
.type(CommandDefinitionOption.Type.STRING)
.build())
.build();
}

protected EmbedOrMessageDefinition getHelpMessage(Locale userLocale) {
return EmbedOrMessageDefinition.builder()
.descriptionOrContent(I18n.getMessage("a.help.message", userLocale) + "\n" + DiceEvaluatorAdapter.getHelp())
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.example.field.name", userLocale), I18n.getMessage("a.help.example.alias.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.example.field.name", userLocale), I18n.getMessage("a.help.example.expression.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.documentation.field.name", userLocale), I18n.getMessage("help.documentation.field.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.discord.server.field.name", userLocale), I18n.getMessage("help.discord.server.field.value", userLocale), false))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,20 @@
public class DirectRollCommand implements SlashCommand {

public static final String ROLL_COMMAND_ID = "r";
protected static final String EXPRESSION_OPTION_NAME = "expression";
private static final String HELP = "help";
protected final String expressionOptionName;
protected final PersistenceManager persistenceManager;
private final DiceEvaluatorAdapter diceEvaluatorAdapter;
private final PersistenceManager persistenceManager;

public DirectRollCommand(PersistenceManager persistenceManager, CachingDiceEvaluator cachingDiceEvaluator) {
this(persistenceManager, cachingDiceEvaluator, "expression");
}


public DirectRollCommand(PersistenceManager persistenceManager, CachingDiceEvaluator cachingDiceEvaluator, String expressionOptionName) {
this.diceEvaluatorAdapter = new DiceEvaluatorAdapter(cachingDiceEvaluator);
this.persistenceManager = persistenceManager;
this.expressionOptionName = expressionOptionName;
}

@Override
Expand All @@ -67,7 +73,7 @@ public DirectRollCommand(PersistenceManager persistenceManager, CachingDiceEvalu
.description(I18n.getMessage("r.description", Locale.ENGLISH))
.descriptionLocales(I18n.allNoneEnglishMessagesDescriptions("r.description"))
.option(CommandDefinitionOption.builder()
.name(EXPRESSION_OPTION_NAME)
.name(expressionOptionName)
.nameLocales(I18n.allNoneEnglishMessagesNames("r.expression.name"))
.description(I18n.getMessage("r.description", Locale.ENGLISH))
.descriptionLocales(I18n.allNoneEnglishMessagesDescriptions("r.description"))
Expand Down Expand Up @@ -101,19 +107,14 @@ DirectRollConfig deserializeConfig(ChannelConfigDTO channelConfigDTO) {

final String commandString = event.getCommandString();

Optional<CommandInteractionOption> expressionOptional = event.getOption(EXPRESSION_OPTION_NAME);
Optional<CommandInteractionOption> expressionOptional = event.getOption(expressionOptionName);
if (expressionOptional.isPresent()) {
final String commandParameter = expressionOptional
.map(CommandInteractionOption::getStringValue)
.orElseThrow();
if (commandParameter.equals(HELP)) {
BotMetrics.incrementSlashHelpMetricCounter(getCommandId());
return event.replyWithEmbedOrMessageDefinition(EmbedOrMessageDefinition.builder()
.descriptionOrContent(I18n.getMessage("r.help.message", userLocale, I18n.getMessage(getCommandId() + ".name", userLocale)) + "\n" + DiceEvaluatorAdapter.getHelp())
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.example.field.name", userLocale), I18n.getMessage("r.help.example.value", userLocale, I18n.getMessage(getCommandId() + ".name", userLocale)), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.documentation.field.name", userLocale), I18n.getMessage("help.documentation.field.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.discord.server.field.name", userLocale), I18n.getMessage("help.discord.server.field.value", userLocale), false))
.build(), true);
return event.replyWithEmbedOrMessageDefinition(getHelpMessage(userLocale), true);
}

final String expressionWithOptionalLabelsAndAppliedAliases = AliasHelper.getAndApplyAliaseToExpression(event.getChannelId(), event.getUserId(), persistenceManager, commandParameter);
Expand All @@ -139,6 +140,15 @@ DirectRollConfig deserializeConfig(ChannelConfigDTO channelConfigDTO) {
return Mono.empty();
}

protected EmbedOrMessageDefinition getHelpMessage(Locale userLocale) {
return EmbedOrMessageDefinition.builder()
.descriptionOrContent(I18n.getMessage("r.help.message", userLocale) + "\n" + DiceEvaluatorAdapter.getHelp())
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.example.field.name", userLocale), I18n.getMessage("r.help.example.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.documentation.field.name", userLocale), I18n.getMessage("help.documentation.field.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.discord.server.field.name", userLocale), I18n.getMessage("help.discord.server.field.value", userLocale), false))
.build();
}

protected @NonNull Mono<Void> createResponse(@NonNull SlashEventAdaptor event,
@NonNull String commandString,
@NonNull String diceExpression,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import de.janno.discord.bot.command.RollAnswer;
import de.janno.discord.bot.command.RollAnswerConverter;
import de.janno.discord.bot.dice.CachingDiceEvaluator;
import de.janno.discord.bot.dice.DiceEvaluatorAdapter;
import de.janno.discord.bot.persistance.PersistenceManager;
import de.janno.discord.connector.api.BottomCustomIdUtils;
import de.janno.discord.connector.api.ButtonEventAdaptor;
Expand Down Expand Up @@ -48,7 +49,7 @@ public HiddenDirectRollCommand(PersistenceManager persistenceManager, CachingDic
.description(I18n.getMessage("h.description", Locale.ENGLISH))
.descriptionLocales(I18n.allNoneEnglishMessagesDescriptions("h.description"))
.option(CommandDefinitionOption.builder()
.name(EXPRESSION_OPTION_NAME)
.name(expressionOptionName)
.nameLocales(I18n.allNoneEnglishMessagesNames("r.expression.name"))
.description(I18n.getMessage("h.description", Locale.ENGLISH))
.descriptionLocales(I18n.allNoneEnglishMessagesDescriptions("h.description"))
Expand Down Expand Up @@ -113,4 +114,13 @@ public Mono<Void> handleComponentInteractEvent(@NonNull ButtonEventAdaptor event
public boolean matchingComponentCustomId(String buttonCustomId) {
return Objects.equals(getCommandId(), BottomCustomIdUtils.getCommandNameFromCustomId(buttonCustomId));
}

protected EmbedOrMessageDefinition getHelpMessage(Locale userLocale) {
return EmbedOrMessageDefinition.builder()
.descriptionOrContent(I18n.getMessage("h.help.message", userLocale) + "\n" + DiceEvaluatorAdapter.getHelp())
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.example.field.name", userLocale), I18n.getMessage("h.help.example.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.documentation.field.name", userLocale), I18n.getMessage("help.documentation.field.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.discord.server.field.name", userLocale), I18n.getMessage("help.discord.server.field.value", userLocale), false))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import de.janno.discord.connector.api.AutoCompleteAnswer;
import de.janno.discord.connector.api.AutoCompleteRequest;
import de.janno.discord.connector.api.SlashEventAdaptor;
import de.janno.discord.connector.api.message.EmbedOrMessageDefinition;
import de.janno.discord.connector.api.slash.CommandDefinition;
import de.janno.discord.connector.api.slash.CommandDefinitionOption;
import lombok.NonNull;
Expand All @@ -38,8 +39,8 @@ public ValidationCommand(PersistenceManager persistenceManager, CachingDiceEvalu
}

@Override
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest option, @NonNull Locale userLocale) {
if (!EXPRESSION_OPTION_NAME.equals(option.getFocusedOptionName())) {
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest option, @NonNull Locale userLocale, long channelId, long userId) {
if (!expressionOptionName.equals(option.getFocusedOptionName())) {
return List.of();
}
if (Strings.isNullOrEmpty(option.getFocusedOptionValue())) {
Expand All @@ -52,11 +53,11 @@ public ValidationCommand(PersistenceManager persistenceManager, CachingDiceEvalu
.orElse(List.of(getValidAutoCompleteMessage(option.getFocusedOptionValue(), userLocale)));
}

private AutoCompleteAnswer getValidAutoCompleteMessage(@NonNull String typedExpression, @NonNull Locale userLocale){
if(typedExpression.length() <= 100){
private AutoCompleteAnswer getValidAutoCompleteMessage(@NonNull String typedExpression, @NonNull Locale userLocale) {
if (typedExpression.length() <= 100) {
return new AutoCompleteAnswer(typedExpression, typedExpression);
}
return new AutoCompleteAnswer(I18n.getMessage("validation.autoComplete.tooLong", userLocale), I18n.getMessage("validation.autoComplete.tooLong", userLocale));
return new AutoCompleteAnswer(I18n.getMessage("validation.autoComplete.tooLong", userLocale), "'" + I18n.getMessage("validation.autoComplete.tooLong", userLocale) + "'");
}

@Override
Expand All @@ -72,8 +73,8 @@ private AutoCompleteAnswer getValidAutoCompleteMessage(@NonNull String typedExpr
.description(I18n.getMessage("validation.description", Locale.ENGLISH))
.descriptionLocales(I18n.allNoneEnglishMessagesDescriptions("validation.description"))
.option(CommandDefinitionOption.builder()
.name(EXPRESSION_OPTION_NAME)
.nameLocales(I18n.allNoneEnglishMessagesNames("r.expression.name"))
.name(expressionOptionName)
.nameLocales(I18n.allNoneEnglishMessagesNames("validation.expression.name"))
.description(I18n.getMessage("validation.description", Locale.ENGLISH))
.descriptionLocales(I18n.allNoneEnglishMessagesDescriptions("validation.description"))
.required(true)
Expand Down Expand Up @@ -105,4 +106,13 @@ private AutoCompleteAnswer getValidAutoCompleteMessage(@NonNull String typedExpr
)
.parallel().then();
}

protected EmbedOrMessageDefinition getHelpMessage(Locale userLocale) {
return EmbedOrMessageDefinition.builder()
.descriptionOrContent(I18n.getMessage("validation.help.message", userLocale) + "\n" + DiceEvaluatorAdapter.getHelp())
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.example.field.name", userLocale), I18n.getMessage("validation.help.example.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.documentation.field.name", userLocale), I18n.getMessage("help.documentation.field.value", userLocale), false))
.field(new EmbedOrMessageDefinition.Field(I18n.getMessage("help.discord.server.field.name", userLocale), I18n.getMessage("help.discord.server.field.value", userLocale), false))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static Optional<RpgSystemCommandPreset.PresetId> getPresetId(@NonNull String id,
}

@Override
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest option, @NonNull Locale userLocale) {
public @NonNull List<AutoCompleteAnswer> getAutoCompleteAnswer(@NonNull AutoCompleteRequest option, @NonNull Locale userLocale, long channelId, long userId) {
if (!SYSTEM_OPTION_NAME.equals(option.getFocusedOptionName())) {
return List.of();
}
Expand Down
Loading

0 comments on commit 615d0ec

Please sign in to comment.