Skip to content

Commit 4a99850

Browse files
committed
Merge remote-tracking branch 'javabot/main' into qotw-view
2 parents de290ac + 6b15baf commit 4a99850

File tree

19 files changed

+414
-9
lines changed

19 files changed

+414
-9
lines changed

src/main/java/net/javadiscord/javabot/Bot.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public static void main(String[] args) throws Exception {
110110
AllowedMentions.setDefaultMentions(EnumSet.of(Message.MentionType.ROLE, Message.MentionType.CHANNEL, Message.MentionType.USER, Message.MentionType.EMOJI));
111111
dih4jda = DIH4JDABuilder.setJDA(jda)
112112
.setCommandsPackage("net.javadiscord.javabot")
113-
.setDefaultCommandType(RegistrationType.GUILD)
113+
.setDefaultCommandType(RegistrationType.GLOBAL)
114114
.build();
115115
customTagManager = new CustomTagManager(jda, dataSource);
116116
messageCache = new MessageCache();

src/main/java/net/javadiscord/javabot/data/h2db/MigrationUtils.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ public static Path getMigrationsDirectory() throws URISyntaxException, IOExcepti
3333
return Path.of(uri);
3434
} catch (FileSystemNotFoundException e) {
3535
Map<String, String> env = new HashMap<>();
36-
try (FileSystem dir = FileSystems.newFileSystem(uri, env)) {
37-
return dir.getPath("/database/migrations/");
38-
}
36+
FileSystem dir = FileSystems.newFileSystem(uri, env);
37+
return dir.getPath("/database/migrations/");
3938
}
4039
}
4140
}

