mirror of
https://github.com/sciwhiz12/Janitor.git
synced 2024-11-10 02:21:25 +00:00
Add listing messages
This commit is contained in:
parent
f861308e4d
commit
09aa6a269c
|
@ -10,6 +10,7 @@ import sciwhiz12.janitor.commands.CommandRegistry;
|
|||
import sciwhiz12.janitor.config.BotConfig;
|
||||
import sciwhiz12.janitor.msg.Messages;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.emote.ReactionManager;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
import sciwhiz12.janitor.utils.Util;
|
||||
|
||||
|
@ -29,6 +30,7 @@ public class JanitorBot {
|
|||
private final TranslationMap translations;
|
||||
private final SubstitutionMap substitutions;
|
||||
private final Messages messages;
|
||||
private final ReactionManager reactions;
|
||||
|
||||
public JanitorBot(JDA discord, BotConfig config) {
|
||||
this.config = config;
|
||||
|
@ -39,8 +41,9 @@ public class JanitorBot {
|
|||
this.translations = new TranslationMap(this, config.getTranslationsFile());
|
||||
this.substitutions = new SubstitutionMap(this);
|
||||
this.messages = new Messages(this, config.getTranslationsFile());
|
||||
this.reactions = new ReactionManager(this);
|
||||
// TODO: find which of these can be loaded in parallel before the bot JDA is ready
|
||||
discord.addEventListener(cmdRegistry);
|
||||
discord.addEventListener(cmdRegistry, reactions);
|
||||
discord.getPresence().setPresence(OnlineStatus.ONLINE, Activity.playing(" n' sweeping n' testing!"));
|
||||
discord.getGuilds().forEach(Guild::loadMembers);
|
||||
JANITOR.info("Ready!");
|
||||
|
@ -82,6 +85,10 @@ public class JanitorBot {
|
|||
return this.translations;
|
||||
}
|
||||
|
||||
public ReactionManager getReactionManager() {
|
||||
return this.reactions;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
JANITOR.info(STATUS, "Shutting down!");
|
||||
getConfig().getOwnerID()
|
||||
|
|
|
@ -24,10 +24,9 @@ public class HelloCommand extends BaseCommand {
|
|||
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("greet")
|
||||
.then(
|
||||
argument("member", GuildMemberArgument.member())
|
||||
.executes(this::run)
|
||||
);
|
||||
.then(argument("member", GuildMemberArgument.member())
|
||||
.executes(this::run)
|
||||
);
|
||||
}
|
||||
|
||||
int run(final CommandContext<MessageReceivedEvent> ctx) throws CommandSyntaxException {
|
||||
|
@ -35,11 +34,22 @@ public class HelloCommand extends BaseCommand {
|
|||
final List<Member> memberList = getMembers("member", ctx).fromGuild(ctx.getSource().getGuild());
|
||||
if (memberList.size() == 1) {
|
||||
final Member member = memberList.get(0);
|
||||
ctx.getSource().getChannel().sendMessage("Hello " + member.getAsMention() + "!")
|
||||
.queue(
|
||||
success -> JANITOR.debug("Sent greeting message to {}, on cmd of {}", Util.toString(member.getUser()), Util.toString(ctx.getSource().getAuthor())),
|
||||
err -> JANITOR.error("Error while sending greeting message to {}, on cmd of {}", Util.toString(member.getUser()), Util.toString(ctx.getSource().getAuthor()))
|
||||
);
|
||||
ctx.getSource().getChannel().sendMessage("Hello " + member.getAsMention() + "!").queue(
|
||||
success -> {
|
||||
JANITOR.debug("Sent greeting message to {}, on cmd of {}", Util.toString(member.getUser()),
|
||||
Util.toString(ctx.getSource().getAuthor()));
|
||||
getBot().getReactionManager().newMessage(success)
|
||||
.add("\u274C", (msg, event) -> success.delete()
|
||||
.flatMap(v -> event.getChannel()
|
||||
.deleteMessageById(ctx.getSource().getMessageIdLong()))
|
||||
.queue()
|
||||
)
|
||||
.owner(ctx.getSource().getAuthor().getIdLong())
|
||||
.create();
|
||||
},
|
||||
err -> JANITOR.error("Error while sending greeting message to {}, on cmd of {}",
|
||||
Util.toString(member.getUser()), Util.toString(ctx.getSource().getAuthor()))
|
||||
);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
@ -16,6 +17,7 @@ import sciwhiz12.janitor.msg.MessageHelper;
|
|||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -32,6 +34,7 @@ import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
|||
import static sciwhiz12.janitor.commands.moderation.NoteCommand.ModeratorFilter.*;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.*;
|
||||
|
||||
public class NoteCommand extends BaseCommand {
|
||||
public static EnumSet<Permission> NOTE_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
@ -93,7 +96,7 @@ public class NoteCommand extends BaseCommand {
|
|||
final MessageChannel channel = ctx.getSource().getChannel();
|
||||
if (!ctx.getSource().isFromGuild()) {
|
||||
messages().getRegularMessage("general/error/guild_only_command")
|
||||
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||
.apply(user("performer", ctx.getSource().getAuthor()))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
return 1;
|
||||
|
@ -137,7 +140,7 @@ public class NoteCommand extends BaseCommand {
|
|||
|
||||
messages().getRegularMessage("moderation/note/add")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.noteEntry("note_entry", noteID, entry))
|
||||
.apply(noteEntry("note_entry", noteID, entry))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
}
|
||||
|
@ -154,7 +157,7 @@ public class NoteCommand extends BaseCommand {
|
|||
final MessageChannel channel = ctx.getSource().getChannel();
|
||||
if (!ctx.getSource().isFromGuild()) {
|
||||
messages().getRegularMessage("general/error/guild_only_command")
|
||||
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||
.apply(user("performer", ctx.getSource().getAuthor()))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
return 1;
|
||||
|
@ -196,16 +199,24 @@ public class NoteCommand extends BaseCommand {
|
|||
.send(getBot(), channel).queue();
|
||||
|
||||
} else {
|
||||
// channel.sendMessage(messages().MODERATION.noteList(
|
||||
// NoteStorage.get(getBot().getStorage(), guild)
|
||||
// .getNotes()
|
||||
// .entrySet().stream()
|
||||
// .filter(predicate)
|
||||
// .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
// ).build(getBot())).queue();
|
||||
messages().getRegularMessage("moderation/note/list")
|
||||
.send(getBot(), channel).queue();
|
||||
// TODO: fix this
|
||||
messages().<Map.Entry<Integer, NoteEntry>>getListingMessage("moderation/note/list")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.amountPerPage(8)
|
||||
.setEntryApplier((entry, subs) -> subs
|
||||
.with("note_entry.note_id", () -> String.valueOf(entry.getKey()))
|
||||
.apply(user("note_entry.performer", entry.getValue().getPerformer()))
|
||||
.apply(user("note_entry.target", entry.getValue().getTarget()))
|
||||
.with("note_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
||||
.with("note_entry.contents", entry.getValue()::getContents)
|
||||
)
|
||||
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||
NoteStorage.get(getBot().getStorage(), guild)
|
||||
.getNotes()
|
||||
.entrySet().stream()
|
||||
.filter(predicate)
|
||||
.sorted(Comparator.<Map.Entry<Integer, NoteEntry>>comparingInt(Map.Entry::getKey).reversed())
|
||||
.collect(ImmutableList.toImmutableList())
|
||||
);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -214,7 +225,7 @@ public class NoteCommand extends BaseCommand {
|
|||
MessageChannel channel = ctx.getSource().getChannel();
|
||||
if (!ctx.getSource().isFromGuild()) {
|
||||
messages().getRegularMessage("general/error/guild_only_command")
|
||||
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||
.apply(user("performer", ctx.getSource().getAuthor()))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
return 1;
|
||||
|
@ -243,7 +254,7 @@ public class NoteCommand extends BaseCommand {
|
|||
|
||||
messages().getRegularMessage("moderation/note/remove")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.noteEntry("note_entry", noteID, entry))
|
||||
.apply(noteEntry("note_entry", noteID, entry))
|
||||
.send(getBot(), channel).queue();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
@ -11,8 +12,10 @@ import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
|||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -23,6 +26,8 @@ import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMember
|
|||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.user;
|
||||
|
||||
public class WarnListCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
@ -93,16 +98,24 @@ public class WarnListCommand extends BaseCommand {
|
|||
.send(getBot(), channel).queue();
|
||||
|
||||
} else {
|
||||
// channel.sendMessage(messages().MODERATION.warnList(
|
||||
// WarningStorage.get(getBot().getStorage(), guild)
|
||||
// .getWarnings()
|
||||
// .entrySet().stream()
|
||||
// .filter(predicate)
|
||||
// .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))
|
||||
// ).build(getBot())).queue();
|
||||
messages().getRegularMessage("moderation/warn/list")
|
||||
.send(getBot(), channel).queue();
|
||||
// TODO: fix this
|
||||
messages().<Map.Entry<Integer, WarningEntry>>getListingMessage("moderation/warn/list")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.amountPerPage(8)
|
||||
.setEntryApplier((entry, subs) -> subs
|
||||
.with("warning_entry.case_id", () -> String.valueOf(entry.getKey()))
|
||||
.apply(user("warning_entry.performer", entry.getValue().getPerformer()))
|
||||
.apply(user("warning_entry.warned", entry.getValue().getWarned()))
|
||||
.with("warning_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
||||
.with("warning_entry.reason", entry.getValue()::getReason)
|
||||
)
|
||||
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||
WarningStorage.get(getBot().getStorage(), guild)
|
||||
.getWarnings()
|
||||
.entrySet().stream()
|
||||
.filter(predicate)
|
||||
.sorted(Comparator.<Map.Entry<Integer, WarningEntry>>comparingInt(Map.Entry::getKey).reversed())
|
||||
.collect(ImmutableList.toImmutableList())
|
||||
);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
161
src/main/java/sciwhiz12/janitor/msg/ListingMessageBuilder.java
Normal file
161
src/main/java/sciwhiz12/janitor/msg/ListingMessageBuilder.java
Normal file
|
@ -0,0 +1,161 @@
|
|||
package sciwhiz12.janitor.msg;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.msg.json.ListingMessage;
|
||||
import sciwhiz12.janitor.msg.substitution.CustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ListingMessageBuilder<T> implements IHasCustomSubstitutions<ListingMessageBuilder<T>> {
|
||||
private final ListingMessage message;
|
||||
private final Map<String, Supplier<String>> customSubstitutions;
|
||||
private int amountPerPage = 10;
|
||||
private BiConsumer<T, CustomSubstitutions> entryApplier = (entry, sub) -> {};
|
||||
|
||||
public ListingMessageBuilder(ListingMessage message, Map<String, Supplier<String>> customSubstitutions) {
|
||||
this.message = message;
|
||||
this.customSubstitutions = customSubstitutions;
|
||||
}
|
||||
|
||||
public ListingMessageBuilder(ListingMessage message) {
|
||||
this(message, new HashMap<>());
|
||||
}
|
||||
|
||||
public ListingMessageBuilder<T> amountPerPage(int amountPerPage) {
|
||||
this.amountPerPage = amountPerPage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListingMessageBuilder<T> setEntryApplier(BiConsumer<T, CustomSubstitutions> entryApplier) {
|
||||
this.entryApplier = entryApplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListingMessageBuilder<T> apply(Consumer<ListingMessageBuilder<T>> consumer) {
|
||||
consumer.accept(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListingMessageBuilder<T> with(final String argument, final Supplier<String> value) {
|
||||
this.customSubstitutions.put(argument, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build(MessageChannel channel, TranslationMap translations, SubstitutionMap globalSubstitutions,
|
||||
Message triggerMessage, List<T> entries) {
|
||||
|
||||
final CustomSubstitutions customSubs = globalSubstitutions.with(customSubstitutions);
|
||||
final ImmutableList<T> list = ImmutableList.copyOf(entries);
|
||||
final PagedMessage pagedMessage = new PagedMessage(message, list, amountPerPage);
|
||||
|
||||
channel.sendMessage(pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
.queue(listMsg -> translations.getBot().getReactionManager().newMessage(listMsg)
|
||||
.owner(triggerMessage.getAuthor().getIdLong())
|
||||
.removeEmotes(true)
|
||||
.add("\u2b05", (msg, event) -> { // PREVIOUS
|
||||
if (pagedMessage.advancePage(PageDirection.PREVIOUS)) {
|
||||
event.retrieveMessage()
|
||||
.flatMap(eventMsg -> eventMsg.editMessage(
|
||||
pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
)
|
||||
.queue();
|
||||
}
|
||||
})
|
||||
.add("\u274c", (msg, event) -> { // CLOSE
|
||||
event.getChannel().deleteMessageById(event.getMessageIdLong())
|
||||
.flatMap(v -> !triggerMessage.isFromGuild() ||
|
||||
event.getGuild().getSelfMember()
|
||||
.hasPermission(triggerMessage.getTextChannel(),
|
||||
Permission.MESSAGE_MANAGE),
|
||||
v -> triggerMessage.delete())
|
||||
.queue();
|
||||
})
|
||||
.add("\u27a1", (msg, event) -> { // NEXT
|
||||
if (pagedMessage.advancePage(PageDirection.NEXT)) {
|
||||
event.retrieveMessage()
|
||||
.flatMap(eventMsg -> eventMsg.editMessage(
|
||||
pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
)
|
||||
.queue();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
);
|
||||
}
|
||||
|
||||
public void build(MessageChannel channel, JanitorBot bot, Message triggerMessage, List<T> entries) {
|
||||
build(channel, bot.getTranslations(), bot.getSubstitutions(), triggerMessage, entries);
|
||||
}
|
||||
|
||||
class PagedMessage {
|
||||
private final ListingMessage message;
|
||||
private final ImmutableList<T> list;
|
||||
private final int maxPages;
|
||||
private final int amountPerPage;
|
||||
private int currentPage = 0;
|
||||
private int lastPage = -1;
|
||||
private EmbedBuilder cachedMessage;
|
||||
|
||||
PagedMessage(ListingMessage message, ImmutableList<T> list, int amountPerPage) {
|
||||
this.message = message;
|
||||
this.list = list;
|
||||
this.amountPerPage = amountPerPage;
|
||||
this.maxPages = Math.floorDiv(list.size(), ListingMessageBuilder.this.amountPerPage);
|
||||
}
|
||||
|
||||
public int getMaxPages() {
|
||||
return maxPages;
|
||||
}
|
||||
|
||||
public int getCurrentPage() {
|
||||
return currentPage;
|
||||
}
|
||||
|
||||
public boolean advancePage(PageDirection direction) {
|
||||
if (direction == PageDirection.PREVIOUS && currentPage > 0) {
|
||||
currentPage -= 1;
|
||||
return true;
|
||||
} else if (direction == PageDirection.NEXT && currentPage < maxPages) {
|
||||
currentPage += 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public MessageEmbed createMessage(TranslationMap translations, CustomSubstitutions substitutions,
|
||||
BiConsumer<T, CustomSubstitutions> applier) {
|
||||
if (currentPage != lastPage) {
|
||||
cachedMessage = message.create(
|
||||
translations,
|
||||
substitutions.with(new HashMap<>())
|
||||
.with("page.max", () -> String.valueOf(maxPages + 1))
|
||||
.with("page.current", () -> String.valueOf(currentPage + 1)),
|
||||
list.stream()
|
||||
.skip(currentPage * amountPerPage)
|
||||
.limit(amountPerPage)
|
||||
.collect(Collectors.toList()),
|
||||
applier);
|
||||
lastPage = currentPage;
|
||||
}
|
||||
return cachedMessage.build();
|
||||
}
|
||||
}
|
||||
|
||||
enum PageDirection {
|
||||
PREVIOUS, NEXT
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import net.dv8tion.jda.api.entities.Role;
|
|||
import net.dv8tion.jda.api.entities.User;
|
||||
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
|
@ -18,19 +19,19 @@ import static java.time.temporal.ChronoField.*;
|
|||
public class MessageHelper {
|
||||
private MessageHelper() {}
|
||||
|
||||
public static Consumer<RegularMessageBuilder> snowflake(String head, ISnowflake snowflake) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> snowflake(String head, ISnowflake snowflake) {
|
||||
return builder -> builder
|
||||
.with(head + ".id", snowflake::getId)
|
||||
.with(head + ".creation_datetime", () -> snowflake.getTimeCreated().format(DATE_TIME_FORMAT));
|
||||
}
|
||||
|
||||
public static Consumer<RegularMessageBuilder> mentionable(String head, IMentionable mentionable) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> mentionable(String head, IMentionable mentionable) {
|
||||
return builder -> builder
|
||||
.apply(snowflake(head, mentionable))
|
||||
.with(head + ".mention", mentionable::getAsMention);
|
||||
}
|
||||
|
||||
public static Consumer<RegularMessageBuilder> role(String head, Role role) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> role(String head, Role role) {
|
||||
return builder -> builder
|
||||
.apply(mentionable(head, role))
|
||||
.with(head + ".color_hex", () -> Integer.toHexString(role.getColorRaw()))
|
||||
|
@ -38,7 +39,7 @@ public class MessageHelper {
|
|||
.with(head + ".permissions", role.getPermissions()::toString);
|
||||
}
|
||||
|
||||
public static Consumer<RegularMessageBuilder> user(String head, User user) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> user(String head, User user) {
|
||||
return builder -> builder
|
||||
.apply(mentionable(head, user))
|
||||
.with(head + ".name", user::getName)
|
||||
|
@ -47,7 +48,7 @@ public class MessageHelper {
|
|||
.with(head + ".flags", user.getFlags()::toString);
|
||||
}
|
||||
|
||||
public static Consumer<RegularMessageBuilder> guild(String head, Guild guild) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> guild(String head, Guild guild) {
|
||||
return builder -> builder
|
||||
.apply(snowflake(head, guild))
|
||||
.with(head + ".name", guild::getName)
|
||||
|
@ -60,7 +61,7 @@ public class MessageHelper {
|
|||
.with(head + ".icon_url", guild::getIconUrl);
|
||||
}
|
||||
|
||||
public static Consumer<RegularMessageBuilder> member(String head, Member member) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> member(String head, Member member) {
|
||||
return builder -> builder
|
||||
.apply(user(head, member.getUser()))
|
||||
.apply(guild(head + ".guild", member.getGuild()))
|
||||
|
@ -70,7 +71,7 @@ public class MessageHelper {
|
|||
.with(head + ".color", () -> String.valueOf(member.getColorRaw()));
|
||||
}
|
||||
|
||||
public static Consumer<RegularMessageBuilder> warningEntry(String head, int caseID, WarningEntry entry) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> warningEntry(String head, int caseID, WarningEntry entry) {
|
||||
return builder -> builder
|
||||
.with(head + ".case_id", () -> String.valueOf(caseID))
|
||||
.apply(user(head + ".performer", entry.getPerformer()))
|
||||
|
@ -79,7 +80,7 @@ public class MessageHelper {
|
|||
.with(head + ".reason", entry::getReason);
|
||||
}
|
||||
|
||||
public static Consumer<RegularMessageBuilder> noteEntry(String head, int noteID, NoteEntry entry) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> noteEntry(String head, int noteID, NoteEntry entry) {
|
||||
return builder -> builder
|
||||
.with(head + ".note_id", () -> String.valueOf(noteID))
|
||||
.apply(user(head + ".performer", entry.getPerformer()))
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.msg.json.ListingMessage;
|
||||
import sciwhiz12.janitor.msg.json.RegularMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -31,6 +32,7 @@ public class Messages {
|
|||
private final JanitorBot bot;
|
||||
private final Path messagesFolder;
|
||||
private final Map<String, RegularMessage> regularMessages = new HashMap<>();
|
||||
private final Map<String, ListingMessage> listingMessages = new HashMap<>();
|
||||
private final ObjectMapper jsonMapper = new ObjectMapper();
|
||||
|
||||
public Messages(JanitorBot bot, Path messagesFolder) {
|
||||
|
@ -39,13 +41,17 @@ public class Messages {
|
|||
loadMessages();
|
||||
}
|
||||
|
||||
public JanitorBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
public void loadMessages() {
|
||||
boolean success = false;
|
||||
|
||||
if (messagesFolder != null) {
|
||||
JANITOR.debug(MESSAGES, "Loading messages from folder {}", messagesFolder);
|
||||
success = loadMessages(
|
||||
path -> Files.newBufferedReader(messagesFolder.resolve(path + JSON_FILE_SUFFIX))
|
||||
path -> Files.newBufferedReader(messagesFolder.resolve(path + JSON_FILE_SUFFIX))
|
||||
);
|
||||
} else {
|
||||
JANITOR.info(MESSAGES, "No custom messages folder specified");
|
||||
|
@ -55,7 +61,7 @@ public class Messages {
|
|||
JANITOR.info(MESSAGES, "Loading default messages");
|
||||
//noinspection UnstableApiUsage
|
||||
loadMessages(
|
||||
file -> new InputStreamReader(getResource(DEFAULT_MESSAGES_FOLDER + file + JSON_FILE_SUFFIX).openStream())
|
||||
file -> new InputStreamReader(getResource(DEFAULT_MESSAGES_FOLDER + file + JSON_FILE_SUFFIX).openStream())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -68,8 +74,11 @@ public class Messages {
|
|||
final String path = messageKey.replace("/", FileSystems.getDefault().getSeparator());
|
||||
try (Reader reader = files.open(path)) {
|
||||
final JsonNode tree = jsonMapper.readTree(reader);
|
||||
if ("regular".equals(tree.path("type").asText("regular"))) {
|
||||
final String type = tree.path("type").asText("regular");
|
||||
if ("regular".equals(type)) {
|
||||
regularMessages.put(messageKey, jsonMapper.convertValue(tree, RegularMessage.class));
|
||||
} else if ("listing".equals(type)) {
|
||||
listingMessages.put(messageKey, jsonMapper.convertValue(tree, ListingMessage.class));
|
||||
} else {
|
||||
JANITOR.warn(MESSAGES, "Unknown message type {} for {}", tree.path("type").asText(), messageKey);
|
||||
}
|
||||
|
@ -92,28 +101,61 @@ public class Messages {
|
|||
public RegularMessageBuilder getRegularMessage(String messageKey) {
|
||||
final RegularMessage msg = regularMessages.get(messageKey);
|
||||
if (msg == null) {
|
||||
JANITOR.warn(MESSAGES, "Attempted to get unknown message with key {}", messageKey);
|
||||
return new RegularMessageBuilder(UNKNOWN_MESSAGE).with("key", () -> messageKey);
|
||||
JANITOR.warn(MESSAGES, "Attempted to get unknown regular message with key {}", messageKey);
|
||||
return new RegularMessageBuilder(UNKNOWN_REGULAR_MESSAGE).with("key", () -> messageKey);
|
||||
}
|
||||
return new RegularMessageBuilder(msg);
|
||||
}
|
||||
|
||||
public Map<String, ListingMessage> getListingMessages() {
|
||||
return listingMessages;
|
||||
}
|
||||
|
||||
public <T> ListingMessageBuilder<T> getListingMessage(String messageKey) {
|
||||
final ListingMessage msg = listingMessages.get(messageKey);
|
||||
if (msg == null) {
|
||||
JANITOR.warn(MESSAGES, "Attempted to get unknown listing message with key {}", messageKey);
|
||||
return new ListingMessageBuilder<T>(UNKNOWN_LISTING_MESSAGE).with("key", () -> messageKey);
|
||||
}
|
||||
return new ListingMessageBuilder<>(msg);
|
||||
}
|
||||
|
||||
interface FileOpener {
|
||||
Reader open(String filePath) throws IOException;
|
||||
}
|
||||
|
||||
public static final RegularMessage UNKNOWN_MESSAGE = new RegularMessage(
|
||||
"UNKNOWN MESSAGE!",
|
||||
null,
|
||||
"A message was tried to be looked up, but was not found. Please report this to your bot maintainer/administrator.",
|
||||
String.valueOf(0xFF0000),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Collections.singletonList(new MessageEmbed.Field("Message Key", "${key}", false))
|
||||
public static final RegularMessage UNKNOWN_REGULAR_MESSAGE = new RegularMessage(
|
||||
"UNKNOWN MESSAGE!",
|
||||
null,
|
||||
"A regular message was tried to be looked up, but was not found. Please report this to your bot " +
|
||||
"maintainer/administrator.",
|
||||
String.valueOf(0xFF0000),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Collections.singletonList(new MessageEmbed.Field("Message Key", "${key}", false))
|
||||
);
|
||||
|
||||
public static final ListingMessage UNKNOWN_LISTING_MESSAGE = new ListingMessage(
|
||||
"UNKNOWN MESSAGE!",
|
||||
null,
|
||||
"A listing message was tried to be looked up, but was not found. " +
|
||||
"Please report this to your bot maintainer/administrator.",
|
||||
String.valueOf(0xFF0000),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new ListingMessage.DescriptionEntry(null, ""),
|
||||
Collections.singletonList(new MessageEmbed.Field("Message Key", "${key}", false)),
|
||||
Collections.emptyList()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import net.dv8tion.jda.api.entities.MessageEmbed;
|
|||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.msg.json.RegularMessage;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -12,7 +13,7 @@ import java.util.Map;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class RegularMessageBuilder {
|
||||
public class RegularMessageBuilder implements IHasCustomSubstitutions<RegularMessageBuilder> {
|
||||
private final RegularMessage message;
|
||||
private final Map<String, Supplier<String>> customSubstitutions;
|
||||
|
||||
|
|
|
@ -77,4 +77,8 @@ public class TranslationMap {
|
|||
return matcher.replaceAll(
|
||||
matchResult -> quoteReplacement(translations.getOrDefault(matchResult.group(1), matchResult.group(0))));
|
||||
}
|
||||
|
||||
public JanitorBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package sciwhiz12.janitor.msg.emote;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ReactionManager extends ListenerAdapter {
|
||||
private final JanitorBot bot;
|
||||
private final Map<Long, ReactionMessage> messageMap = new HashMap<>();
|
||||
|
||||
public ReactionManager(JanitorBot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
public ReactionMessage newMessage(Message message) {
|
||||
if (messageMap.containsKey(message.getIdLong())) {
|
||||
throw new IllegalArgumentException("Reaction message already exists for message with id " + message.getIdLong());
|
||||
}
|
||||
final ReactionMessage msg = new ReactionMessage(bot, message);
|
||||
messageMap.put(message.getIdLong(), msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void removeMessage(long messageID) {
|
||||
bot.getDiscord().removeEventListener(messageMap.remove(messageID));
|
||||
}
|
||||
|
||||
public Map<Long, ReactionMessage> getRegisteredMessages() {
|
||||
return messageMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageDelete(@Nonnull MessageDeleteEvent event) {
|
||||
if (messageMap.containsKey(event.getMessageIdLong())) {
|
||||
bot.getDiscord().removeEventListener(messageMap.get(event.getMessageIdLong()));
|
||||
}
|
||||
}
|
||||
}
|
112
src/main/java/sciwhiz12/janitor/msg/emote/ReactionMessage.java
Normal file
112
src/main/java/sciwhiz12/janitor/msg/emote/ReactionMessage.java
Normal file
|
@ -0,0 +1,112 @@
|
|||
package sciwhiz12.janitor.msg.emote;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageReaction.ReactionEmote;
|
||||
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
|
||||
import net.dv8tion.jda.api.exceptions.ErrorHandler;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static net.dv8tion.jda.api.Permission.MESSAGE_MANAGE;
|
||||
|
||||
public class ReactionMessage extends ListenerAdapter {
|
||||
private final JanitorBot bot;
|
||||
private final Message message;
|
||||
private final Map<ReactionEmote, IReactionListener> emotes = new LinkedHashMap<>();
|
||||
private boolean removeEmotes = true;
|
||||
private long ownerID;
|
||||
private boolean onlyOwner;
|
||||
|
||||
public ReactionMessage(JanitorBot bot, Message message, boolean onlyOwner, long ownerID) {
|
||||
this.bot = bot;
|
||||
this.message = message;
|
||||
this.ownerID = ownerID;
|
||||
this.onlyOwner = onlyOwner;
|
||||
}
|
||||
|
||||
public ReactionMessage(JanitorBot bot, Message message) {
|
||||
this(bot, message, false, 0);
|
||||
}
|
||||
|
||||
public ReactionMessage add(ReactionEmote emote, IReactionListener listener) {
|
||||
emotes.put(emote, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReactionMessage add(String emote, IReactionListener listener) {
|
||||
return add(ReactionEmote.fromUnicode(emote, bot.getDiscord()), listener);
|
||||
}
|
||||
|
||||
public ReactionMessage add(Emote emote, IReactionListener listener) {
|
||||
return add(ReactionEmote.fromCustom(emote), listener);
|
||||
}
|
||||
|
||||
public ReactionMessage removeEmotes(boolean remove) {
|
||||
this.removeEmotes = remove;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReactionMessage owner(long ownerID) {
|
||||
this.ownerID = ownerID;
|
||||
this.onlyOwner = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void create() {
|
||||
for (ReactionEmote reaction : emotes.keySet()) {
|
||||
if (reaction.isEmote()) {
|
||||
message.addReaction(reaction.getEmote()).queue();
|
||||
} else {
|
||||
message.addReaction(reaction.getEmoji()).queue();
|
||||
}
|
||||
}
|
||||
bot.getDiscord().addEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageReactionAdd(@Nonnull MessageReactionAddEvent event) {
|
||||
if (event.getMessageIdLong() != message.getIdLong()) return;
|
||||
if (event.getUserIdLong() == bot.getDiscord().getSelfUser().getIdLong()) return;
|
||||
if (onlyOwner && event.getUserIdLong() != ownerID) return;
|
||||
|
||||
emotes.keySet().stream()
|
||||
.filter(emote -> event.getReactionEmote().equals(emote))
|
||||
.forEach(emote -> emotes.get(emote).accept(this, event));
|
||||
|
||||
if (removeEmotes && (!event.isFromGuild()
|
||||
|| event.getGuild().getSelfMember().hasPermission(event.getTextChannel(), MESSAGE_MANAGE))) {
|
||||
event.retrieveUser()
|
||||
.flatMap(user -> event.getReaction().removeReaction(user))
|
||||
.queue(null, new ErrorHandler().ignore(ErrorResponse.UNKNOWN_MESSAGE));
|
||||
}
|
||||
}
|
||||
|
||||
public JanitorBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
public long getOwnerID() {
|
||||
return ownerID;
|
||||
}
|
||||
|
||||
public boolean isOwnerOnly() {
|
||||
return onlyOwner;
|
||||
}
|
||||
|
||||
public Map<ReactionEmote, IReactionListener> getListeners() {
|
||||
return Collections.unmodifiableMap(emotes);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IReactionListener extends BiConsumer<ReactionMessage, MessageReactionAddEvent> {
|
||||
void accept(ReactionMessage message, MessageReactionAddEvent event);
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package sciwhiz12.janitor.msg.json;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
|
||||
public interface IMessage {
|
||||
EmbedBuilder create(TranslationMap translations, ISubstitutor substitutions);
|
||||
}
|
|
@ -1,61 +1,254 @@
|
|||
package sciwhiz12.janitor.msg.json;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.google.common.primitives.Ints;
|
||||
import joptsimple.internal.Strings;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.substitution.CustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@JsonDeserialize(using = ListingMessageDeserializer.class)
|
||||
public class ListingMessage {
|
||||
protected final String url;
|
||||
protected final String title;
|
||||
protected final String description;
|
||||
protected final OffsetDateTime timestamp;
|
||||
protected final int color;
|
||||
protected final MessageEmbed.Thumbnail thumbnail;
|
||||
protected final MessageEmbed.AuthorInfo author;
|
||||
protected final MessageEmbed.Footer footer;
|
||||
protected final MessageEmbed.ImageInfo image;
|
||||
protected final Multimap<FieldPlacement, MessageEmbed.Field> fields;
|
||||
@Nullable protected final String title;
|
||||
@Nullable protected final String url;
|
||||
@Nullable protected final String description;
|
||||
@Nullable protected final String color;
|
||||
@Nullable protected final String authorName;
|
||||
@Nullable protected final String authorUrl;
|
||||
@Nullable protected final String authorIconUrl;
|
||||
@Nullable protected final String footerText;
|
||||
@Nullable protected final String footerIconUrl;
|
||||
@Nullable protected final String imageUrl;
|
||||
@Nullable protected final String thumbnailUrl;
|
||||
@Nullable protected final String emptyText;
|
||||
protected final Entry entry;
|
||||
protected final List<MessageEmbed.Field> beforeFields;
|
||||
protected final List<MessageEmbed.Field> afterFields;
|
||||
|
||||
@Deprecated
|
||||
public ListingMessage() {
|
||||
this(null, null, null, null, 0, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public ListingMessage(MessageEmbed embed) {
|
||||
this(embed.getUrl(),
|
||||
embed.getTitle(),
|
||||
embed.getDescription(),
|
||||
embed.getTimestamp(),
|
||||
embed.getColorRaw(),
|
||||
embed.getThumbnail(),
|
||||
embed.getAuthor(),
|
||||
embed.getFooter(),
|
||||
embed.getImage(),
|
||||
Multimaps.index(embed.getFields(), k -> FieldPlacement.BEFORE));
|
||||
}
|
||||
|
||||
public ListingMessage(String url, String title, String description, OffsetDateTime timestamp, int color,
|
||||
MessageEmbed.Thumbnail thumbnail, MessageEmbed.AuthorInfo author, MessageEmbed.Footer footer,
|
||||
MessageEmbed.ImageInfo image, Multimap<FieldPlacement, MessageEmbed.Field> fields) {
|
||||
this.url = url;
|
||||
public ListingMessage(
|
||||
@Nullable String title,
|
||||
@Nullable String url,
|
||||
@Nullable String description,
|
||||
@Nullable String color,
|
||||
@Nullable String authorName,
|
||||
@Nullable String authorUrl,
|
||||
@Nullable String authorIconUrl,
|
||||
@Nullable String footerText,
|
||||
@Nullable String footerIconUrl,
|
||||
@Nullable String imageUrl,
|
||||
@Nullable String thumbnailUrl,
|
||||
@Nullable String emptyText,
|
||||
Entry entry,
|
||||
List<MessageEmbed.Field> beforeFields,
|
||||
List<MessageEmbed.Field> afterFields
|
||||
) {
|
||||
this.title = title;
|
||||
this.url = url;
|
||||
this.description = description;
|
||||
this.timestamp = timestamp;
|
||||
this.color = color;
|
||||
this.thumbnail = thumbnail;
|
||||
this.author = author;
|
||||
this.footer = footer;
|
||||
this.image = image;
|
||||
this.fields = fields;
|
||||
this.authorName = authorName;
|
||||
this.authorUrl = authorUrl;
|
||||
this.authorIconUrl = authorIconUrl;
|
||||
this.footerText = footerText;
|
||||
this.footerIconUrl = footerIconUrl;
|
||||
this.imageUrl = imageUrl;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.emptyText = emptyText;
|
||||
this.entry = entry;
|
||||
this.beforeFields = beforeFields;
|
||||
this.afterFields = afterFields;
|
||||
}
|
||||
|
||||
public enum ListingType {
|
||||
DESCRIPTION, FIELDS
|
||||
@Nullable
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public enum FieldPlacement {
|
||||
BEFORE, AFTER;
|
||||
@Nullable
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAuthorName() {
|
||||
return authorName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAuthorUrl() {
|
||||
return authorUrl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAuthorIconUrl() {
|
||||
return authorIconUrl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getFooterText() {
|
||||
return footerText;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getFooterIconUrl() {
|
||||
return footerIconUrl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getThumbnailUrl() {
|
||||
return thumbnailUrl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getEmptyText() {
|
||||
return emptyText;
|
||||
}
|
||||
|
||||
public Entry getEntry() {
|
||||
return entry;
|
||||
}
|
||||
|
||||
public List<MessageEmbed.Field> getBeforeFields() {
|
||||
return beforeFields;
|
||||
}
|
||||
|
||||
public List<MessageEmbed.Field> getAfterFields() {
|
||||
return afterFields;
|
||||
}
|
||||
|
||||
public <T> EmbedBuilder create(
|
||||
TranslationMap translations,
|
||||
ISubstitutor global,
|
||||
Iterable<T> iterable,
|
||||
BiConsumer<T, CustomSubstitutions> entryApplier
|
||||
) {
|
||||
final Function<String, String> func = str -> str != null ? global.substitute(translations.translate(str)) : null;
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle(func.apply(title), func.apply(url));
|
||||
builder.setColor(parseColor(global.substitute(color)));
|
||||
builder.setAuthor(func.apply(authorName), func.apply(authorUrl), func.apply(authorIconUrl));
|
||||
builder.setDescription(func.apply(description));
|
||||
builder.setImage(func.apply(imageUrl));
|
||||
builder.setThumbnail(func.apply(thumbnailUrl));
|
||||
builder.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||
builder.setFooter(func.apply(footerText), func.apply(footerIconUrl));
|
||||
for (MessageEmbed.Field field : beforeFields) {
|
||||
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||
}
|
||||
|
||||
final CustomSubstitutions entrySubs = new CustomSubstitutions();
|
||||
final Function<String, String> entryFunc = str -> str != null ? entrySubs.substitute(func.apply(str)) : null;
|
||||
int count = 0;
|
||||
for (T listEntry : iterable) {
|
||||
entryApplier.accept(listEntry, entrySubs);
|
||||
if (entry instanceof FieldEntry) {
|
||||
FieldEntry fieldEntry = (FieldEntry) entry;
|
||||
builder.addField(
|
||||
entryFunc.apply(fieldEntry.getFieldName()),
|
||||
entryFunc.apply(fieldEntry.getFieldValue()),
|
||||
fieldEntry.isInline()
|
||||
);
|
||||
} else if (entry instanceof DescriptionEntry) {
|
||||
DescriptionEntry descEntry = (DescriptionEntry) entry;
|
||||
builder.getDescriptionBuilder().append(entryFunc.apply(descEntry.getDescription()));
|
||||
builder.getDescriptionBuilder().append(descEntry.getJoiner());
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (count < 1) {
|
||||
builder.getDescriptionBuilder().append(func.apply(emptyText));
|
||||
}
|
||||
|
||||
for (MessageEmbed.Field field : afterFields) {
|
||||
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static int parseColor(String str) {
|
||||
if (Strings.isNullOrEmpty(str)) return Role.DEFAULT_COLOR_RAW;
|
||||
if (str.startsWith("0x")) {
|
||||
// noinspection UnstableApiUsage
|
||||
final Integer res = Ints.tryParse(str.substring(2), 16);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
// noinspection UnstableApiUsage
|
||||
final Integer res = Ints.tryParse(str, 10);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
return Role.DEFAULT_COLOR_RAW;
|
||||
}
|
||||
|
||||
public interface Entry {}
|
||||
|
||||
public static class DescriptionEntry implements Entry {
|
||||
public static final String DEFAULT_JOINER = "\n";
|
||||
private final String joiner;
|
||||
private final String descriptionEntry;
|
||||
|
||||
public DescriptionEntry(@Nullable String joiner, String descriptionEntry) {
|
||||
this.joiner = joiner != null ? joiner : DEFAULT_JOINER;
|
||||
this.descriptionEntry = descriptionEntry;
|
||||
}
|
||||
|
||||
public String getJoiner() {
|
||||
return joiner;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return descriptionEntry;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FieldEntry implements Entry {
|
||||
private final String fieldName;
|
||||
private final String fieldValue;
|
||||
private final boolean inline;
|
||||
|
||||
public FieldEntry(String fieldName, String fieldValue, boolean inline) {
|
||||
this.fieldName = fieldName;
|
||||
this.fieldValue = fieldValue;
|
||||
this.inline = inline;
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
public String getFieldValue() {
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
public boolean isInline() {
|
||||
return inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
package sciwhiz12.janitor.msg.json;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ListingMessageDeserializer extends StdDeserializer<ListingMessage> {
|
||||
public ListingMessageDeserializer() {
|
||||
super(ListingMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListingMessage deserialize(JsonParser p, DeserializationContext ctx)
|
||||
throws IOException {
|
||||
|
||||
final JsonNode root = ctx.readTree(p);
|
||||
|
||||
String title = null;
|
||||
String url = null;
|
||||
String description = root.path("description").asText(null);
|
||||
String color = root.path("color").asText(null);
|
||||
String authorName = null;
|
||||
String authorUrl = null;
|
||||
String authorIconUrl = null;
|
||||
String footerText = null;
|
||||
String footerIconUrl = null;
|
||||
String imageUrl = root.path("image").asText(null);
|
||||
String thumbnailUrl = root.path("thumbnail").asText(null);
|
||||
String emptyText = root.path("empty").asText(null);
|
||||
List<MessageEmbed.Field> beforeFields = readFields(root.path("fields").path("before"));
|
||||
List<MessageEmbed.Field> afterFields = readFields(root.path("fields").path("after"));
|
||||
|
||||
// Title
|
||||
if (root.path("title").isTextual()) {
|
||||
title = root.path("title").asText();
|
||||
} else if (root.path("title").path("text").isTextual()) {
|
||||
title = root.path("title").path("text").asText();
|
||||
url = root.path("title").path("url").asText(null);
|
||||
}
|
||||
|
||||
// Author
|
||||
if (root.path("author").isTextual()) {
|
||||
authorName = root.path("author").asText();
|
||||
} else if (root.path("author").path("name").isTextual()) {
|
||||
authorName = root.path("author").path("name").asText();
|
||||
authorUrl = root.path("author").path("url").asText(null);
|
||||
authorIconUrl = root.path("author").path("icon_url").asText(null);
|
||||
}
|
||||
|
||||
// Footer
|
||||
if (root.path("footer").isTextual()) {
|
||||
footerText = root.path("footer").asText();
|
||||
} else if (root.path("footer").path("text").isTextual()) {
|
||||
footerText = root.path("footer").path("text").asText();
|
||||
footerIconUrl = root.path("footer").path("icon_url").asText(null);
|
||||
}
|
||||
|
||||
// ENTRY
|
||||
final ListingMessage.Entry entry = readEntry(root.path("entry"));
|
||||
|
||||
return new ListingMessage(title, url, description, color, authorName, authorUrl, authorIconUrl, footerText,
|
||||
footerIconUrl, imageUrl, thumbnailUrl, emptyText, entry, beforeFields, afterFields);
|
||||
}
|
||||
|
||||
public static ListingMessage.Entry readEntry(JsonNode root) {
|
||||
switch (root.path("type").asText()) {
|
||||
case "field": {
|
||||
return new ListingMessage.FieldEntry(
|
||||
root.path("name").asText(EmbedBuilder.ZERO_WIDTH_SPACE),
|
||||
root.path("value").asText(EmbedBuilder.ZERO_WIDTH_SPACE),
|
||||
root.path("inline").asBoolean(false)
|
||||
);
|
||||
}
|
||||
default:
|
||||
case "description": {
|
||||
return new ListingMessage.DescriptionEntry(
|
||||
root.path("joiner").asText(null),
|
||||
root.path("text").asText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MessageEmbed.Field> readFields(JsonNode node) {
|
||||
if (node.isArray()) {
|
||||
final ArrayList<MessageEmbed.Field> fields = new ArrayList<>();
|
||||
for (int i = 0; i < node.size(); i++) {
|
||||
final MessageEmbed.Field field = readField(node.path(i));
|
||||
if (field != null) {
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static MessageEmbed.Field readField(JsonNode fieldNode) {
|
||||
if (fieldNode.path("name").isTextual() && fieldNode.path("value").isTextual()) {
|
||||
return new MessageEmbed.Field(
|
||||
fieldNode.path("name").asText(),
|
||||
fieldNode.path("value").asText(),
|
||||
fieldNode.path("inline").asBoolean(false)
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@ import joptsimple.internal.Strings;
|
|||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
@ -20,7 +20,7 @@ import java.util.function.Function;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
@JsonDeserialize(using = RegularMessageDeserializer.class)
|
||||
public class RegularMessage implements IMessage {
|
||||
public class RegularMessage {
|
||||
@Nullable
|
||||
protected final String title;
|
||||
@Nullable
|
||||
|
@ -176,7 +176,6 @@ public class RegularMessage implements IMessage {
|
|||
thumbnailUrl, fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbedBuilder create(TranslationMap translations, ISubstitutor substitutions) {
|
||||
final Function<String, String> func = str -> str != null ? substitutions.substitute(translations.translate(str)) : null;
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
|
|
|
@ -1,20 +1,47 @@
|
|||
package sciwhiz12.janitor.msg.substitution;
|
||||
|
||||
import org.apache.commons.collections4.TransformerUtils;
|
||||
import org.apache.commons.collections4.map.DefaultedMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class CustomSubstitutions implements ISubstitutor {
|
||||
public class CustomSubstitutions implements ISubstitutor, IHasCustomSubstitutions<CustomSubstitutions> {
|
||||
private final Map<String, Supplier<String>> map;
|
||||
|
||||
public CustomSubstitutions(Map<String, Supplier<String>> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public CustomSubstitutions() {
|
||||
this(new HashMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String substitute(String text) {
|
||||
return SubstitutionMap.substitute(text, map);
|
||||
}
|
||||
|
||||
public CustomSubstitutions apply(Consumer<CustomSubstitutions> consumer) {
|
||||
consumer.accept(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CustomSubstitutions with(final String argument, final Supplier<String> value) {
|
||||
map.put(argument, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CustomSubstitutions with(Map<String, Supplier<String>> customSubstitutions) {
|
||||
return new CustomSubstitutions(createDefaultedMap(customSubstitutions));
|
||||
}
|
||||
|
||||
public Map<String, Supplier<String>> createDefaultedMap(Map<String, Supplier<String>> custom) {
|
||||
return DefaultedMap.defaultedMap(custom, TransformerUtils.mapTransformer(map));
|
||||
}
|
||||
|
||||
public Map<String, Supplier<String>> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package sciwhiz12.janitor.msg.substitution;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface IHasCustomSubstitutions<T extends IHasCustomSubstitutions<?>> {
|
||||
T with(String argument, Supplier<String> value);
|
||||
|
||||
T apply(Consumer<T> consumer);
|
||||
}
|
|
@ -110,9 +110,8 @@
|
|||
"moderation.note.remove.field.contents": "Text",
|
||||
"moderation.warnlist.author": "Listing of Warnings",
|
||||
"moderation.warnlist.empty": "**_No warnings logged matching your query._**",
|
||||
"moderation.warnlist.entry": "**Case #%1$s**: Warned %2$s by %3$s %n - _Date & Time:_ %4$s %n - _Reason:_ %5$s",
|
||||
"moderation.warnlist.entry.no_reason": "_no reason specified_",
|
||||
"moderation.note.list.author": "Listing of Notes",
|
||||
"moderation.warnlist.entry": "**Case #${warning_entry.case_id}**: Warned ${warning_entry.warned.mention} by ${warning_entry.performer.mention} \n - _Date & Time:_ ${warning_entry.date_time} \n - _Reason:_ ${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||
"moderation.note.list.author": "Listing of Notes (Page ${page.current}/${page.max})",
|
||||
"moderation.note.list.empty": "**_No recorded notes matching your query._**",
|
||||
"moderation.note.list.entry": "**#%1$s**: for %2$s by %3$s %n - _Date & Time:_ %4$s %n - _Text:_ %5$s"
|
||||
"moderation.note.list.entry": "**#${note_entry.note_id}**: for ${note_entry.target.mention} by ${note_entry.performer.mention} \n - _Date & Time:_ ${note_entry.date_time} \n - _Text:_ ${note_entry.contents}"
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
"moderation/unban/info",
|
||||
"moderation/warn/info",
|
||||
"moderation/warn/dm",
|
||||
"moderation/warn/list",
|
||||
"moderation/unwarn/info",
|
||||
"moderation/error/unwarn/no_case_found",
|
||||
"moderation/error/unwarn/cannot_unwarn_self",
|
||||
|
@ -22,5 +23,6 @@
|
|||
"moderation/error/note/max_amount_of_notes",
|
||||
"moderation/error/note/no_note_found",
|
||||
"moderation/note/add",
|
||||
"moderation/note/remove"
|
||||
"moderation/note/remove",
|
||||
"moderation/note/list"
|
||||
]
|
13
src/main/resources/messages/moderation/note/list.json
Normal file
13
src/main/resources/messages/moderation/note/list.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"type": "listing",
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.note.list.author>",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"entry": {
|
||||
"type": "description",
|
||||
"text": "<moderation.note.list.entry>"
|
||||
},
|
||||
"empty": "<moderation.note.list.empty>"
|
||||
}
|
13
src/main/resources/messages/moderation/warn/list.json
Normal file
13
src/main/resources/messages/moderation/warn/list.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"type": "listing",
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.warnlist.author>",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"entry": {
|
||||
"type": "description",
|
||||
"text": "<moderation.warnlist.entry>"
|
||||
},
|
||||
"empty": "<moderation.warnlist.empty>"
|
||||
}
|
Loading…
Reference in New Issue
Block a user