Skip to content

Commit

Permalink
Merge pull request #356 from Java-Discord/dynxsty/preference_improvem…
Browse files Browse the repository at this point in the history
…ents

Improved User Preferences by using Strings instead of Booleans
  • Loading branch information
jasonlessenich authored Sep 24, 2022
2 parents 5234032 + ca0668e commit 5891fe6
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected void execute(JobExecutionContext context, @NotNull JDA jda) throws Job
for (QOTWSubmission submission : submissions) {
UserPreferenceService manager = new UserPreferenceService(Bot.getDataSource());
UserPreference preference = manager.getOrCreate(submission.getAuthorId(), Preference.QOTW_REMINDER);
if (preference.isEnabled()) {
if (Boolean.parseBoolean(preference.getState())) {
TextChannel channel = config.getSubmissionChannel();
channel.getThreadChannels().stream().filter(t -> t.getIdLong() == submission.getThreadId()).forEach(t -> {
if (t.getMessageCount() <= 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@ public class UserPreferenceService {
*
* @param userId The users' id.
* @param preference The {@link Preference} to change the state for.
* @param enabled The preferences' state.
* @param state The preferences' state.
* @return Whether the operation was successful.
*/
public boolean setOrCreate(long userId, Preference preference, boolean enabled) {
public boolean setOrCreate(long userId, Preference preference, String state) {
try (Connection con = dataSource.getConnection()) {
UserPreferenceRepository repo = new UserPreferenceRepository(con);
Optional<UserPreference> preferenceOptional = repo.getById(userId, preference);
if (preferenceOptional.isPresent()) {
return repo.updateState(userId, preference, enabled);
return repo.updateState(userId, preference, state);
} else {
UserPreference userPreference = new UserPreference();
userPreference.setUserId(userId);
userPreference.setPreference(preference);
userPreference.setEnabled(enabled);
userPreference.setState(state);
repo.insert(userPreference, false);
return true;
}
Expand All @@ -64,7 +64,7 @@ public UserPreference getOrCreate(long userId, Preference preference) {
UserPreference userPreference = new UserPreference();
userPreference.setUserId(userId);
userPreference.setPreference(preference);
userPreference.setEnabled(preference.getDefaultState());
userPreference.setState(preference.getDefaultState());
repo.insert(userPreference, false);
return userPreference;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package net.javadiscord.javabot.systems.user_preferences.commands;

import com.dynxsty.dih4jda.interactions.commands.SlashCommand;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.javadiscord.javabot.Bot;
Expand All @@ -9,9 +12,6 @@
import net.javadiscord.javabot.util.Responses;
import org.jetbrains.annotations.NotNull;

import java.util.Arrays;
import java.util.stream.Collectors;

/**
* <h3>This class represents the /preferences list command.</h3>
*/
Expand All @@ -25,10 +25,24 @@ public PreferencesListSubcommand() {

@Override
public void execute(@NotNull SlashCommandInteractionEvent event) {
UserPreferenceService manager = new UserPreferenceService(Bot.getDataSource());
String preferences = Arrays.stream(Preference.values())
.map(p -> String.format("`%s` %s", manager.getOrCreate(event.getUser().getIdLong(), p).isEnabled() ? "\uD83D\uDFE2" : "\uD83D\uDD34", p))
.collect(Collectors.joining("\n"));
Responses.info(event, String.format("%s's Preferences", event.getUser().getName()), preferences).queue();
event.replyEmbeds(buildPreferencesEmbed(new UserPreferenceService(Bot.getDataSource()), event.getUser()))
.setEphemeral(true)
.queue();
}

private @NotNull MessageEmbed buildPreferencesEmbed(UserPreferenceService service, @NotNull User user) {
EmbedBuilder builder = new EmbedBuilder()
.setAuthor(user.getAsTag(), null, user.getEffectiveAvatarUrl())
.setTitle(user.getName() + "'s Preferences")
.setColor(Responses.Type.INFO.getColor());
for (Preference p : Preference.values()) {
builder.addField(buildPreferenceField(user, service, p));
}
return builder.build();
}

private MessageEmbed.@NotNull Field buildPreferenceField(@NotNull User user, @NotNull UserPreferenceService service, Preference preference) {
String state = service.getOrCreate(user.getIdLong(), preference).getState();
return new MessageEmbed.Field(preference.toString(), state.isEmpty() ? String.format("`%s` has not yet been set.", preference) : state, true);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package net.javadiscord.javabot.systems.user_preferences.commands;

import com.dynxsty.dih4jda.interactions.commands.AutoCompletable;
import com.dynxsty.dih4jda.interactions.commands.SlashCommand;
import com.dynxsty.dih4jda.util.AutoCompleteUtils;
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.AutoCompleteQuery;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.OptionType;
Expand All @@ -15,11 +19,12 @@
import org.jetbrains.annotations.NotNull;

import java.util.Arrays;
import java.util.List;

/**
* <h3>This class represents the /preferences set command.</h3>
*/
public class PreferencesSetSubcommand extends SlashCommand.Subcommand {
public class PreferencesSetSubcommand extends SlashCommand.Subcommand implements AutoCompletable {
/**
* The constructor of this class, which sets the corresponding {@link net.dv8tion.jda.api.interactions.commands.build.SlashCommandData}.
*/
Expand All @@ -28,7 +33,7 @@ public PreferencesSetSubcommand() {
.addOptions(
new OptionData(OptionType.INTEGER, "preference", "The preference to set.", true)
.addChoices(Arrays.stream(Preference.values()).map(this::toChoice).toList()),
new OptionData(OptionType.BOOLEAN, "state", "The state of the specified preference.", true)
new OptionData(OptionType.STRING, "state", "The state/value of the specified preference.", true, true)
)
);
}
Expand All @@ -42,17 +47,34 @@ public void execute(@NotNull SlashCommandInteractionEvent event) {
return;
}
Preference preference = Preference.values()[preferenceMapping.getAsInt()];
boolean state = stateMapping.getAsBoolean();
String state = stateMapping.getAsString();
if (Arrays.stream(preference.getType().getAllowedChoices()).noneMatch(s -> s.equals(state))) {
Responses.error(event, "`%s` is not allowed for this preference! Expected one of the following values:\n%s",
state, String.join(", ", preference.getType().getAllowedChoices())
).queue();
return;
}
UserPreferenceService manager = new UserPreferenceService(Bot.getDataSource());
if (manager.setOrCreate(event.getUser().getIdLong(), preference, state)) {
Responses.info(event, "Preference Updated", "Successfully %s `%s`!", state ? "enabled" : "disabled", preference).queue();
Responses.info(event, "Preference Updated", "Successfully set %s to `%s`!", preference, state).queue();
} else {
Responses.error(event, "Could not %s `%s`.", state ? "enable" : "disable", preference).queue();
Responses.error(event, "Could not set %s to `%s`.", preference, state).queue();
}
}

@Contract("_ -> new")
private Command.@NotNull Choice toChoice(@NotNull Preference preference) {
return new Command.Choice(preference.toString(), String.valueOf(preference.ordinal()));
}

@Override
public void handleAutoComplete(@NotNull CommandAutoCompleteInteractionEvent event, @NotNull AutoCompleteQuery target) {
String preferenceString = event.getOption("preference", OptionMapping::getAsString);
if (preferenceString != null && Arrays.stream(Preference.values()).map(Preference::name).anyMatch(c -> c.equals(preferenceString))) {
Preference preference = Preference.valueOf(preferenceString);
if (preference.getType().getDefaultChoices() != null && preference.getType().getDefaultChoices().length > 0) {
event.replyChoices(AutoCompleteUtils.filterChoices(event, List.of(preference.getType().getDefaultChoices()))).queue();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ public UserPreferenceRepository(Connection con) {
super(con, UserPreference.class, "USER_PREFERENCES", List.of(
TableProperty.of("user_id", H2Type.BIGINT, (x, y) -> x.setUserId((Long) y), UserPreference::getUserId),
TableProperty.of("ordinal", H2Type.INTEGER, (x, y) -> x.setPreference(Preference.values()[(Integer) y]), p -> p.getPreference().ordinal()),
TableProperty.of("enabled", H2Type.BOOLEAN, (x, y) -> x.setEnabled((Boolean) y), UserPreference::isEnabled)
TableProperty.of("state", H2Type.VARCHAR, (x, y) -> x.setState((String) y), UserPreference::getState)
));
}

public Optional<UserPreference> getById(long userId, @NotNull Preference preference) throws SQLException {
return querySingle("WHERE user_id = ? AND ordinal = ?", userId, preference.ordinal());
}

public boolean updateState(long userId, @NotNull Preference preference, boolean enabled) throws SQLException {
return update("UPDATE user_preferences SET enabled = ? WHERE user_id = ? AND ordinal = ?", enabled, userId, preference.ordinal()) > 0;
public boolean updateState(long userId, @NotNull Preference preference, String state) throws SQLException {
return update("UPDATE user_preferences SET state = ? WHERE user_id = ? AND ordinal = ?", state, userId, preference.ordinal()) > 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.javadiscord.javabot.systems.user_preferences.model;

import net.dv8tion.jda.api.interactions.commands.Command;

/**
* Represents a {@link Preference} of the {@link Boolean} type.
*/
public final class BooleanPreference implements PreferenceType {
@Override
public String[] getAllowedChoices() {
return new String[]{
"true", "false"
};
}

@Override
public Command.Choice[] getDefaultChoices() {
return new Command.Choice[]{
new Command.Choice("Enable", "true"),
new Command.Choice("Disable", "false")
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,28 @@ public enum Preference {
/**
* Enables/Disables QOTW reminders.
*/
QOTW_REMINDER("Question of the Week Reminder", false);
QOTW_REMINDER("Question of the Week Reminder", "false", new BooleanPreference());

private final String name;
private final boolean defaultState;
private final String defaultState;
private final PreferenceType type;

Preference(String name, boolean defaultState) {
Preference(String name, String defaultState, PreferenceType type) {
this.name = name;
this.defaultState = defaultState;
this.type = type;
}

@Override
public String toString() {
return name;
}

public boolean getDefaultState() {
public String getDefaultState() {
return defaultState;
}

public PreferenceType getType() {
return type;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.javadiscord.javabot.systems.user_preferences.model;

import net.dv8tion.jda.api.interactions.commands.Command;

/**
* Interface used by different Preference Types. This holds the default and allowed choices.
*/
public interface PreferenceType {
default String[] getAllowedChoices() {
return new String[0];
}

default Command.Choice[] getDefaultChoices() {
return new Command.Choice[0];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package net.javadiscord.javabot.systems.user_preferences.model;

/**
* Represents a {@link Preference} of the {@link String} type.
*/
public final class StringPreference implements PreferenceType {}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
public class UserPreference {
private long userId;
private Preference preference;
private boolean enabled;
private String state;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ CREATE TABLE user_preferences
(
user_id BIGINT NOT NULL,
ordinal INTEGER NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
state VARCHAR NOT NULL DEFAULT '',
PRIMARY KEY (user_id, ordinal)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
TRUNCATE TABLE user_preferences;

ALTER TABLE user_preferences DROP COLUMN enabled;

ALTER TABLE user_preferences ADD COLUMN state VARCHAR NOT NULL DEFAULT ''
2 changes: 1 addition & 1 deletion src/main/resources/database/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,6 @@ CREATE TABLE user_preferences
(
user_id BIGINT NOT NULL,
ordinal INTEGER NOT NULL,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
state VARCHAR NOT NULL DEFAULT '',
PRIMARY KEY (user_id, ordinal)
)

0 comments on commit 5891fe6

Please sign in to comment.