src/main/java/net/javadiscord/javabot/data/h2db/commands/MigrateSubcommand.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public void execute(@NotNull SlashCommandInteractionEvent event) {
8181
return;
8282
}
8383
String sql = Files.readString(migrationFile);
84+
migrationsDir.getFileSystem().close();
8485
String[] statements = sql.split("\\s*;\\s*");
8586
if (statements.length == 0) {
8687
Responses.error(event, "The migration `" + migrationName + "` does not contain any statements. Please remove or edit it before running again.").queue();
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package net.javadiscord.javabot.systems.qotw;
2+
3+
import net.dv8tion.jda.api.JDA;
4+
import net.dv8tion.jda.api.entities.Guild;
5+
import net.dv8tion.jda.api.entities.TextChannel;
6+
import net.javadiscord.javabot.Bot;
7+
import net.javadiscord.javabot.data.config.guild.QOTWConfig;
8+
import net.javadiscord.javabot.systems.qotw.submissions.SubmissionManager;
9+
import net.javadiscord.javabot.systems.qotw.submissions.model.QOTWSubmission;
10+
import net.javadiscord.javabot.systems.user_preferences.UserPreferenceManager;
11+
import net.javadiscord.javabot.systems.user_preferences.model.Preference;
12+
import net.javadiscord.javabot.systems.user_preferences.model.UserPreference;
13+
import net.javadiscord.javabot.tasks.jobs.DiscordApiJob;
14+
import org.jetbrains.annotations.NotNull;
15+
import org.quartz.JobExecutionContext;
16+
import org.quartz.JobExecutionException;
17+
18+
import java.util.List;
19+
20+
/**
21+
* Checks that there's a question in the QOTW queue ready for posting soon.
22+
*/
23+
public class QOTWUserReminderJob extends DiscordApiJob {
24+
@Override
25+
protected void execute(JobExecutionContext context, @NotNull JDA jda) throws JobExecutionException {
26+
for (Guild guild : jda.getGuilds()) {
27+
QOTWConfig config = Bot.getConfig().get(guild).getQotwConfig();
28+
List<QOTWSubmission> submissions = new SubmissionManager(config).getActiveSubmissionThreads(guild.getIdLong());
29+
for (QOTWSubmission submission : submissions) {
30+
UserPreferenceManager manager = new UserPreferenceManager(Bot.getDataSource());
31+
UserPreference preference = manager.getOrCreate(submission.getAuthorId(), Preference.QOTW_REMINDER);
32+
if (preference.isEnabled()) {
33+
TextChannel channel = config.getSubmissionChannel();
34+
channel.getThreadChannels().stream().filter(t -> t.getIdLong() == submission.getThreadId()).forEach(t -> {
35+
if (t.getMessageCount() <= 1) {
36+
t.sendMessageFormat("**Question of the Week Reminder**\nHey <@%s>! You still have some time left to submit your answer!", submission.getAuthorId())
37+
.queue();
38+
}
39+
});
40+
}
41+
}
42+
}
43+
}
44+
}

src/main/java/net/javadiscord/javabot/systems/qotw/submissions/SubmissionManager.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.sql.Connection;
2626
import java.sql.SQLException;
2727
import java.time.Instant;
28+
import java.util.List;
2829
import java.util.Optional;
2930

3031
/**
@@ -129,14 +130,30 @@ public boolean hasActiveSubmissionThreads(long authorId) {
129130
}
130131
}
131132

133+
/**
134+
* Gets all active submission threads.
135+
*
136+
* @param guildId The ID of the guild to get the submission threads from
137+
* @return An immutable {@link List} of {@link QOTWSubmission}s.
138+
*/
139+
public List<QOTWSubmission> getActiveSubmissionThreads(long guildId) {
140+
try (Connection con = Bot.getDataSource().getConnection()) {
141+
QOTWSubmissionRepository repo = new QOTWSubmissionRepository(con);
142+
return repo.getSubmissionsByQuestionNumber(guildId, repo.getCurrentQuestionNumber());
143+
} catch (SQLException e) {
144+
ExceptionLogger.capture(e, getClass().getSimpleName());
145+
return List.of();
146+
}
147+
}
148+
132149
private @NotNull MessageEmbed buildSubmissionThreadEmbed(@NotNull User createdBy, @NotNull QOTWQuestion question, @NotNull QOTWConfig config) {
133150
return new EmbedBuilder()
134151
.setColor(Responses.Type.DEFAULT.getColor())
135152
.setAuthor(createdBy.getAsTag(), null, createdBy.getEffectiveAvatarUrl())
136153
.setTitle(String.format("Question of the Week #%s", question.getQuestionNumber()))
137154
.setDescription(String.format("""
138155
%s
139-
156+
140157
Hey, %s! Please submit your answer into this private thread.
141158
The %s will review your submission once a new question appears.""",
142159
question.getText(), createdBy.getAsMention(), config.getQOTWReviewRole().getAsMention()))
@@ -145,7 +162,7 @@ public boolean hasActiveSubmissionThreads(long authorId) {
145162
To maximize your chances of getting this week's QOTW Point make sure to:
146163
— Provide a **Code example** (if possible)
147164
— Try to answer the question as detailed as possible.
148-
165+
149166
Staff usually won't reply in here.""", false)
150167
.setTimestamp(Instant.now())
151168
.build();

src/main/java/net/javadiscord/javabot/systems/staff_commands/self_roles/ChangeSelfRoleStatusSubcommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import java.time.Instant;
1818

1919
/**
20-
* Subcommand that disables all Elements on an ActionRow.
20+
* Subcommand that disables all Elements on all ActionRows.
2121
*/
2222
public class ChangeSelfRoleStatusSubcommand extends SlashCommand.Subcommand {
2323
/**
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package net.javadiscord.javabot.systems.staff_commands.self_roles;
2+
3+
import com.dynxsty.dih4jda.interactions.commands.SlashCommand;
4+
import net.dv8tion.jda.api.EmbedBuilder;
5+
import net.dv8tion.jda.api.entities.Message;
6+
import net.dv8tion.jda.api.entities.MessageEmbed;
7+
import net.dv8tion.jda.api.entities.User;
8+
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
9+
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
10+
import net.dv8tion.jda.api.interactions.commands.OptionType;
11+
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
12+
import net.javadiscord.javabot.systems.notification.GuildNotificationService;
13+
import net.javadiscord.javabot.util.Responses;
14+
import org.jetbrains.annotations.NotNull;
15+
16+
import java.time.Instant;
17+
18+
/**
19+
* Subcommands that removes all Elements on all ActionRows.
20+
*/
21+
public class RemoveSelfRolesSubcommand extends SlashCommand.Subcommand {
22+
23+
public RemoveSelfRolesSubcommand() {
24+
setSubcommandData(new SubcommandData("remove-all", "Removes all Self-Roles from a specified message.")
25+
.addOption(OptionType.STRING, "message-id", "Id of the message.", true));
26+
}
27+
28+
@Override
29+
public void execute(SlashCommandInteractionEvent event) {
30+
OptionMapping idMapping = event.getOption("message-id");
31+
if (idMapping == null) {
32+
Responses.replyMissingArguments(event).queue();
33+
return;
34+
}
35+
event.deferReply(true).queue();
36+
event.getChannel().retrieveMessageById(idMapping.getAsLong()).queue(message -> {
37+
message.editMessageComponents().queue();
38+
MessageEmbed embed = buildSelfRoleDeletedEmbed(event.getUser(), message);
39+
new GuildNotificationService(event.getGuild()).sendLogChannelNotification(embed);
40+
event.getHook().sendMessageEmbeds(embed).setEphemeral(true).queue();
41+
}, e -> Responses.error(event.getHook(), e.getMessage()));
42+
}
43+
44+
private @NotNull MessageEmbed buildSelfRoleDeletedEmbed(@NotNull User changedBy, @NotNull Message message) {
45+
return new EmbedBuilder()
46+
.setAuthor(changedBy.getAsTag(), message.getJumpUrl(), changedBy.getEffectiveAvatarUrl())
47+
.setTitle("Self Roles Removed")
48+
.setColor(Responses.Type.DEFAULT.getColor())
49+
.addField("Channel", message.getChannel().getAsMention(), true)
50+
.addField("Message", String.format("[Jump to Message](%s)", message.getJumpUrl()), true)
51+
.setTimestamp(Instant.now())
52+
.build();
53+
}
54+
}

src/main/java/net/javadiscord/javabot/systems/staff_commands/self_roles/SelfRoleCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public SelfRoleCommand() {
1717
.setDefaultPermissions(DefaultMemberPermissions.DISABLED)
1818
.setGuildOnly(true)
1919
);
20-
addSubcommands(new CreateSelfRoleSubcommand(), new ChangeSelfRoleStatusSubcommand());
20+
addSubcommands(new CreateSelfRoleSubcommand(), new ChangeSelfRoleStatusSubcommand(), new RemoveSelfRolesSubcommand());
2121
}
2222
}
2323

src/main/java/net/javadiscord/javabot/systems/staff_commands/tags/commands/TagsCommand.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ public class TagsCommand extends SlashCommand {
1212
* adds the corresponding {@link net.dv8tion.jda.api.interactions.commands.Command.Subcommand}s.
1313
*/
1414
public TagsCommand() {
15-
setSlashCommandData(Commands.slash("tag", "Commands for interacting with Custom Tags."));
15+
setSlashCommandData(Commands.slash("tag", "Commands for interacting with Custom Tags.")
16+
.setGuildOnly(true)
17+
);
1618
addSubcommands(new TagViewSubcommand(), new TagListSubcommand());
1719
}
1820
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package net.javadiscord.javabot.systems.user_preferences;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import net.javadiscord.javabot.systems.user_preferences.dao.UserPreferenceRepository;
5+
import net.javadiscord.javabot.systems.user_preferences.model.Preference;
6+
import net.javadiscord.javabot.systems.user_preferences.model.UserPreference;
7+
import net.javadiscord.javabot.util.ExceptionLogger;
8+
9+
import javax.sql.DataSource;
10+
import java.sql.Connection;
11+
import java.sql.SQLException;
12+
import java.util.Optional;
13+
14+
/**
15+
* Handles & manages user preferences.
16+
*/
17+
@RequiredArgsConstructor
18+
public class UserPreferenceManager {
19+
private final DataSource dataSource;
20+
21+
/**
22+
* Simply sets the state of the specified {@link Preference} for the specified user.
23+
* If no entry for that user is found, this will simply create a new one.
24+
*
25+
* @param userId The users' id.
26+
* @param preference The {@link Preference} to change the state for.
27+
* @param enabled The preferences' state.
28+
* @return Whether the operation was successful.
29+
*/
30+
public boolean setOrCreate(long userId, Preference preference, boolean enabled) {
31+
try (Connection con = dataSource.getConnection()) {
32+
UserPreferenceRepository repo = new UserPreferenceRepository(con);
33+
Optional<UserPreference> preferenceOptional = repo.getById(userId, preference);
34+
if (preferenceOptional.isPresent()) {
35+
return repo.updateState(userId, preference, enabled);
36+
} else {
37+
UserPreference userPreference = new UserPreference();
38+
userPreference.setUserId(userId);
39+
userPreference.setPreference(preference);
40+
userPreference.setEnabled(enabled);
41+
repo.insert(userPreference, false);
42+
return true;
43+
}
44+
} catch (SQLException e) {
45+
ExceptionLogger.capture(e, getClass().getSimpleName());
46+
return false;
47+
}
48+
}
49+
50+
/**
51+
* Gets a single {@link UserPreference} (or creates a new one if it doesn't exist yet).
52+
*
53+
* @param userId The users' id.
54+
* @param preference The {@link Preference} to get.
55+
* @return The {@link UserPreference}.
56+
*/
57+
public UserPreference getOrCreate(long userId, Preference preference) {
58+
try (Connection con = dataSource.getConnection()) {
59+
UserPreferenceRepository repo = new UserPreferenceRepository(con);
60+
Optional<UserPreference> preferenceOptional = repo.getById(userId, preference);
61+
if (preferenceOptional.isPresent()) {
62+
return preferenceOptional.get();
63+
} else {
64+
UserPreference userPreference = new UserPreference();
65+
userPreference.setUserId(userId);
66+
userPreference.setPreference(preference);
67+
userPreference.setEnabled(preference.getDefaultState());
68+
repo.insert(userPreference, false);
69+
return userPreference;
70+
}
71+
} catch (SQLException e) {
72+
ExceptionLogger.capture(e, getClass().getSimpleName());
73+
return null;
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)