Cyclic Dependency Patch

- Fixed cyclic dependencies
- Added a TFShoppe class for effective plugin initialization
- Registered discord commands, did not before
- Added SLF4J loggers for module logging.
This commit is contained in:
Paul Reilly
2023-03-10 19:21:03 -06:00
parent b5804c7eb1
commit 3a96c853d2
38 changed files with 721 additions and 418 deletions

View File

@ -80,22 +80,6 @@ public class Bot
RATELIMIT_EXECUTOR.setRemoveOnCancelPolicy(true);
}
public String getCode(PlayerData playerData) {
for (String code : LINK_CODES.keySet())
{
if (LINK_CODES.get(code).equals(playerData))
{
return code;
}
}
return "";
}
public String generateCode(int size)
{
return RandomStringUtils.randomNumeric(size);
}
public String formatBotTag() {
return client.getSelf()
.blockOptional()
@ -106,94 +90,6 @@ public class Bot
.getDiscriminator();
}
public boolean syncRoles(Admin admin, String discordID)
{
if (discordID == null)
{
return false;
}
Guild server = client.getGuildById(SnowflakeEntry.serverID)
.blockOptional()
.orElseThrow();
Member member = server.getMemberById(Snowflake.of(discordID))
.blockOptional()
.orElseThrow();
Role adminRole = server.getRoleById(SnowflakeEntry.adminRoleID)
.blockOptional()
.orElseThrow();
Role senioradminRole = server.getRoleById(SnowflakeEntry.seniorRoleID)
.blockOptional()
.orElseThrow();
if (!admin.isActive())
{
syncRolesActivityCheck(member, adminRole, senioradminRole);
return true;
}
if (admin.getRank().equals(Rank.ADMIN))
{
syncRolesAdminAssignment(member, adminRole, senioradminRole);
return true;
}
else if (admin.getRank().equals(Rank.SENIOR_ADMIN))
{
syncRolesSeniorAssignment(member, adminRole, senioradminRole);
return true;
}
return false;
}
private void syncRolesAdminAssignment(Member member, Role adminRole, Role senioradminRole) {
member.getRoles().doFirst(() -> {
if (!member.getRoles().collectList().blockOptional().orElseThrow().contains(adminRole))
{
member.addRole(adminRole.getId()).block();
}
}).doOnEach(r -> {
Role role = r.get();
if (role == null) return;
if (role.equals(senioradminRole))
{
member.removeRole(role.getId()).block();
}
}).subscribe();
}
private void syncRolesActivityCheck(Member member, Role adminRole, Role senioradminRole) {
member.getRoles().doOnEach(r -> {
Role role = r.get();
if (role == null) return;
if (role.equals(adminRole) || role.equals(senioradminRole))
{
member.removeRole(role.getId()).block();
}
}).subscribe();
}
private void syncRolesSeniorAssignment(Member member, Role adminRole, Role senioradminRole) {
member.getRoles().doFirst(() -> {
if (!member.getRoles().collectList().blockOptional().orElseThrow().contains(senioradminRole))
{
member.addRole(senioradminRole.getId()).block();
}
}).doOnEach(r -> {
Role role = r.get();
if (role == null) return;
if (role.equals(adminRole))
{
member.removeRole(role.getId()).block();
}
}).subscribe();
}
private String poolIdentifier()
{

View File

@ -1,35 +1,77 @@
package me.totalfreedom.discord;
import me.totalfreedom.discord.command.HelpCommand;
import me.totalfreedom.discord.command.ListCommand;
import me.totalfreedom.discord.command.TPSCommand;
import me.totalfreedom.discord.handling.CommandHandler;
import me.totalfreedom.discord.listener.AdminChatListener;
import me.totalfreedom.discord.listener.BukkitNative;
import me.totalfreedom.discord.listener.MinecraftListener;
import me.totalfreedom.discord.util.Utilities;
import me.totalfreedom.totalfreedommod.api.Context;
import me.totalfreedom.totalfreedommod.api.TFD4JCommons;
import org.bukkit.plugin.java.JavaPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TFD4J extends JavaPlugin
{
private final Logger slf4j = LoggerFactory.getLogger("TFD4J");
private Bot bot;
private Utilities utils;
private MinecraftListener mc;
private AdminChatListener ac;
private TFD4JCommons tfd4jcommons;
private BukkitNative bn;
private CommandHandler ch;
@Override
public void onEnable()
{
slf4j().info("Hello from TFD4J! Initializing our API implementation...");
this.tfd4jcommons = new TFD4JCommonsImpl(this);
slf4j().info("API successfully initialized! Initializing our bot...");
this.bot = new Bot();
this.utils = new Utilities(this);
new BukkitNative(this);
slf4j().info("Bot successfully initialized! Registering the Bukkit Native listener...");
this.bn = new BukkitNative(this);
slf4j().info("Bukkit Native listener successfully registered! Registering the Discord4J Listeners...");
this.mc = new MinecraftListener(this);
this.ac = new AdminChatListener(this);
mc.minecraftChatBound();
ac.adminChatBound();
slf4j().info("Discord4J listeners successfully registered! Registering the Command Handler...");
this.ch = new CommandHandler(bot.getClient().getRestClient());
slf4j().info("Command Handler successfully registered! Registering commands...");
this.ch.registerCommand(new HelpCommand());
this.ch.registerCommand(new ListCommand());
this.ch.registerCommand(new TPSCommand());
slf4j().info("Commands successfully registered! Providing context to TFM...");
Context<TFD4JCommons> context = new Context<>(tfd4jcommons);
bot.getTFM().getCommons().ag.setDiscordContext(context);
bot.getTFM().getCommons().registerDiscord();
slf4j().info("Context provided! TFD4J is now ready to go!");
}
@Override
public void onDisable()
{
bot.getClient().onDisconnect().subscribe();
slf4j().info("Disconnecting the Discord bot...");
bot.getClient()
.onDisconnect()
.doOnError(th -> slf4j().error("Error disconnecting the bot!", th))
.doOnSuccess(v -> slf4j().info("Bot disconnected!"))
.subscribe();
slf4j().info("Goodbye from TFD4J!");
}
public Logger slf4j()
{
return slf4j;
}
public Bot getBot()
@ -37,9 +79,9 @@ public class TFD4J extends JavaPlugin
return bot;
}
public Utilities getUtils()
public TFD4JCommons getImpl()
{
return utils;
return tfd4jcommons;
}
public MinecraftListener getMinecraftListener()

View File

@ -0,0 +1,372 @@
package me.totalfreedom.discord;
import com.google.common.collect.ImmutableList;
import discord4j.common.util.Snowflake;
import discord4j.core.object.entity.Guild;
import discord4j.core.object.entity.Member;
import discord4j.core.object.entity.Message;
import discord4j.core.object.entity.Role;
import discord4j.core.object.entity.channel.TextChannel;
import discord4j.core.object.reaction.ReactionEmoji;
import discord4j.core.spec.EmbedCreateSpec;
import discord4j.core.spec.MessageCreateSpec;
import me.totalfreedom.discord.util.SnowflakeEntry;
import me.totalfreedom.discord.util.Utilities;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.api.TFD4JCommons;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.WordUtils;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class TFD4JCommonsImpl implements TFD4JCommons
{
private final TFD4J tfd4J;
private final ImmutableList<String> DISCORD_SUBDOMAINS;
private Flux<Message> sentMessages;
public TFD4JCommonsImpl(TFD4J tfd4J)
{
this.tfd4J = tfd4J;
this.sentMessages = Flux.fromIterable(new ArrayList<>());
this.DISCORD_SUBDOMAINS = (ImmutableList<String>)
List.of("discordapp.com",
"discord.com",
"discord.gg");
}
@Override
public void messageAdminChatChannel(String message)
{
String chat_channel_id = ConfigEntry.DISCORD_ADMINCHAT_CHANNEL_ID.getString();
String sanitizedMessage = sanitizeChatMessage(message);
if (sanitizedMessage.isBlank()) return;
if (!chat_channel_id.isEmpty())
{
MessageCreateSpec spec = MessageCreateSpec.builder()
.content(sanitizedMessage)
.build();
Mono<Message> sentMessage = tfd4J
.getBot()
.getClient()
.getChannelById(SnowflakeEntry.adminChatChannelID)
.ofType(TextChannel.class)
.flatMap(c -> c.createMessage(spec));
insert(sentMessage);
}
}
public Flux<Message> getMessagesSent()
{
return sentMessages;
}
private void insert(Mono<Message> messageMono)
{
sentMessages.concatWith(messageMono);
}
@Override
public void clearQueue()
{
sentMessages = Flux.fromIterable(new ArrayList<>());
}
@Override
public void messageChatChannel(String message, boolean system)
{
String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString();
String sanitizedMessage = (system) ? message : sanitizeChatMessage(message);
if (sanitizedMessage.isBlank()) return;
if (!chat_channel_id.isEmpty())
{
MessageCreateSpec spec = MessageCreateSpec.builder()
.content(sanitizedMessage)
.build();
Mono<Message> sentMessage = tfd4J
.getBot()
.getClient()
.getChannelById(SnowflakeEntry.chatChannelID)
.ofType(TextChannel.class)
.flatMap(c -> c.createMessage(spec));
insert(sentMessage);
}
}
private String sanitizeChatMessage(String message)
{
String newMessage = message;
if (message.contains("@"))
{
// \u200B is Zero Width Space, invisible on Discord
newMessage = message.replace("@", "@\u200B");
}
if (message.toLowerCase().contains("discord.gg")) // discord.gg/invite works as an invite
{
return "";
}
for (String subdomain : DISCORD_SUBDOMAINS)
{
if (message.toLowerCase().contains(subdomain + "/invite"))
{
return "";
}
}
if (message.contains("§"))
{
newMessage = message.replace("§", "");
}
return Utilities.deformat(newMessage);
}
@Override
public boolean syncRoles(Admin admin, String discordID)
{
if (discordID == null)
{
return false;
}
Guild server = tfd4J.getBot().getGuildById()
.blockOptional()
.orElseThrow();
Member member = server.getMemberById(Snowflake.of(discordID))
.blockOptional()
.orElseThrow();
Role adminRole = server.getRoleById(SnowflakeEntry.adminRoleID)
.blockOptional()
.orElseThrow();
Role senioradminRole = server.getRoleById(SnowflakeEntry.seniorRoleID)
.blockOptional()
.orElseThrow();
if (!admin.isActive())
{
syncRolesActivityCheck(member, adminRole, senioradminRole);
return true;
}
if (admin.getRank().equals(Rank.ADMIN))
{
syncRolesAdminAssignment(member, adminRole, senioradminRole);
return true;
} else if (admin.getRank().equals(Rank.SENIOR_ADMIN))
{
syncRolesSeniorAssignment(member, adminRole, senioradminRole);
return true;
}
return false;
}
private void syncRolesAdminAssignment(Member member, Role adminRole, Role senioradminRole)
{
member.getRoles().doFirst(() ->
{
if (!member.getRoles().collectList().blockOptional().orElseThrow().contains(adminRole))
{
member.addRole(adminRole.getId()).block();
}
}).doOnEach(r ->
{
Role role = r.get();
if (role == null) return;
if (role.equals(senioradminRole))
{
member.removeRole(role.getId()).block();
}
}).subscribe();
}
private void syncRolesActivityCheck(Member member, Role adminRole, Role senioradminRole)
{
member.getRoles().doOnEach(r ->
{
Role role = r.get();
if (role == null) return;
if (role.equals(adminRole) || role.equals(senioradminRole))
{
member.removeRole(role.getId()).block();
}
}).subscribe();
}
private void syncRolesSeniorAssignment(Member member, Role adminRole, Role senioradminRole)
{
member.getRoles().doFirst(() ->
{
if (!member.getRoles().collectList().blockOptional().orElseThrow().contains(senioradminRole))
{
member.addRole(senioradminRole.getId()).block();
}
}).doOnEach(r ->
{
Role role = r.get();
if (role == null) return;
if (role.equals(adminRole))
{
member.removeRole(role.getId()).block();
}
}).subscribe();
}
@Override
public String getCode(PlayerData playerData)
{
for (String code : this.getLinkCodes().keySet())
{
if (this.getLinkCodes().get(code).equals(playerData))
{
return code;
}
}
return "";
}
@Override
public String generateCode(int size)
{
return RandomStringUtils.randomNumeric(size);
}
@Override
public Map<String, PlayerData> getLinkCodes()
{
return tfd4J.getBot().getLinkCodes();
}
@Override
public String formatBotTag()
{
return tfd4J.getBot().formatBotTag();
}
@Override
public boolean sendReportOffline(Player reporter, OfflinePlayer reported, String reason)
{
if (!tfd4J.getBot().shouldISendReport())
{
return false;
}
final Guild server = tfd4J.getBot().getGuildById().block();
if (server == null) return false;
final TextChannel channel = server.getChannelById(SnowflakeEntry.reportChannelID)
.ofType(TextChannel.class)
.blockOptional()
.orElseThrow();
final EmbedCreateSpec.Builder builder = EmbedCreateSpec.builder()
.title("Report for " + reported.getName() + " (offline)")
.description(reason)
.footer("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png")
.timestamp(Instant.from(ZonedDateTime.now()));
if (tfd4J.getBot().getTFM().getCommons().esb.isEnabled())
{
com.earth2me.essentials.User user = tfd4J.getBot().getTFM().getCommons().esb.getEssentialsUser(reported.getName());
String location = "World: " + Objects.requireNonNull(user.getLastLocation().getWorld()).getName() + ", X: " + user.getLastLocation().getBlockX() + ", Y: " + user.getLastLocation().getBlockY() + ", Z: " + user.getLastLocation().getBlockZ();
builder.addField("Location", location, true);
builder.addField("God Mode", WordUtils.capitalizeFully(String.valueOf(user.isGodModeEnabled())), true);
if (user.getNickname() != null)
{
builder.addField("Nickname", user.getNickname(), true);
}
}
EmbedCreateSpec embed = builder.build();
Message message = channel.createMessage(embed).block();
if (message != null && !ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty())
{
message.addReaction(ReactionEmoji.unicode("\uD83D\uDCCB")).subscribe();
}
return true;
}
@Override
public boolean sendReport(Player reporter, Player reported, String reason)
{
if (!tfd4J.getBot().shouldISendReport())
{
return false;
}
final Guild server = tfd4J.getBot()
.getClient()
.getGuildById(SnowflakeEntry.serverID)
.block();
if (server == null)
{
FLog.severe("The guild ID specified in the config is invalid.");
return false;
}
final TextChannel channel = server.getChannelById(SnowflakeEntry.reportChannelID)
.ofType(TextChannel.class)
.blockOptional()
.orElseThrow();
String location = "World: " + Objects.requireNonNull(reported.getLocation().getWorld()).getName() + ", X: " + reported.getLocation().getBlockX() + ", Y: " + reported.getLocation().getBlockY() + ", Z: " + reported.getLocation().getBlockZ();
final EmbedCreateSpec spec = EmbedCreateSpec.builder()
.title("Report for " + reported.getName())
.description(reason)
.footer("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png")
.timestamp(Instant.from(ZonedDateTime.now()))
.addField("Location", location, true)
.addField("Game Mode", WordUtils.capitalizeFully(reported.getGameMode().name()), true)
.build();
Message message = channel.createMessage(spec).block();
if (!ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty() && message != null)
{
ReactionEmoji emoji = ReactionEmoji.unicode("\uD83D\uDCCB");
message.addReaction(emoji);
}
return true;
}
@Override
public boolean isEnabled()
{
return tfd4J.isEnabled();
}
}

View File

@ -1,18 +0,0 @@
package me.totalfreedom.discord;
import org.bukkit.Bukkit;
public class TFM_Accessor
{
private final TFD4J accessor;
public TFM_Accessor()
{
this.accessor = (TFD4J) Bukkit.getPluginManager().getPlugin("TFD4J");
}
public TFD4J botAccessor()
{
return accessor;
}
}

View File

@ -2,6 +2,7 @@ package me.totalfreedom.discord.listener;
import me.totalfreedom.discord.Bot;
import me.totalfreedom.discord.TFD4J;
import me.totalfreedom.discord.util.Utilities;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import net.kyori.adventure.text.Component;
@ -28,8 +29,6 @@ public class BukkitNative implements Listener
this.tfd4j = tfd4j;
this.bot = tfd4j.getBot();
this.commons = bot.getTFM().getCommons();
tfd4j.getServer().getPluginManager().registerEvents(this, tfd4j);
}
@EventHandler(priority = EventPriority.MONITOR)
@ -37,8 +36,8 @@ public class BukkitNative implements Listener
{
if (!commons.al.isVanished(event.getPlayer().getUniqueId()))
{
tfd4j.getUtils().messageChatChannel("**"
+ tfd4j.getUtils().deformat(event.getPlayer().getName())
tfd4j.getImpl().messageChatChannel("**"
+ Utilities.deformat(event.getPlayer().getName())
+ " joined the server" + "**", true);
}
}
@ -48,8 +47,8 @@ public class BukkitNative implements Listener
{
if (!commons.al.isVanished(event.getPlayer().getUniqueId()))
{
tfd4j.getUtils().messageChatChannel("**"
+ tfd4j.getUtils().deformat(event.getPlayer().getName())
tfd4j.getImpl().messageChatChannel("**"
+ Utilities.deformat(event.getPlayer().getName())
+ " left the server" + "**", true);
}
}
@ -68,8 +67,8 @@ public class BukkitNative implements Listener
if (deathMessage != null)
{
tfd4j.getUtils().messageChatChannel("**"
+ tfd4j.getUtils().deformat(PlainTextComponentSerializer.plainText().serialize(deathMessage))
tfd4j.getImpl().messageChatChannel("**"
+ Utilities.deformat(PlainTextComponentSerializer.plainText().serialize(deathMessage))
+ "**", true);
}
}
@ -83,7 +82,7 @@ public class BukkitNative implements Listener
if (!ConfigEntry.ADMIN_ONLY_MODE.getBoolean() && !tfd4j.getServer().hasWhitelist()
&& !commons.pl.getPlayer(player).isMuted() && bot != null)
{
tfd4j.getUtils().messageChatChannel(player.getName()
tfd4j.getImpl().messageChatChannel(player.getName()
+ " \u00BB "
+ ChatColor.stripColor(message), true);
}

View File

@ -28,204 +28,13 @@ import java.util.Objects;
public class Utilities
{
private Flux<Message> sentMessages = Flux.fromIterable(new ArrayList<>());
private final TFD4J tfd4J;
private final ImmutableList<String> DISCORD_SUBDOMAINS = (ImmutableList<String>)
List.of("discordapp.com",
"discord.com",
"discord.gg");
public Utilities(TFD4J tfd4J)
{
this.tfd4J = tfd4J;
private Utilities() {
throw new AssertionError();
}
public void clearQueue()
{
sentMessages = Flux.fromIterable(new ArrayList<>());
}
public String sanitizeChatMessage(String message)
{
String newMessage = message;
if (message.contains("@"))
{
// \u200B is Zero Width Space, invisible on Discord
newMessage = message.replace("@", "@\u200B");
}
if (message.toLowerCase().contains("discord.gg")) // discord.gg/invite works as an invite
{
return "";
}
for (String subdomain : DISCORD_SUBDOMAINS)
{
if (message.toLowerCase().contains(subdomain + "/invite"))
{
return "";
}
}
if (message.contains("§"))
{
newMessage = message.replace("§", "");
}
return deformat(newMessage);
}
public void messageChatChannel(String message, boolean system)
{
String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString();
String sanitizedMessage = (system) ? message : sanitizeChatMessage(message);
if (sanitizedMessage.isBlank()) return;
if (!chat_channel_id.isEmpty())
{
MessageCreateSpec spec = MessageCreateSpec.builder()
.content(sanitizedMessage)
.build();
Mono<Message> sentMessage = tfd4J
.getBot()
.getClient()
.getChannelById(SnowflakeEntry.chatChannelID)
.ofType(TextChannel.class)
.flatMap(c -> c.createMessage(spec));
insert(sentMessage);
}
}
public void messageAdminChatChannel(String message)
{
String chat_channel_id = ConfigEntry.DISCORD_ADMINCHAT_CHANNEL_ID.getString();
String sanitizedMessage = sanitizeChatMessage(message);
if (sanitizedMessage.isBlank()) return;
if (!chat_channel_id.isEmpty())
{
MessageCreateSpec spec = MessageCreateSpec.builder()
.content(sanitizedMessage)
.build();
Mono<Message> sentMessage = tfd4J
.getBot()
.getClient()
.getChannelById(SnowflakeEntry.adminChatChannelID)
.ofType(TextChannel.class)
.flatMap(c -> c.createMessage(spec));
insert(sentMessage);
}
}
public boolean sendReportOffline(Player reporter, OfflinePlayer reported, String reason)
{
if (!tfd4J.getBot().shouldISendReport())
{
return false;
}
final Guild server = tfd4J.getBot().getGuildById().block();
if (server == null) return false;
final TextChannel channel = server.getChannelById(SnowflakeEntry.reportChannelID)
.ofType(TextChannel.class)
.blockOptional()
.orElseThrow();
final EmbedCreateSpec.Builder builder = EmbedCreateSpec.builder()
.title("Report for " + reported.getName() + " (offline)")
.description(reason)
.footer("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png")
.timestamp(Instant.from(ZonedDateTime.now()));
if (tfd4J.getBot().getTFM().getCommons().esb.isEnabled())
{
com.earth2me.essentials.User user = tfd4J.getBot().getTFM().getCommons().esb.getEssentialsUser(reported.getName());
String location = "World: " + Objects.requireNonNull(user.getLastLocation().getWorld()).getName() + ", X: " + user.getLastLocation().getBlockX() + ", Y: " + user.getLastLocation().getBlockY() + ", Z: " + user.getLastLocation().getBlockZ();
builder.addField("Location", location, true);
builder.addField("God Mode", WordUtils.capitalizeFully(String.valueOf(user.isGodModeEnabled())), true);
if (user.getNickname() != null)
{
builder.addField("Nickname", user.getNickname(), true);
}
}
EmbedCreateSpec embed = builder.build();
Message message = channel.createMessage(embed).block();
if (message != null && !ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty())
{
message.addReaction(ReactionEmoji.unicode("\uD83D\uDCCB")).subscribe();
}
return true;
}
public boolean sendReport(Player reporter, Player reported, String reason)
{
if (!tfd4J.getBot().shouldISendReport())
{
return false;
}
final Guild server = tfd4J.getBot()
.getClient()
.getGuildById(SnowflakeEntry.serverID)
.block();
if (server == null)
{
FLog.severe("The guild ID specified in the config is invalid.");
return false;
}
final TextChannel channel = server.getChannelById(SnowflakeEntry.reportChannelID)
.ofType(TextChannel.class)
.blockOptional()
.orElseThrow();
String location = "World: " + Objects.requireNonNull(reported.getLocation().getWorld()).getName() + ", X: " + reported.getLocation().getBlockX() + ", Y: " + reported.getLocation().getBlockY() + ", Z: " + reported.getLocation().getBlockZ();
final EmbedCreateSpec spec = EmbedCreateSpec.builder()
.title("Report for " + reported.getName())
.description(reason)
.footer("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png")
.timestamp(Instant.from(ZonedDateTime.now()))
.addField("Location", location, true)
.addField("Game Mode", WordUtils.capitalizeFully(reported.getGameMode().name()), true)
.build();
Message message = channel.createMessage(spec).block();
if (!ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty() && message != null)
{
ReactionEmoji emoji = ReactionEmoji.unicode("\uD83D\uDCCB");
message.addReaction(emoji);
}
return true;
}
public String deformat(String input)
// Leaving this here so I don't need to do more work than necessary.
public static String deformat(String input)
{
return input.replaceAll("([_\\\\`*>|])", "\\\\$1");
}
public Flux<Message> getMessagesSent()
{
return sentMessages;
}
public void insert(Mono<Message> messageMono)
{
sentMessages.concatWith(messageMono);
}
}