Skip to content

Commit 5891fe6

Browse files
Merge pull request #356 from Java-Discord/dynxsty/preference_improvements
Improved User Preferences by using Strings instead of Booleans
2 parents 5234032 + ca0668e commit 5891fe6

13 files changed

+121
-29
lines changed

Diff for: src/main/java/net/javadiscord/javabot/systems/qotw/QOTWUserReminderJob.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ protected void execute(JobExecutionContext context, @NotNull JDA jda) throws Job
2929
for (QOTWSubmission submission : submissions) {
3030
UserPreferenceService manager = new UserPreferenceService(Bot.getDataSource());
3131
UserPreference preference = manager.getOrCreate(submission.getAuthorId(), Preference.QOTW_REMINDER);
32-
if (preference.isEnabled()) {
32+
if (Boolean.parseBoolean(preference.getState())) {
3333
TextChannel channel = config.getSubmissionChannel();
3434
channel.getThreadChannels().stream().filter(t -> t.getIdLong() == submission.getThreadId()).forEach(t -> {
3535
if (t.getMessageCount() <= 1) {

Diff for: src/main/java/net/javadiscord/javabot/systems/user_preferences/UserPreferenceService.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ public class UserPreferenceService {
2424
*
2525
* @param userId The users' id.
2626
* @param preference The {@link Preference} to change the state for.
27-
* @param enabled The preferences' state.
27+
* @param state The preferences' state.
2828
* @return Whether the operation was successful.
2929
*/
30-
public boolean setOrCreate(long userId, Preference preference, boolean enabled) {
30+
public boolean setOrCreate(long userId, Preference preference, String state) {
3131
try (Connection con = dataSource.getConnection()) {
3232
UserPreferenceRepository repo = new UserPreferenceRepository(con);
3333
Optional<UserPreference> preferenceOptional = repo.getById(userId, preference);
3434
if (preferenceOptional.isPresent()) {
35-
return repo.updateState(userId, preference, enabled);
35+
return repo.updateState(userId, preference, state);
3636
} else {
3737
UserPreference userPreference = new UserPreference();
3838
userPreference.setUserId(userId);
3939
userPreference.setPreference(preference);
40-
userPreference.setEnabled(enabled);
40+
userPreference.setState(state);
4141
repo.insert(userPreference, false);
4242
return true;
4343
}
@@ -64,7 +64,7 @@ public UserPreference getOrCreate(long userId, Preference preference) {
6464
UserPreference userPreference = new UserPreference();
6565
userPreference.setUserId(userId);
6666
userPreference.setPreference(preference);
67-
userPreference.setEnabled(preference.getDefaultState());
67+
userPreference.setState(preference.getDefaultState());
6868
repo.insert(userPreference, false);
6969
return userPreference;
7070
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package net.javadiscord.javabot.systems.user_preferences.commands;
22

33
import com.dynxsty.dih4jda.interactions.commands.SlashCommand;
4+
import net.dv8tion.jda.api.EmbedBuilder;
5+
import net.dv8tion.jda.api.entities.MessageEmbed;
6+
import net.dv8tion.jda.api.entities.User;
47
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
58
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
69
import net.javadiscord.javabot.Bot;
@@ -9,9 +12,6 @@
912
import net.javadiscord.javabot.util.Responses;
1013
import org.jetbrains.annotations.NotNull;
1114

12-
import java.util.Arrays;
13-
import java.util.stream.Collectors;
14-
1515
/**
1616
* <h3>This class represents the /preferences list command.</h3>
1717
*/
@@ -25,10 +25,24 @@ public PreferencesListSubcommand() {
2525

2626
@Override
2727
public void execute(@NotNull SlashCommandInteractionEvent event) {
28-
UserPreferenceService manager = new UserPreferenceService(Bot.getDataSource());
29-
String preferences = Arrays.stream(Preference.values())
30-
.map(p -> String.format("`%s` %s", manager.getOrCreate(event.getUser().getIdLong(), p).isEnabled() ? "\uD83D\uDFE2" : "\uD83D\uDD34", p))
31-
.collect(Collectors.joining("\n"));
32-
Responses.info(event, String.format("%s's Preferences", event.getUser().getName()), preferences).queue();
28+
event.replyEmbeds(buildPreferencesEmbed(new UserPreferenceService(Bot.getDataSource()), event.getUser()))
29+
.setEphemeral(true)
30+
.queue();
31+
}
32+
33+
private @NotNull MessageEmbed buildPreferencesEmbed(UserPreferenceService service, @NotNull User user) {
34+
EmbedBuilder builder = new EmbedBuilder()
35+
.setAuthor(user.getAsTag(), null, user.getEffectiveAvatarUrl())
36+
.setTitle(user.getName() + "'s Preferences")
37+
.setColor(Responses.Type.INFO.getColor());
38+
for (Preference p : Preference.values()) {
39+
builder.addField(buildPreferenceField(user, service, p));
40+
}
41+
return builder.build();
42+
}
43+
44+
private MessageEmbed.@NotNull Field buildPreferenceField(@NotNull User user, @NotNull UserPreferenceService service, Preference preference) {
45+
String state = service.getOrCreate(user.getIdLong(), preference).getState();
46+
return new MessageEmbed.Field(preference.toString(), state.isEmpty() ? String.format("`%s` has not yet been set.", preference) : state, true);
3347
}
3448
}

Diff for: src/main/java/net/javadiscord/javabot/systems/user_preferences/commands/PreferencesSetSubcommand.java

+27-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package net.javadiscord.javabot.systems.user_preferences.commands;
22

3+
import com.dynxsty.dih4jda.interactions.commands.AutoCompletable;
34
import com.dynxsty.dih4jda.interactions.commands.SlashCommand;
5+
import com.dynxsty.dih4jda.util.AutoCompleteUtils;
6+
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
47
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
8+
import net.dv8tion.jda.api.interactions.AutoCompleteQuery;
59
import net.dv8tion.jda.api.interactions.commands.Command;
610
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
711
import net.dv8tion.jda.api.interactions.commands.OptionType;
@@ -15,11 +19,12 @@
1519
import org.jetbrains.annotations.NotNull;
1620

1721
import java.util.Arrays;
22+
import java.util.List;
1823

1924
/**
2025
* <h3>This class represents the /preferences set command.</h3>
2126
*/
22-
public class PreferencesSetSubcommand extends SlashCommand.Subcommand {
27+
public class PreferencesSetSubcommand extends SlashCommand.Subcommand implements AutoCompletable {
2328
/**
2429
* The constructor of this class, which sets the corresponding {@link net.dv8tion.jda.api.interactions.commands.build.SlashCommandData}.
2530
*/
@@ -28,7 +33,7 @@ public PreferencesSetSubcommand() {
2833
.addOptions(
2934
new OptionData(OptionType.INTEGER, "preference", "The preference to set.", true)
3035
.addChoices(Arrays.stream(Preference.values()).map(this::toChoice).toList()),
31-
new OptionData(OptionType.BOOLEAN, "state", "The state of the specified preference.", true)
36+
new OptionData(OptionType.STRING, "state", "The state/value of the specified preference.", true, true)
3237
)
3338
);
3439
}
@@ -42,17 +47,34 @@ public void execute(@NotNull SlashCommandInteractionEvent event) {
4247
return;
4348
}
4449
Preference preference = Preference.values()[preferenceMapping.getAsInt()];
45-
boolean state = stateMapping.getAsBoolean();
50+
String state = stateMapping.getAsString();
51+
if (Arrays.stream(preference.getType().getAllowedChoices()).noneMatch(s -> s.equals(state))) {
52+
Responses.error(event, "`%s` is not allowed for this preference! Expected one of the following values:\n%s",
53+
state, String.join(", ", preference.getType().getAllowedChoices())
54+
).queue();
55+
return;
56+
}
4657
UserPreferenceService manager = new UserPreferenceService(Bot.getDataSource());
4758
if (manager.setOrCreate(event.getUser().getIdLong(), preference, state)) {
48-
Responses.info(event, "Preference Updated", "Successfully %s `%s`!", state ? "enabled" : "disabled", preference).queue();
59+
Responses.info(event, "Preference Updated", "Successfully set %s to `%s`!", preference, state).queue();
4960
} else {
50-
Responses.error(event, "Could not %s `%s`.", state ? "enable" : "disable", preference).queue();
61+
Responses.error(event, "Could not set %s to `%s`.", preference, state).queue();
5162
}
5263
}
5364

5465
@Contract("_ -> new")
5566
private Command.@NotNull Choice toChoice(@NotNull Preference preference) {
5667
return new Command.Choice(preference.toString(), String.valueOf(preference.ordinal()));
5768
}
69+
70+
@Override
71+
public void handleAutoComplete(@NotNull CommandAutoCompleteInteractionEvent event, @NotNull AutoCompleteQuery target) {
72+
String preferenceString = event.getOption("preference", OptionMapping::getAsString);
73+
if (preferenceString != null && Arrays.stream(Preference.values()).map(Preference::name).anyMatch(c -> c.equals(preferenceString))) {
74+
Preference preference = Preference.valueOf(preferenceString);
75+
if (preference.getType().getDefaultChoices() != null && preference.getType().getDefaultChoices().length > 0) {
76+
event.replyChoices(AutoCompleteUtils.filterChoices(event, List.of(preference.getType().getDefaultChoices()))).queue();
77+
}
78+
}
79+
}
5880
}

Diff for: src/main/java/net/javadiscord/javabot/systems/user_preferences/dao/UserPreferenceRepository.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ public UserPreferenceRepository(Connection con) {
2626
super(con, UserPreference.class, "USER_PREFERENCES", List.of(
2727
TableProperty.of("user_id", H2Type.BIGINT, (x, y) -> x.setUserId((Long) y), UserPreference::getUserId),
2828
TableProperty.of("ordinal", H2Type.INTEGER, (x, y) -> x.setPreference(Preference.values()[(Integer) y]), p -> p.getPreference().ordinal()),
29-
TableProperty.of("enabled", H2Type.BOOLEAN, (x, y) -> x.setEnabled((Boolean) y), UserPreference::isEnabled)
29+
TableProperty.of("state", H2Type.VARCHAR, (x, y) -> x.setState((String) y), UserPreference::getState)
3030
));
3131
}
3232

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

37-
public boolean updateState(long userId, @NotNull Preference preference, boolean enabled) throws SQLException {
38-
return update("UPDATE user_preferences SET enabled = ? WHERE user_id = ? AND ordinal = ?", enabled, userId, preference.ordinal()) > 0;
37+
public boolean updateState(long userId, @NotNull Preference preference, String state) throws SQLException {
38+
return update("UPDATE user_preferences SET state = ? WHERE user_id = ? AND ordinal = ?", state, userId, preference.ordinal()) > 0;
3939
}
4040
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package net.javadiscord.javabot.systems.user_preferences.model;
2+
3+
import net.dv8tion.jda.api.interactions.commands.Command;
4+
5+
/**
6+
* Represents a {@link Preference} of the {@link Boolean} type.
7+
*/
8+
public final class BooleanPreference implements PreferenceType {
9+
@Override
10+
public String[] getAllowedChoices() {
11+
return new String[]{
12+
"true", "false"
13+
};
14+
}
15+
16+
@Override
17+
public Command.Choice[] getDefaultChoices() {
18+
return new Command.Choice[]{
19+
new Command.Choice("Enable", "true"),
20+
new Command.Choice("Disable", "false")
21+
};
22+
}
23+
}

Diff for: src/main/java/net/javadiscord/javabot/systems/user_preferences/model/Preference.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,28 @@ public enum Preference {
77
/**
88
* Enables/Disables QOTW reminders.
99
*/
10-
QOTW_REMINDER("Question of the Week Reminder", false);
10+
QOTW_REMINDER("Question of the Week Reminder", "false", new BooleanPreference());
1111

1212
private final String name;
13-
private final boolean defaultState;
13+
private final String defaultState;
14+
private final PreferenceType type;
1415

15-
Preference(String name, boolean defaultState) {
16+
Preference(String name, String defaultState, PreferenceType type) {
1617
this.name = name;
1718
this.defaultState = defaultState;
19+
this.type = type;
1820
}
1921

2022
@Override
2123
public String toString() {
2224
return name;
2325
}
2426

25-
public boolean getDefaultState() {
27+
public String getDefaultState() {
2628
return defaultState;
2729
}
30+
31+
public PreferenceType getType() {
32+
return type;
33+
}
2834
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package net.javadiscord.javabot.systems.user_preferences.model;
2+
3+
import net.dv8tion.jda.api.interactions.commands.Command;
4+
5+
/**
6+
* Interface used by different Preference Types. This holds the default and allowed choices.
7+
*/
8+
public interface PreferenceType {
9+
default String[] getAllowedChoices() {
10+
return new String[0];
11+
}
12+
13+
default Command.Choice[] getDefaultChoices() {
14+
return new Command.Choice[0];
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package net.javadiscord.javabot.systems.user_preferences.model;
2+
3+
/**
4+
* Represents a {@link Preference} of the {@link String} type.
5+
*/
6+
public final class StringPreference implements PreferenceType {}

Diff for: src/main/java/net/javadiscord/javabot/systems/user_preferences/model/UserPreference.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
public class UserPreference {
1010
private long userId;
1111
private Preference preference;
12-
private boolean enabled;
12+
private String state;
1313
}

Diff for: src/main/resources/database/migrations/07-31-2022_add_user_preferences_table.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ CREATE TABLE user_preferences
22
(
33
user_id BIGINT NOT NULL,
44
ordinal INTEGER NOT NULL,
5-
enabled BOOLEAN NOT NULL DEFAULT TRUE,
5+
state VARCHAR NOT NULL DEFAULT '',
66
PRIMARY KEY (user_id, ordinal)
77
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
TRUNCATE TABLE user_preferences;
2+
3+
ALTER TABLE user_preferences DROP COLUMN enabled;
4+
5+
ALTER TABLE user_preferences ADD COLUMN state VARCHAR NOT NULL DEFAULT ''

Diff for: src/main/resources/database/schema.sql

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,6 @@ CREATE TABLE user_preferences
110110
(
111111
user_id BIGINT NOT NULL,
112112
ordinal INTEGER NOT NULL,
113-
enabled BOOLEAN NOT NULL DEFAULT TRUE,
113+
state VARCHAR NOT NULL DEFAULT '',
114114
PRIMARY KEY (user_id, ordinal)
115115
)

0 commit comments

Comments
 (0)