|
2 | 2 |
|
3 | 3 | import net.dv8tion.jda.api.EmbedBuilder;
|
4 | 4 | import net.dv8tion.jda.api.JDA;
|
5 |
| -import net.dv8tion.jda.api.entities.Guild; |
6 |
| -import net.dv8tion.jda.api.entities.MessageEmbed; |
7 |
| -import net.dv8tion.jda.api.entities.TextChannel; |
| 5 | +import net.dv8tion.jda.api.entities.*; |
| 6 | +import net.dv8tion.jda.api.requests.RestAction; |
8 | 7 | import org.jetbrains.annotations.NotNull;
|
| 8 | +import org.jetbrains.annotations.Nullable; |
9 | 9 | import org.slf4j.Logger;
|
10 | 10 | import org.slf4j.LoggerFactory;
|
11 | 11 | import org.togetherjava.tjbot.commands.Routine;
|
@@ -51,46 +51,89 @@ public void runRoutine(@NotNull JDA jda) {
|
51 | 51 | .where(PENDING_REMINDERS.REMIND_AT.lessOrEqual(now))
|
52 | 52 | .stream()
|
53 | 53 | .forEach(pendingReminder -> {
|
54 |
| - sendReminder(jda, pendingReminder.getGuildId(), pendingReminder.getChannelId(), |
55 |
| - pendingReminder.getAuthorId(), pendingReminder.getContent(), |
56 |
| - pendingReminder.getCreatedAt()); |
| 54 | + sendReminder(jda, pendingReminder.getId(), pendingReminder.getGuildId(), |
| 55 | + pendingReminder.getChannelId(), pendingReminder.getAuthorId(), |
| 56 | + pendingReminder.getContent(), pendingReminder.getCreatedAt()); |
57 | 57 | pendingReminder.delete();
|
58 | 58 | }));
|
59 | 59 | }
|
60 | 60 |
|
61 |
| - private static void sendReminder(@NotNull JDA jda, long guildId, long channelId, long authorId, |
62 |
| - @NotNull CharSequence content, @NotNull TemporalAccessor createdAt) { |
| 61 | + private static void sendReminder(@NotNull JDA jda, long id, long guildId, long channelId, |
| 62 | + long authorId, @NotNull CharSequence content, @NotNull TemporalAccessor createdAt) { |
| 63 | + RestAction<ReminderRoute> route = computeReminderRoute(jda, guildId, channelId, authorId); |
| 64 | + sendReminderViaRoute(route, id, content, createdAt); |
| 65 | + } |
| 66 | + |
| 67 | + private static RestAction<ReminderRoute> computeReminderRoute(@NotNull JDA jda, long guildId, |
| 68 | + long channelId, long authorId) { |
| 69 | + // If guild and channel can still be found, send there |
63 | 70 | Guild guild = jda.getGuildById(guildId);
|
64 |
| - if (guild == null) { |
65 |
| - logger.debug( |
66 |
| - "Attempted to send a reminder but the bot is not connected to the guild '{}' anymore, skipping reminder.", |
67 |
| - guildId); |
68 |
| - return; |
| 71 | + if (guild != null) { |
| 72 | + TextChannel channel = guild.getTextChannelById(channelId); |
| 73 | + if (channel != null) { |
| 74 | + return createGuildReminderRoute(jda, authorId, channel); |
| 75 | + } |
69 | 76 | }
|
70 | 77 |
|
71 |
| - TextChannel channel = guild.getTextChannelById(channelId); |
72 |
| - if (channel == null) { |
73 |
| - logger.debug( |
74 |
| - "Attempted to send a reminder but the guild '{}' does not have a channel with id '{}' anymore, skipping reminder.", |
75 |
| - guildId, channelId); |
76 |
| - return; |
77 |
| - } |
| 78 | + // Otherwise, attempt to DM the user directly |
| 79 | + return createDmReminderRoute(jda, authorId); |
| 80 | + } |
78 | 81 |
|
79 |
| - jda.retrieveUserById(authorId).onErrorMap(error -> null).flatMap(author -> { |
80 |
| - String authorName = author == null ? "Unknown user" : author.getAsTag(); |
81 |
| - String authorIconUrl = author == null ? null : author.getAvatarUrl(); |
| 82 | + private static @NotNull RestAction<ReminderRoute> createGuildReminderRoute(@NotNull JDA jda, |
| 83 | + long authorId, @NotNull TextChannel channel) { |
| 84 | + return jda.retrieveUserById(authorId) |
| 85 | + .onErrorMap(error -> null) |
| 86 | + .map(author -> new ReminderRoute(channel, author, |
| 87 | + author == null ? null : author.getAsMention())); |
| 88 | + } |
82 | 89 |
|
83 |
| - MessageEmbed embed = new EmbedBuilder().setAuthor(authorName, null, authorIconUrl) |
84 |
| - .setDescription(content) |
85 |
| - .setFooter("reminder from") |
86 |
| - .setTimestamp(createdAt) |
87 |
| - .setColor(AMBIENT_COLOR) |
88 |
| - .build(); |
| 90 | + private static @NotNull RestAction<ReminderRoute> createDmReminderRoute(@NotNull JDA jda, |
| 91 | + long authorId) { |
| 92 | + return jda.openPrivateChannelById(authorId) |
| 93 | + .onErrorMap(error -> null) |
| 94 | + .map(channel -> channel == null ? new ReminderRoute(null, null, null) |
| 95 | + : new ReminderRoute(channel, channel.getUser(), |
| 96 | + "(Sending your reminder directly, because I was unable to" |
| 97 | + + " locate the original channel you wanted it to be send to)")); |
| 98 | + } |
89 | 99 |
|
90 |
| - if (author == null) { |
91 |
| - return channel.sendMessageEmbeds(embed); |
| 100 | + private static void sendReminderViaRoute(@NotNull RestAction<ReminderRoute> routeAction, |
| 101 | + long id, @NotNull CharSequence content, @NotNull TemporalAccessor createdAt) { |
| 102 | + routeAction.flatMap(route -> { |
| 103 | + if (route.isUndeliverable()) { |
| 104 | + throw new IllegalStateException("Route is not deliverable"); |
92 | 105 | }
|
93 |
| - return channel.sendMessage(author.getAsMention()).setEmbeds(embed); |
94 |
| - }).queue(); |
| 106 | + |
| 107 | + MessageEmbed embed = createReminderEmbed(content, createdAt, route.target()); |
| 108 | + if (route.description() == null) { |
| 109 | + return route.channel().sendMessageEmbeds(embed); |
| 110 | + } |
| 111 | + return route.channel().sendMessage(route.description()).setEmbeds(embed); |
| 112 | + }).queue(message -> { |
| 113 | + }, failure -> logger.warn( |
| 114 | + "Failed to send a reminder (id '{}'), skipping it. This can be due to a network issue," |
| 115 | + + " but also happen if the bot disconnected from the target guild and the" |
| 116 | + + " user has disabled DMs or has been deleted.", |
| 117 | + id)); |
| 118 | + } |
| 119 | + |
| 120 | + private static @NotNull MessageEmbed createReminderEmbed(@NotNull CharSequence content, |
| 121 | + @NotNull TemporalAccessor createdAt, @Nullable User author) { |
| 122 | + String authorName = author == null ? "Unknown user" : author.getAsTag(); |
| 123 | + String authorIconUrl = author == null ? null : author.getAvatarUrl(); |
| 124 | + |
| 125 | + return new EmbedBuilder().setAuthor(authorName, null, authorIconUrl) |
| 126 | + .setDescription(content) |
| 127 | + .setFooter("reminder from") |
| 128 | + .setTimestamp(createdAt) |
| 129 | + .setColor(AMBIENT_COLOR) |
| 130 | + .build(); |
| 131 | + } |
| 132 | + |
| 133 | + private record ReminderRoute(@Nullable MessageChannel channel, @Nullable User target, |
| 134 | + @Nullable String description) { |
| 135 | + boolean isUndeliverable() { |
| 136 | + return channel == null && target == null; |
| 137 | + } |
95 | 138 | }
|
96 | 139 | }
|
0 commit comments