diff --git a/src/main/java/org/maxgamer/maxbans/MaxBansPlus.java b/src/main/java/org/maxgamer/maxbans/MaxBansPlus.java index 180fd07..d0254c7 100644 --- a/src/main/java/org/maxgamer/maxbans/MaxBansPlus.java +++ b/src/main/java/org/maxgamer/maxbans/MaxBansPlus.java @@ -15,14 +15,17 @@ import org.maxgamer.maxbans.context.PluginContext; import org.maxgamer.maxbans.context.component.CommandExecutorComponent; import org.maxgamer.maxbans.exception.ConfigException; -import org.maxgamer.maxbans.exception.SchemaBrokenException; import org.maxgamer.maxbans.exception.RejectedException; +import org.maxgamer.maxbans.exception.SchemaBrokenException; import org.maxgamer.maxbans.locale.Locale; import org.maxgamer.maxbans.transaction.TransactionLayer; import org.maxgamer.maxbans.util.FlywayUtil; import org.maxgamer.maxbans.util.SentryLogger; -import java.io.*; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; import java.nio.channels.OverlappingFileLockException; import java.util.logging.Level; import java.util.logging.Logger; @@ -31,7 +34,7 @@ * @author Dirk Jamieson */ public class MaxBansPlus extends JavaPlugin { - private Locale locale = new Locale(); + private Locale locale; private PluginContext context; private File messagesFile; private Logger sentryLogger; @@ -63,8 +66,12 @@ public void reloadConfig() { getPluginLoader().disablePlugin(this); return; } + + context.components().locale().load(getMessageConfiguration()); } + } + private YamlConfiguration getMessageConfiguration() { YamlConfiguration localeConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(getResource("messages.yml"))); try { localeConfig.load(new FileReader(messagesFile)); @@ -74,7 +81,7 @@ public void reloadConfig() { throw new IllegalStateException("Bad YML configuration file: " + messagesFile, e); } - locale.load(localeConfig); + return localeConfig; } /** @@ -105,7 +112,8 @@ public void onEnable() { sentryLogger = new SentryLogger(this, Event.Level.WARNING, client); } - context = new PluginContext(this, config, locale, getServer(), getDataFolder(), getErrorLogger(), getServer().getPluginManager()); + context = new PluginContext(this, config, getServer(), getDataFolder(), getMessageConfiguration(), getErrorLogger(), getServer().getPluginManager()); + locale = context.components().locale(); try { // Update our database if necessary @@ -173,10 +181,6 @@ public PluginContext getContext() { return context; } - public Locale getLocale() { - return locale; - } - public Logger getErrorLogger() { if(sentryLogger == null) { // Just use the regular plugin logger diff --git a/src/main/java/org/maxgamer/maxbans/command/BanCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/BanCommandExecutor.java index 4a16bae..49595e2 100644 --- a/src/main/java/org/maxgamer/maxbans/command/BanCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/BanCommandExecutor.java @@ -38,13 +38,13 @@ public void restrict(CommandSender source, User user, Duration duration, String userService.ban(banner, user, reason, duration); MessageBuilder message = locale.get() - .with("name", user.getName()) + .withUserOrConsole("name", user) .with("reason", reason) - .with("source", banner == null ? "Console" : banner.getName()) + .withUserOrConsole("source", banner) .with("duration", TemporalDuration.of(duration)); Player player = locatorService.player(user); - if(player != null) player.kickPlayer(message.get("ban.kick")); + if(player != null) player.kickPlayer(message.get("ban.kick").toString()); broadcastService.broadcast(message.get("ban.broadcast"), silent, source, player); diff --git a/src/main/java/org/maxgamer/maxbans/command/HistoryCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/HistoryCommandExecutor.java index d0913dc..7873b5b 100644 --- a/src/main/java/org/maxgamer/maxbans/command/HistoryCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/HistoryCommandExecutor.java @@ -5,6 +5,7 @@ import org.bukkit.entity.Player; import org.maxgamer.maxbans.exception.MessageException; import org.maxgamer.maxbans.exception.RejectedException; +import org.maxgamer.maxbans.locale.Message; import org.maxgamer.maxbans.orm.User; import org.maxgamer.maxbans.service.HistoryService; import org.maxgamer.maxbans.service.UserService; @@ -35,7 +36,7 @@ public HistoryCommandExecutor() { public void perform(CommandSender sender, Command command, String cmd, String[] userArgs) throws MessageException { LinkedList args = new LinkedList<>(Arrays.asList(userArgs)); - List messages; + List messages; int page = 0; if (!args.isEmpty()) { @@ -73,8 +74,8 @@ public void perform(CommandSender sender, Command command, String cmd, String[] messages = historyService.getHistory(page); } - for (String message : messages) { - sender.sendMessage(message); + for (Message message : messages) { + message.send(sender); } sender.sendMessage("--- Page " + (page + 1) + " ---"); diff --git a/src/main/java/org/maxgamer/maxbans/command/IPBanCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/IPBanCommandExecutor.java index c52e4a0..1de08c6 100644 --- a/src/main/java/org/maxgamer/maxbans/command/IPBanCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/IPBanCommandExecutor.java @@ -41,16 +41,16 @@ public void restrict(CommandSender source, Address address, User user, Duration addressService.ban(banner, address, reason, duration); MessageBuilder message = locale.get() - .with("name", user == null ? null : user.getName()) + .with("name", user) .with("address", address.getHost()) .with("reason", reason) - .with("source", banner == null ? "Console" : banner.getName()) + .withUserOrConsole("source", banner) .with("duration", TemporalDuration.of(duration)); broadcastService.broadcast(message.get("ipban.broadcast"), silent, source); for(Player player : locatorService.players(address)) { - player.kickPlayer(message.get("ipban.kick")); + player.kickPlayer(message.get("ipban.kick").toString()); } // Shouldn't be necessary, if everything else is working, to kick the player by retrieving them by the user object here. diff --git a/src/main/java/org/maxgamer/maxbans/command/IPMuteCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/IPMuteCommandExecutor.java index 51fcd57..95838de 100644 --- a/src/main/java/org/maxgamer/maxbans/command/IPMuteCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/IPMuteCommandExecutor.java @@ -41,10 +41,10 @@ public void restrict(CommandSender source, Address address, User user, Duration addressService.mute(muter, address, reason, duration); MessageBuilder message = locale.get() - .with("name", user == null ? null : user.getName()) + .with("name", user) .with("address", address.getHost()) .with("reason", reason) - .with("source", muter == null ? "Console" : muter.getName()) + .withUserOrConsole("source", muter) .with("duration", TemporalDuration.of(duration)); broadcastService.broadcast(message.get("mute.broadcast"), silent, source, locatorService.player(user)); diff --git a/src/main/java/org/maxgamer/maxbans/command/KickCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/KickCommandExecutor.java index 8c38a67..aab83e3 100644 --- a/src/main/java/org/maxgamer/maxbans/command/KickCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/KickCommandExecutor.java @@ -66,7 +66,7 @@ public void perform(CommandSender sender, Command command, String s, String[] us .with("name", player.getName()) .with("reason", reason); - player.kickPlayer(properties.get("kick.message")); + player.kickPlayer(properties.get("kick.message").toString()); broadcastService.broadcast(properties.get("kick.broadcast"), silent, sender); metricService.increment(MetricService.KICKS); diff --git a/src/main/java/org/maxgamer/maxbans/command/LookupCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/LookupCommandExecutor.java index e80b2b0..a47529e 100644 --- a/src/main/java/org/maxgamer/maxbans/command/LookupCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/LookupCommandExecutor.java @@ -3,6 +3,7 @@ import org.bukkit.command.CommandSender; import org.maxgamer.maxbans.exception.PermissionException; import org.maxgamer.maxbans.exception.RejectedException; +import org.maxgamer.maxbans.locale.Message; import org.maxgamer.maxbans.orm.Address; import org.maxgamer.maxbans.orm.User; import org.maxgamer.maxbans.service.UserService; @@ -25,21 +26,21 @@ public LookupCommandExecutor() { @Override public void restrict(CommandSender source, Address address, User user, Duration duration, String reason, boolean silent) throws RejectedException, PermissionException { if(user != null) { - String message = userService + Message message = userService .report(user, locale) .get("iplookup.user"); - source.sendMessage(message); + message.send(source); } // Newline to separate the reports source.sendMessage("-----------------------------------"); // Address can't be null - String message = addressService + Message message = addressService .report(address, locale) .get("iplookup.ip"); - source.sendMessage(message); + message.send(source); } } diff --git a/src/main/java/org/maxgamer/maxbans/command/MuteCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/MuteCommandExecutor.java index 5f2445d..6c2ab83 100644 --- a/src/main/java/org/maxgamer/maxbans/command/MuteCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/MuteCommandExecutor.java @@ -39,9 +39,9 @@ public void restrict(CommandSender source, User user, Duration duration, String userService.mute(banner, user, reason, duration); MessageBuilder message = locale.get() - .with("name", user.getName()) + .with("name", user) .with("reason", reason) - .with("source", banner == null ? "Console" : banner.getName()) + .withUserOrConsole("source", banner) .with("duration", TemporalDuration.of(duration)); broadcastService.broadcast(message.get("mute.broadcast"), silent, source, locatorService.player(user)); diff --git a/src/main/java/org/maxgamer/maxbans/command/UnbanCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/UnbanCommandExecutor.java index 4cf1355..704c7c4 100644 --- a/src/main/java/org/maxgamer/maxbans/command/UnbanCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/UnbanCommandExecutor.java @@ -38,12 +38,12 @@ public void restrict(CommandSender sender, Address address, User user, Duration User source = (sender instanceof Player ? userService.getOrCreate((Player) sender) : null); MessageBuilder message = locale.get() - .with("source", source == null ? "Console" : source.getName()); + .withUserOrConsole("source", source); boolean any = false; if(user != null && userService.getBan(user) != null) { userService.unban(source, user); - message.with("name", user.getName()); + message.with("name", user); broadcastService.broadcast(message.get("ban.unban"), silent, sender); any = true; } diff --git a/src/main/java/org/maxgamer/maxbans/command/UnmuteCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/UnmuteCommandExecutor.java index 893c4f3..d98846f 100644 --- a/src/main/java/org/maxgamer/maxbans/command/UnmuteCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/UnmuteCommandExecutor.java @@ -42,12 +42,12 @@ public void restrict(CommandSender sender, Address address, User user, Duration User source = (sender instanceof Player ? userService.getOrCreate((Player) sender) : null); MessageBuilder message = locale.get() - .with("source", source == null ? "Console" : source.getName()); + .withUserOrConsole("source", source); boolean any = false; if(user != null && userService.getMute(user) != null) { userService.unmute(source, user); - message.with("name", user.getName()); + message.with("name", user); any = true; } diff --git a/src/main/java/org/maxgamer/maxbans/command/UserRestrictionCommandExecutor.java b/src/main/java/org/maxgamer/maxbans/command/UserRestrictionCommandExecutor.java index b289b87..83267f2 100644 --- a/src/main/java/org/maxgamer/maxbans/command/UserRestrictionCommandExecutor.java +++ b/src/main/java/org/maxgamer/maxbans/command/UserRestrictionCommandExecutor.java @@ -45,7 +45,11 @@ public final void perform(CommandSender sender, Command command, String s, Strin } Duration duration = RestrictionUtil.getDuration(args); - String reason = String.join(" ", args); + + String reason = null; + if (args.size() > 0) { + reason = String.join(" ", args); + } restrict(sender, user, duration, reason, silent); } diff --git a/src/main/java/org/maxgamer/maxbans/config/PluginConfig.java b/src/main/java/org/maxgamer/maxbans/config/PluginConfig.java index fbc369b..252086d 100644 --- a/src/main/java/org/maxgamer/maxbans/config/PluginConfig.java +++ b/src/main/java/org/maxgamer/maxbans/config/PluginConfig.java @@ -1,5 +1,6 @@ package org.maxgamer.maxbans.config; +import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.configuration.Configuration; import org.maxgamer.maxbans.exception.ConfigException; @@ -18,6 +19,7 @@ public class PluginConfig { private Set chatCommands; private boolean errorTracking; private boolean metrics; + private boolean tooltips; public PluginConfig() { setJdbcConfig(new JdbcConfig()); @@ -36,6 +38,15 @@ public void load(Configuration configuration, Server server) throws ConfigExcept this.setChatCommands(configuration.getStringList("chat-commands")); this.setErrorTracking(configuration.getBoolean("error-tracking", false)); this.setMetrics(configuration.getBoolean("metrics", true)); + + boolean wantsTooltips = configuration.getBoolean("tooltips", true); + if (wantsTooltips && !server.getVersion().contains("Spigot")) { + server.getLogger().warning("MaxBans has tooltips: true in it's configuration, but that requires Spigot for Minecraft 1.8.3 or higher"); + + wantsTooltips = false; + } + + this.setTooltips(wantsTooltips); } public JdbcConfig getJdbcConfig() { @@ -60,6 +71,15 @@ public boolean isOffline() { return isOffline; } + public boolean isTooltips() { + return tooltips; + } + + public PluginConfig setTooltips(boolean tooltips) { + this.tooltips = tooltips; + return this; + } + public PluginConfig setOffline(boolean offline) { isOffline = offline; return this; diff --git a/src/main/java/org/maxgamer/maxbans/context/PluginContext.java b/src/main/java/org/maxgamer/maxbans/context/PluginContext.java index 5fbb6e9..d8a1d6e 100644 --- a/src/main/java/org/maxgamer/maxbans/context/PluginContext.java +++ b/src/main/java/org/maxgamer/maxbans/context/PluginContext.java @@ -1,6 +1,7 @@ package org.maxgamer.maxbans.context; import org.bukkit.Server; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.PluginManager; @@ -13,7 +14,6 @@ import org.maxgamer.maxbans.context.component.DaggerPluginComponent; import org.maxgamer.maxbans.context.component.PluginComponent; import org.maxgamer.maxbans.context.module.PluginModule; -import org.maxgamer.maxbans.locale.Locale; import java.io.File; import java.util.logging.Logger; @@ -27,15 +27,14 @@ public class PluginContext { private File dataFolder; private PluginComponent modules; private PluginModule pluginModule; - - public PluginContext(MaxBansPlus plugin, PluginConfig config, Locale locale, Server server, File dataFolder, Logger logger, PluginManager pluginManager) { + + public PluginContext(MaxBansPlus plugin, PluginConfig config, Server server, File dataFolder, ConfigurationSection messageConfiguration, Logger logger, PluginManager pluginManager) { this.config = config; this.server = server; this.dataFolder = dataFolder; FileConfiguration lockdownCfg = YamlConfiguration.loadConfiguration(new File(dataFolder, "lockdown.yml")); - - pluginModule = new PluginModule(plugin, server, config, lockdownCfg, locale, logger, pluginManager); + pluginModule = new PluginModule(plugin, server, config, lockdownCfg, messageConfiguration, logger, pluginManager); modules = DaggerPluginComponent .builder() diff --git a/src/main/java/org/maxgamer/maxbans/context/component/PluginComponent.java b/src/main/java/org/maxgamer/maxbans/context/component/PluginComponent.java index 2e81467..9cea423 100644 --- a/src/main/java/org/maxgamer/maxbans/context/component/PluginComponent.java +++ b/src/main/java/org/maxgamer/maxbans/context/component/PluginComponent.java @@ -7,6 +7,7 @@ import org.maxgamer.maxbans.context.module.JdbcModule; import org.maxgamer.maxbans.context.module.PluginModule; import org.maxgamer.maxbans.context.module.ServiceModule; +import org.maxgamer.maxbans.locale.Locale; import org.maxgamer.maxbans.transaction.Transactor; import javax.inject.Singleton; @@ -31,4 +32,5 @@ public interface PluginComponent { Logger logger(); SessionFactory sessionFactory(); PluginManager pluginManager(); + Locale locale(); } diff --git a/src/main/java/org/maxgamer/maxbans/context/module/PluginModule.java b/src/main/java/org/maxgamer/maxbans/context/module/PluginModule.java index d06b1a1..822840d 100644 --- a/src/main/java/org/maxgamer/maxbans/context/module/PluginModule.java +++ b/src/main/java/org/maxgamer/maxbans/context/module/PluginModule.java @@ -3,11 +3,13 @@ import dagger.Module; import dagger.Provides; import org.bukkit.Server; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.plugin.PluginManager; import org.maxgamer.maxbans.MaxBansPlus; import org.maxgamer.maxbans.config.PluginConfig; import org.maxgamer.maxbans.locale.Locale; +import org.maxgamer.maxbans.service.GeoIPService; import javax.inject.Singleton; import java.util.logging.Logger; @@ -22,16 +24,16 @@ public class PluginModule { private PluginConfig config; private Server server; private FileConfiguration configuration; - private Locale locale; private PluginManager pluginManager; + private ConfigurationSection messageConfiguration; private boolean sessionInitialised = false; - public PluginModule(MaxBansPlus plugin, Server server, PluginConfig config, FileConfiguration configuration, Locale locale, Logger logger, PluginManager pluginManager) { + public PluginModule(MaxBansPlus plugin, Server server, PluginConfig config, FileConfiguration configuration, ConfigurationSection messageConfiguration, Logger logger, PluginManager pluginManager) { this.plugin = plugin; this.config = config; this.server = server; this.configuration = configuration; - this.locale = locale; + this.messageConfiguration = messageConfiguration; this.logger = logger; this.pluginManager = pluginManager; } @@ -74,8 +76,8 @@ public FileConfiguration getConfiguration() { @Provides @Singleton - public Locale getLocale() { - return locale; + public Locale getLocale(GeoIPService geoIPService, PluginConfig config) { + return new Locale(geoIPService, config, messageConfiguration); } @Provides diff --git a/src/main/java/org/maxgamer/maxbans/exception/MessageException.java b/src/main/java/org/maxgamer/maxbans/exception/MessageException.java index 0d9c488..8aba511 100644 --- a/src/main/java/org/maxgamer/maxbans/exception/MessageException.java +++ b/src/main/java/org/maxgamer/maxbans/exception/MessageException.java @@ -32,7 +32,7 @@ public String getMessage(Locale locale) { // The message has a translation MessageBuilder builder = toBuilder(locale); - return builder.get(getMessage()); + return builder.get(getMessage()).toString(); } else { // This message has no translation. Perhaps it's not defined or perhaps it's a lazy message return super.getMessage(); diff --git a/src/main/java/org/maxgamer/maxbans/locale/BukkitMessage.java b/src/main/java/org/maxgamer/maxbans/locale/BukkitMessage.java new file mode 100644 index 0000000..ee4ea4b --- /dev/null +++ b/src/main/java/org/maxgamer/maxbans/locale/BukkitMessage.java @@ -0,0 +1,94 @@ +package org.maxgamer.maxbans.locale; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.maxgamer.maxbans.util.StringUtil; + +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * TODO: Document this + */ +public class BukkitMessage implements Message { + protected Locale locale; + protected Map substitutions; + protected String templateId; + protected BukkitMessage next; + + public BukkitMessage(Locale locale, Map substitutions, String templateId) { + this.locale = locale; + this.substitutions = new HashMap<>(substitutions); + this.templateId = templateId; + } + + public BukkitMessage append(BukkitMessage suffix) { + this.next = suffix; + + return this; + } + + public BukkitMessage insert(BukkitMessage prefix) { + prefix.next = this; + + return prefix; + } + + protected Object transform(Object value) { + if (value instanceof Instant) { + // Instants get turned into dates + return Date.from((Instant) value); + } + + if (value instanceof Date) { + // Instants and Dates get pretty printed + return locale.prettyTime.format(((Date) value)); + } + + if (value instanceof Duration) { + // Little bit of a hack because we have a Java 8 Duration object + // instead of a PrettyTime Duration object. So we add the duration + // to the current time, and then get pretty time to write the difference + // between now and then, which hopefully looks like "1 week from now". + Duration d = (Duration) value; + Instant duration = Instant.now().plus(d); + + return locale.prettyTime.format(Date.from(duration)); + } + + return value; + } + + public void send(CommandSender recipient) { + String output = toString(); + recipient.sendMessage(output); + } + + @Override + public String toString() { + String template = locale.getMessages().get(this.templateId); + if (template == null) throw new IllegalArgumentException("No such template: " + this.templateId); + + Map preprocessed = new HashMap<>(substitutions.size()); + for (Map.Entry entry : substitutions.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + value = transform(value); + preprocessed.put(key, value); + } + + // Now we expand the template before parsing in variable substitutions + template = ChatColor.translateAlternateColorCodes('&', template); + + String output = StringUtil.expand(template, preprocessed); + if (next != null) { + output += next.toString(); + } + + return output; + } +} diff --git a/src/main/java/org/maxgamer/maxbans/locale/BukkitMessageBuilder.java b/src/main/java/org/maxgamer/maxbans/locale/BukkitMessageBuilder.java new file mode 100644 index 0000000..1110ed2 --- /dev/null +++ b/src/main/java/org/maxgamer/maxbans/locale/BukkitMessageBuilder.java @@ -0,0 +1,47 @@ +package org.maxgamer.maxbans.locale; + +import org.bukkit.command.CommandSender; +import org.maxgamer.maxbans.orm.User; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author netherfoam + */ +public class BukkitMessageBuilder implements MessageBuilder { + protected Locale locale; + protected Map substitutions = new HashMap<>(6); + + public BukkitMessageBuilder(Locale locale) { + this.locale = locale; + } + + public MessageBuilder with(String key, Object value) { + substitutions.put(key, value); + + return this; + } + + public MessageBuilder withUserOrConsole(String key, User user) { + return with(key, user == null ? "Console" : user.getName()); + } + + public MessageBuilder with(String key, User user) { + if (user == null) return this; + + return with(key, user.getName()); + } + + public Object preview(String key) { + return substitutions.get(key); + } + + public Message get(String templateId) { + return new BukkitMessage(locale, substitutions, templateId); + } + + public void send(String templateId, CommandSender recipient) { + get(templateId).send(recipient); + } +} diff --git a/src/main/java/org/maxgamer/maxbans/locale/Locale.java b/src/main/java/org/maxgamer/maxbans/locale/Locale.java index 764ea76..c98a4d9 100644 --- a/src/main/java/org/maxgamer/maxbans/locale/Locale.java +++ b/src/main/java/org/maxgamer/maxbans/locale/Locale.java @@ -1,9 +1,12 @@ package org.maxgamer.maxbans.locale; import org.bukkit.configuration.ConfigurationSection; +import org.maxgamer.maxbans.config.PluginConfig; +import org.maxgamer.maxbans.service.GeoIPService; import org.ocpsoft.prettytime.PrettyTime; import org.ocpsoft.prettytime.units.JustNow; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -11,35 +14,39 @@ * @author Dirk Jamieson */ public class Locale { - protected HashMap messages; + private HashMap messages; protected PrettyTime prettyTime = new PrettyTime(java.util.Locale.ENGLISH); + private GeoIPService geoIPService; + private PluginConfig pluginConfig; - public Locale(){ - messages = new HashMap<>(); - prettyTime.removeUnit(JustNow.class); + public Locale(GeoIPService geoIPService){ + this.messages = new HashMap<>(); + this.prettyTime.removeUnit(JustNow.class); + this.geoIPService = geoIPService; } - public Locale(Map messages) { - this(); + public Locale(GeoIPService geoIPService, Map messages) { + this(geoIPService); this.messages = new HashMap<>(messages); } - - public Locale(ConfigurationSection config) { - this(); - - load(config); + + public Locale(GeoIPService geoIPService, PluginConfig config, ConfigurationSection messageConfig) { + this(geoIPService); + this.pluginConfig = config; + + load(messageConfig); } - public void load(ConfigurationSection config) { + public void load(ConfigurationSection messageConfig) { messages = new HashMap<>(); - for(String key : config.getKeys(true)) { - String value = config.getString(key); + for(String key : messageConfig.getKeys(true)) { + String value = messageConfig.getString(key); messages.put(key, value); } - String locale = config.getString("locale"); + String locale = messageConfig.getString("locale"); if(locale != null) { setLocale(locale); } @@ -54,14 +61,22 @@ public String getLocale() { } public MessageBuilder get() { - return new MessageBuilder(this); + if (pluginConfig != null && pluginConfig.isTooltips()) { + return new TooltipMessageBuilder(this, geoIPService); + } + + return new BukkitMessageBuilder(this); + } + + public Map getMessages() { + return Collections.unmodifiableMap(messages); } /** - * Puts the given template under the given key + * Puts the given template message under the given key * - * @param key the key - * @param template the template message + * @param key the key eg "ban.kick" + * @param template the template message eg "You have been banned for {{duration}}" */ public void put(String key, String template) { messages.put(key, template); diff --git a/src/main/java/org/maxgamer/maxbans/locale/Message.java b/src/main/java/org/maxgamer/maxbans/locale/Message.java new file mode 100644 index 0000000..be192c7 --- /dev/null +++ b/src/main/java/org/maxgamer/maxbans/locale/Message.java @@ -0,0 +1,12 @@ +package org.maxgamer.maxbans.locale; + +import org.bukkit.command.CommandSender; + +/** + * TODO: Document this + */ +public interface Message { + T append(T suffix); + T insert(T prefix); + void send(CommandSender recipient); +} diff --git a/src/main/java/org/maxgamer/maxbans/locale/MessageBuilder.java b/src/main/java/org/maxgamer/maxbans/locale/MessageBuilder.java index abbfb17..a1dc24b 100644 --- a/src/main/java/org/maxgamer/maxbans/locale/MessageBuilder.java +++ b/src/main/java/org/maxgamer/maxbans/locale/MessageBuilder.java @@ -1,70 +1,19 @@ package org.maxgamer.maxbans.locale; -import org.bukkit.ChatColor; -import org.maxgamer.maxbans.util.StringUtil; +import org.bukkit.command.CommandSender; +import org.maxgamer.maxbans.orm.User; -import java.time.Duration; -import java.util.Date; -import java.time.Instant; import java.util.HashMap; import java.util.Map; /** * @author netherfoam */ -public class MessageBuilder { - private Locale locale; - private Map substitutions = new HashMap<>(6); - - public MessageBuilder(Locale locale) { - this.locale = locale; - } - - public MessageBuilder with(String key, Object value) { - substitutions.put(key, value); - - return this; - } - - public Object preview(String key) { - return substitutions.get(key); - } - - public String get(String name) { - String template = locale.messages.get(name); - if (template == null) throw new IllegalArgumentException("No such template: " + name); - - Map preprocessed = new HashMap<>(substitutions.size()); - for (Map.Entry entry : substitutions.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - - if (value instanceof Instant) { - // Instants get turned into dates - value = Date.from((Instant) value); - } - - if (value instanceof Date) { - // Instants and Dates get pretty printed - value = locale.prettyTime.format(((Date) value)); - } - - if (value instanceof Duration) { - // Little bit of a hack because we have a Java 8 Duration object - // instead of a PrettyTime Duration object. So we add the duration - // to the current time, and then get pretty time to write the difference - // between now and then, which hopefully looks like "1 week from now". - Duration d = (Duration) value; - Instant duration = Instant.now().plus(d); - value = locale.prettyTime.format(Date.from(duration)); - } - - preprocessed.put(key, value); - } - - // Now we expand the template before parsing in variable substitutions - template = ChatColor.translateAlternateColorCodes('&', template); - - return StringUtil.expand(template, preprocessed); - } +public interface MessageBuilder { + MessageBuilder with(String key, Object value); + MessageBuilder withUserOrConsole(String key, User user); + MessageBuilder with(String key, User user); + Object preview(String key); + Message get(String templateId); + void send(String templateId, CommandSender recipient); } diff --git a/src/main/java/org/maxgamer/maxbans/locale/TooltipMessage.java b/src/main/java/org/maxgamer/maxbans/locale/TooltipMessage.java new file mode 100644 index 0000000..3b931bc --- /dev/null +++ b/src/main/java/org/maxgamer/maxbans/locale/TooltipMessage.java @@ -0,0 +1,293 @@ +package org.maxgamer.maxbans.locale; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.command.CommandSender; +import org.maxgamer.maxbans.util.StringUtil; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * TODO: Document this + */ +public class TooltipMessage extends BukkitMessage { + private static final Pattern URL_PATTERN = Pattern.compile("^(?:(https?)://)?([-\\w_\\.]{2,}\\.[a-z]{2,4})(/\\S*)?$"); + + /** + * Correct implementation of {@link TextComponent#fromLegacyText(String, ChatColor)} + */ + public static BaseComponent[] fromLegacyText(String message, ChatColor defaultColor) { + ArrayList components = new ArrayList<>(); + StringBuilder builder = new StringBuilder(); + TextComponent component = new TextComponent(); + Matcher matcher = URL_PATTERN.matcher(message); + + for(int i = 0; i < message.length(); ++i) { + char c = message.charAt(i); + TextComponent old; + if (c == 167) { + ++i; + if (i >= message.length()) { + break; + } + + c = message.charAt(i); + if (c >= 'A' && c <= 'Z') { + c = (char)(c + 32); + } + + ChatColor format = ChatColor.getByChar(c); + if (format != null) { + if (builder.length() > 0) { + old = component; + component = new TextComponent(component); + old.setText(builder.toString()); + builder = new StringBuilder(); + components.add(old); + } + + switch(format) { + case BOLD: + component.setBold(true); + break; + case ITALIC: + component.setItalic(true); + break; + case UNDERLINE: + component.setUnderlined(true); + break; + case STRIKETHROUGH: + component.setStrikethrough(true); + break; + case MAGIC: + component.setObfuscated(true); + break; + case RESET: + format = defaultColor; + default: + component = new TextComponent(); + component.setColor(format); + } + } + } else { + int pos = message.indexOf(' ', i); + if (pos == -1) { + pos = message.length(); + } + + if (matcher.region(i, pos).find()) { + if (builder.length() > 0) { + old = component; + component = new TextComponent(component); + old.setText(builder.toString()); + builder = new StringBuilder(); + components.add(old); + } + + old = component; + component = new TextComponent(component); + String urlString = message.substring(i, pos); + component.setText(urlString); + component.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, urlString.startsWith("http") ? urlString : "http://" + urlString)); + components.add(component); + i += pos - i - 1; + component = old; + } else { + builder.append(c); + } + } + } + + if (builder.length() > 0 || component.getColorRaw() != defaultColor) { + component.setText(builder.toString()); + components.add(component); + } + + if (components.isEmpty()) { + components.add(new TextComponent("")); + } + + return components.toArray(new BaseComponent[components.size()]); + } + + public static BaseComponent[] expand(String template, Map substitutions) { + List components = new ArrayList<>(); + + Matcher matcher = Pattern.compile("\\{\\{[^\\}\\}]*\\}\\}").matcher(template); + + // This is a dummy value for copying formatting from the previous literal + BaseComponent previousLiteral = new TextComponent(); + + int last = 0; + while(matcher.find()) { + int start = matcher.start(); + int end = matcher.end(); + + String group = matcher.group(); + BaseComponent[] literalText = fromLegacyText(template.substring(last, start), ChatColor.WHITE); + + if (literalText.length > 0) { + copyPrevious(previousLiteral, literalText); + previousLiteral = literalText[literalText.length - 1]; + } + + components.addAll(Arrays.asList(literalText)); + last = end; + + group = group.substring(2, group.length() - 2); + String[] options = split(group, '|'); + BaseComponent[] value = expand(options, substitutions); + + BaseComponent lastComponent = previousLiteral; + for (BaseComponent v : value) { + v.copyFormatting(lastComponent, ComponentBuilder.FormatRetention.FORMATTING, false); + lastComponent = v; + } + + components.addAll(Arrays.asList(value)); + } + + String lastLiteral = template.substring(last); + if (!lastLiteral.isEmpty()) { + BaseComponent[] literalText = fromLegacyText(lastLiteral, ChatColor.WHITE); + copyPrevious(previousLiteral, literalText); + + components.addAll(Arrays.asList(literalText)); + } + + return components.stream() + .filter(c -> !c.toPlainText().isEmpty()) + .toArray(BaseComponent[]::new); + } + + private static void copyPrevious(BaseComponent previous, BaseComponent[] literalText) { + for (int i = 0; i < literalText.length; i++) { + if (i == 0) { + // First iteration, copy from the last component + if (previous == null) continue; + + literalText[i].copyFormatting(previous, ComponentBuilder.FormatRetention.FORMATTING, false); + continue; + } + + literalText[i].copyFormatting(literalText[i - 1], ComponentBuilder.FormatRetention.FORMATTING, false); + } + } + + public static BaseComponent[] expand(String[] options, Map substitutions) { + for(String option : options) { + BaseComponent[] value = substitutions.get(option); + if(value == null) continue; + if (value.length <= 0) continue; + if (Arrays.stream(value).allMatch(c -> c.toLegacyText().isEmpty())) continue; + + return value; + } + + // We just use the name instead + return fromLegacyText(options[options.length - 1], ChatColor.WHITE); + } + + private static String[] split(String text, char delimiter) { + // Can't use string.split("\\|") because that splits "hello||" into just "hello" and not {"hello", "", ""} as it should + + LinkedList components = new LinkedList<>(); + + int start = 0; + int end; + + while((end = text.indexOf(delimiter, start)) >= 0) { + String s = text.substring(start, end); + components.add(s); + + // +1 so we skip the | next. + start = end + 1; + } + + components.add(text.substring(start, text.length())); + + return components.toArray(new String[components.size()]); + } + + public TooltipMessage(Locale locale, Map substitutions, String templateId) { + super(locale, substitutions, templateId); + } + + protected BaseComponent[] transformValueToComponents(CommandSender recipient, Object value) { + if (value instanceof BaseComponent) { + return new BaseComponent[]{(BaseComponent) value}; + } else if (value instanceof BaseComponent[]) { + return (BaseComponent[]) value; + } + + Object fallback = super.transform(value); + if (fallback == null) return null; + + String legacyText = String.valueOf(fallback); + + return fromLegacyText(legacyText, ChatColor.WHITE); + } + + @Override + public void send(CommandSender recipient) { + String template = locale.getMessages().get(this.templateId); + if (template == null) throw new IllegalArgumentException("No such template: " + this.templateId); + + Map variableComponents = new HashMap<>(substitutions.size()); + for (Map.Entry entry : substitutions.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + BaseComponent[] components = transformValueToComponents(recipient, value); + + variableComponents.put(key, components); + } + + // Now we expand the template before parsing in variable substitutions + template = ChatColor.translateAlternateColorCodes('&', template); + + BaseComponent[] components = expand(template, variableComponents); + + recipient.spigot().sendMessage(components); + } + + @Override + public String toString() { + String template = locale.getMessages().get(this.templateId); + if (template == null) throw new IllegalArgumentException("No such template: " + this.templateId); + + Map preprocessed = new HashMap<>(substitutions.size()); + for (Map.Entry entry : substitutions.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + + if (value instanceof BaseComponent) { + value = ((BaseComponent) value).toLegacyText(); + } else if (value instanceof BaseComponent[]) { + value = Arrays.stream(((BaseComponent[]) value)) + .map(component -> component.toLegacyText()) + .collect(Collectors.joining()); + } else { + value = super.transform(value); + } + + preprocessed.put(key, value); + } + + // Now we expand the template before parsing in variable substitutions + template = ChatColor.translateAlternateColorCodes('&', template); + + String output = StringUtil.expand(template, preprocessed); + if (next != null) { + output += next.toString(); + } + + return output; + } +} diff --git a/src/main/java/org/maxgamer/maxbans/locale/TooltipMessageBuilder.java b/src/main/java/org/maxgamer/maxbans/locale/TooltipMessageBuilder.java new file mode 100644 index 0000000..dad5c86 --- /dev/null +++ b/src/main/java/org/maxgamer/maxbans/locale/TooltipMessageBuilder.java @@ -0,0 +1,98 @@ +package org.maxgamer.maxbans.locale; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.maxgamer.maxbans.orm.User; +import org.maxgamer.maxbans.orm.UserAddress; +import org.maxgamer.maxbans.service.GeoIPService; +import org.maxgamer.maxbans.util.geoip.GeoCountry; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * TODO: Document this + */ +public class TooltipMessageBuilder extends BukkitMessageBuilder { + private GeoIPService geoIPService; + + public TooltipMessageBuilder(Locale locale, GeoIPService geoIPService) { + super(locale); + this.geoIPService = geoIPService; + } + + @Override + public MessageBuilder withUserOrConsole(String key, User user) { + if (user == null) { + // Standard behaviour for missing users + return super.with(key, "Console"); + } + + return this.with(key, user); + } + + @Override + public MessageBuilder with(String key, User user) { + if (user == null) { + // Standard behaviour for missing users + return super.with(key, (String) null); + } + + BaseComponent component = toComponent(user); + + substitutions.put(key, component); + + return this; + } + + @Override + public Message get(String templateId) { + return new TooltipMessage(locale, substitutions, templateId); + } + + private BaseComponent toComponent(User user) { + TextComponent name = new TextComponent(user.getName()); + name.setColor(ChatColor.LIGHT_PURPLE); + + MessageBuilder hover = this + .with("firstActive", user.getFirstActive()) + .with("lastActive", user.getLastActive()); + + UserAddress lastAddress = user.getLastAddress(); + if (lastAddress != null) { + List alts = new ArrayList<>(); + + // Sort by most recent users first + List mostRecentUsers = new ArrayList<>(lastAddress.getAddress().getUsers()); + mostRecentUsers.sort(Comparator.comparing(UserAddress::getFirstActive)); + + for (UserAddress alt : mostRecentUsers) { + alts.add(alt.getUser().getName()); + } + + String host = lastAddress.getAddress().getHost(); + GeoCountry country = geoIPService.getCountry(host); + + hover.with("users", alts) + .with("ip", host) + .with("users", alts); + + if (country != null) { + hover.with("country", country.getCountryName()) + .with("continent", country.getContinentName()); + } + } + + Message text = hover.get("hover.user"); + + name.setHoverEvent(new HoverEvent( + HoverEvent.Action.SHOW_TEXT, + TooltipMessage.fromLegacyText(text.toString(), ChatColor.WHITE) + )); + + return name; + } +} diff --git a/src/main/java/org/maxgamer/maxbans/service/AddressService.java b/src/main/java/org/maxgamer/maxbans/service/AddressService.java index 593c62e..51e915f 100644 --- a/src/main/java/org/maxgamer/maxbans/service/AddressService.java +++ b/src/main/java/org/maxgamer/maxbans/service/AddressService.java @@ -180,7 +180,7 @@ public void onChat(Address address) throws RejectedException { throw new RejectedException("mute.denied") .with("address", address.getHost()) - .with("banner", mute.getSource() == null ? "Console" : mute.getSource().getName()) + .with("banner", mute.getSource()) .with("reason", mute.getReason()) .with("duration", mute.getExpiresAt()); } @@ -207,8 +207,8 @@ public void onJoin(User user, String ip) throws RejectedException { if (ban != null) { throw new RejectedException("ipban.denied") .with("address", ip) - .with("name", user.getName()) - .with("source", ban.getSource() == null ? "Console" : ban.getSource().getName()) + .with("name", user) + .with("source", ban.getSource()) .with("reason", ban.getReason()) .with("duration", ban.getExpiresAt()); } @@ -258,7 +258,7 @@ public MessageBuilder report(Address address, Locale locale) throws RejectedExce builder.with("ban", reason); // Legacy support < 1.5 builder.with("ban.reason", reason); - builder.with("ban.source", ban.getSource() == null ? "Console" : ban.getSource().getName()); + builder.withUserOrConsole("ban.source", ban.getSource()); builder.with("ban.expires", ban.getExpiresAt()); builder.with("ban.created", ban.getCreated()); } @@ -269,7 +269,7 @@ public MessageBuilder report(Address address, Locale locale) throws RejectedExce if (reason == null || reason.isEmpty()) reason = "No reason"; builder.with("mute", reason); // Legacy support < 1.5 builder.with("mute.reason", reason); - builder.with("mute.source", mute.getSource() == null ? "Console" : mute.getSource().getName()); + builder.withUserOrConsole("mute.source", mute.getSource()); builder.with("mute.expires", mute.getExpiresAt()); builder.with("mute.created", mute.getCreated()); } diff --git a/src/main/java/org/maxgamer/maxbans/service/BroadcastService.java b/src/main/java/org/maxgamer/maxbans/service/BroadcastService.java index dfbe9e8..3b219af 100644 --- a/src/main/java/org/maxgamer/maxbans/service/BroadcastService.java +++ b/src/main/java/org/maxgamer/maxbans/service/BroadcastService.java @@ -2,13 +2,16 @@ import org.bukkit.Server; import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import org.maxgamer.maxbans.locale.Locale; +import org.maxgamer.maxbans.locale.Message; import org.maxgamer.maxbans.util.Permissions; import javax.inject.Inject; import java.time.Duration; import java.time.Instant; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -27,8 +30,32 @@ public BroadcastService(Server server, Locale locale) { this.locale = locale; } - public void moderators(String message) { - server.broadcast(message, MODERATOR_PERMISSION); + private void broadcast(Message message, String permission, CommandSender... required) { + for (Player player : server.getOnlinePlayers()) { + if (!player.hasPermission(permission)) { + continue; + } + + message.send(player); + } + + for(CommandSender involved : required) { + // If the target already has permission, we've already messaged them! + if(involved == null || involved.hasPermission(permission)) continue; + + // Target doesn't have permission so wasn't notified by the broadcast! + message.send(involved); + } + + // Don't forget to send it to the console too, if necessary! + ConsoleCommandSender console = server.getConsoleSender(); + if (Arrays.stream(required).noneMatch(sender -> sender == console)) { + message.send(console); + } + } + + public void moderators(Message message) { + broadcast(message, MODERATOR_PERMISSION); } /** @@ -37,7 +64,7 @@ public void moderators(String message) { * @param silent true if the broadcast should only notify moderators, false if it should notify players * @param required the list of players who must, indisputably, be sent the message. May contain nulls. */ - public void broadcast(String message, boolean silent, CommandSender... required) { + public void broadcast(Message message, boolean silent, CommandSender... required) { String permission; if(silent) { @@ -45,24 +72,17 @@ public void broadcast(String message, boolean silent, CommandSender... required) // Attach our silence prefix & suffix if (locale.has("silent.prefix")) { - message = locale.get().get("silent.prefix") + message; + message = locale.get().get("silent.prefix").append(message); } if (locale.has("silent.suffix")) { - message = message + locale.get().get("silent.suffix"); + message = message.append(locale.get().get("silent.suffix")); } } else { permission = Permissions.SEE_BROADCAST; } - server.broadcast(message, permission); - for(CommandSender involved : required) { - // If the target already has permission, we've already messaged them! - if(involved == null || involved.hasPermission(permission)) continue; - - // Target doesn't have permission so wasn't notified by the broadcast! - involved.sendMessage(message); - } + broadcast(message, permission, required); } /** @@ -77,7 +97,7 @@ public void broadcast(String message, boolean silent, CommandSender... required) * @param timeout the minimum time between notifications * @param message the message to deliver to moderators */ - public void moderators(Object key, Duration timeout, String message) { + public void moderators(Object key, Duration timeout, Message message) { if(key == null) { throw new IllegalArgumentException("Key may not be null"); } diff --git a/src/main/java/org/maxgamer/maxbans/service/HistoryService.java b/src/main/java/org/maxgamer/maxbans/service/HistoryService.java index d13cd39..fd016f6 100644 --- a/src/main/java/org/maxgamer/maxbans/service/HistoryService.java +++ b/src/main/java/org/maxgamer/maxbans/service/HistoryService.java @@ -1,6 +1,7 @@ package org.maxgamer.maxbans.service; import org.maxgamer.maxbans.locale.Locale; +import org.maxgamer.maxbans.locale.Message; import org.maxgamer.maxbans.locale.MessageBuilder; import org.maxgamer.maxbans.orm.*; import org.maxgamer.maxbans.transaction.TransactionLayer; @@ -45,7 +46,7 @@ public HistoryService(Transactor transactor, Locale locale) { * @param source the moderator to view the past actions of * @return the page of actions */ - public List getHistory(int page, User source) { + public List getHistory(int page, User source) { try (TransactionLayer tx = transactor.transact()) { return describe(getBySender(page, source)); } @@ -56,7 +57,7 @@ public List getHistory(int page, User source) { * @param page the page number, zero indexed * @return the page of history */ - public List getHistory(int page) { + public List getHistory(int page) { try (TransactionLayer tx = transactor.transact()) { return describe(getAll(page)); } @@ -98,12 +99,12 @@ private List getAll(int page) { } } - private List describe(List restrictions) { - List messages = new ArrayList<>(restrictions.size()); + private List describe(List restrictions) { + List messages = new ArrayList<>(restrictions.size()); for (Restriction restriction : restrictions) { MessageBuilder builder = contextualise(restriction); - String message = get(builder, restriction); + Message message = get(builder, restriction); messages.add(message); } @@ -120,7 +121,7 @@ private MessageBuilder contextualise(Restriction restriction) { return builder; } - private String get(MessageBuilder builder, Restriction restriction) { + private Message get(MessageBuilder builder, Restriction restriction) { if (restriction instanceof Mute) { return builder.get("history.mute"); } diff --git a/src/main/java/org/maxgamer/maxbans/service/LockdownService.java b/src/main/java/org/maxgamer/maxbans/service/LockdownService.java index 236fe03..1b01572 100644 --- a/src/main/java/org/maxgamer/maxbans/service/LockdownService.java +++ b/src/main/java/org/maxgamer/maxbans/service/LockdownService.java @@ -101,14 +101,14 @@ public MessageBuilder lockdown(User source, String name, String reason, Locale l .with("type", state.toString().toLowerCase()) .with("reason", reason) .with("description", state.description()) - .with("source", source == null ? "Console" : source.getName()); + .withUserOrConsole("source", source); // Kick all players who no longer are allowed (new or all players) if(type == Lockdown.ALL || type == Lockdown.NEW) { for(Player player : server.getOnlinePlayers()) { User user = userService.getOrCreate(player); if(!isAllowed(user, false)) { - player.kickPlayer(message.get("lockdown.message")); + player.kickPlayer(message.get("lockdown.message").toString()); } } } diff --git a/src/main/java/org/maxgamer/maxbans/service/UserService.java b/src/main/java/org/maxgamer/maxbans/service/UserService.java index 791417f..ca3828d 100644 --- a/src/main/java/org/maxgamer/maxbans/service/UserService.java +++ b/src/main/java/org/maxgamer/maxbans/service/UserService.java @@ -95,6 +95,7 @@ public User getOrCreate(Player player) { if(user != null) { if(!player.getName().equals(user.getName())) { + // Our existing name is stored with the wrong case, or the name case was changed user.setName(player.getName()); } return user; @@ -123,9 +124,9 @@ public void onJoin(User user) throws RejectedException { Ban ban = getBan(user); if(ban != null) { throw new RejectedException("ban.denied") - .with("name", user.getName()) + .with("name", user) .with("reason", ban.getReason()) - .with("source", ban.getSource() == null ? "Console" : ban.getSource().getName()) + .with("source", ban.getSource()) .with("duration", ban.getExpiresAt()); } @@ -137,9 +138,9 @@ public void onChat(User user) throws RejectedException { if(mute == null) return; throw new RejectedException("mute.denied") - .with("name", user.getName()) + .with("name", user) .with("reason", mute.getReason()) - .with("source", mute.getSource() == null ? "Console" : mute.getSource().getName()) + .with("source", mute.getSource()) .with("duration", mute.getExpiresAt()); } @@ -206,7 +207,7 @@ public void mute(User source, User user, String reason, Duration duration) throw public void unmute(User source, User user) throws RejectedException, CancelledException { List list = user.getMutes(); if(!RestrictionUtil.isActive(list)) { - throw new RejectedException("mute.error.not-muted").with("name", user.getName()); + throw new RejectedException("mute.error.not-muted").with("name", user); } List revocable = new ArrayList<>(list.size()); @@ -233,7 +234,7 @@ public void unmute(User source, User user) throws RejectedException, CancelledEx public void unban(User source, User user) throws RejectedException, CancelledException { List list = user.getBans(); if(!RestrictionUtil.isActive(list)) { - throw new RejectedException("ban.error.not-banned").with("name", user.getName()); + throw new RejectedException("ban.error.not-banned").with("name", user); } List enforced = new ArrayList<>(list.size()); @@ -265,7 +266,7 @@ public MessageBuilder report(User user, Locale locale) throws RejectedException } MessageBuilder builder = locale.get(); - builder.with("name", user.getName()); + builder.with("name", user); builder.with("firstActive", user.getFirstActive()); builder.with("lastActive", user.getLastActive()); @@ -281,7 +282,7 @@ public MessageBuilder report(User user, Locale locale) throws RejectedException if(reason == null || reason.isEmpty()) reason = "No reason"; builder.with("ban", reason); // Legacy support < 1.5 builder.with("ban.reason", reason); - builder.with("ban.source", ban.getSource() == null ? "Console" : ban.getSource().getName()); + builder.withUserOrConsole("ban.source", ban.getSource()); builder.with("ban.expires", ban.getExpiresAt()); builder.with("ban.created", ban.getCreated()); } @@ -292,7 +293,7 @@ public MessageBuilder report(User user, Locale locale) throws RejectedException if(reason == null || reason.isEmpty()) reason = "No reason"; builder.with("mute", reason); // Legacy support < 1.5 builder.with("mute.reason", reason); - builder.with("mute.source", mute.getSource() == null ? "Console" : mute.getSource().getName()); + builder.withUserOrConsole("mute.source", mute.getSource()); builder.with("mute.expires", mute.getExpiresAt()); builder.with("mute.created", mute.getCreated()); } diff --git a/src/main/java/org/maxgamer/maxbans/service/WarningService.java b/src/main/java/org/maxgamer/maxbans/service/WarningService.java index 7910e94..1c98eff 100644 --- a/src/main/java/org/maxgamer/maxbans/service/WarningService.java +++ b/src/main/java/org/maxgamer/maxbans/service/WarningService.java @@ -60,7 +60,7 @@ public MessageBuilder warn(User source, User user, String reason, Locale locale) if (penalties != null && !penalties.isEmpty()) { Map substitutions = new HashMap<>(); substitutions.put("name", user.getName()); - substitutions.put("source", source == null ? "Console" : source.getName()); + substitutions.put("source", source); substitutions.put("reason", reason); substitutions.put("strike", strike); @@ -70,14 +70,14 @@ public MessageBuilder warn(User source, User user, String reason, Locale locale) } MessageBuilder message = locale.get() - .with("source", source == null ? "Console" : source.getName()) + .withUserOrConsole("source", source) .with("reason", reason) .with("duration", config.getDuration()) - .with("name", user.getName()); + .with("name", user); Player player = locatorService.player(user); if (player != null) { - player.sendMessage(message.get("warn.warned")); + message.get("warn.warned").send(player); } return message; diff --git a/src/main/java/org/maxgamer/maxbans/service/metric/bStatsMetricService.java b/src/main/java/org/maxgamer/maxbans/service/metric/bStatsMetricService.java index 01a0653..add7296 100644 --- a/src/main/java/org/maxgamer/maxbans/service/metric/bStatsMetricService.java +++ b/src/main/java/org/maxgamer/maxbans/service/metric/bStatsMetricService.java @@ -20,7 +20,7 @@ public bStatsMetricService(MaxBansPlus plugin) { metrics.addCustomChart(new Metrics.SimplePie(LOCALE) { @Override public String getValue() { - return plugin.getLocale().getLocale(); + return plugin.getContext().components().locale().getLocale(); } }); diff --git a/src/main/java/org/maxgamer/maxbans/util/MessageUtil.java b/src/main/java/org/maxgamer/maxbans/util/MessageUtil.java index d9cc5e9..3df46fd 100644 --- a/src/main/java/org/maxgamer/maxbans/util/MessageUtil.java +++ b/src/main/java/org/maxgamer/maxbans/util/MessageUtil.java @@ -21,7 +21,7 @@ public static MessageBuilder inject(MessageBuilder builder, Tenant tenant) { public static MessageBuilder inject(MessageBuilder builder, User user) { builder.with("id", user.getId()); - builder.with("name", user.getName()); + builder.withUserOrConsole("name", user); // Check last address UserAddress lastAddress = user.getLastAddress(); @@ -40,7 +40,7 @@ public static MessageBuilder inject(MessageBuilder builder, Address address) { public static MessageBuilder inject(MessageBuilder builder, Restriction restriction) { builder.with("reason", restriction.getReason()); - builder.with("source", restriction.getSource() == null ? "Console" : restriction.getSource().getName()); + builder.withUserOrConsole("source", restriction.getSource()); builder.with("duration", restriction.getExpiresAt()); builder.with("created", restriction.getCreated()); diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 35d170d..319f42b 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -98,6 +98,10 @@ silent: prefix: "&a&o[Silent]&r&r " suffix: "" +hover: + user: | + AKA &a{{users|nobody}}&r + From &a{{country|Unknown}}&r (&a{{continent|Unknown}}&f) # The locale to use for time units. Valid examples include: # en, fr, de, it, ja, ko, zh locale: en diff --git a/src/test/java/org/maxgamer/maxbans/LocaleTest.java b/src/test/java/org/maxgamer/maxbans/LocaleTest.java index b785b09..9e620b7 100644 --- a/src/test/java/org/maxgamer/maxbans/LocaleTest.java +++ b/src/test/java/org/maxgamer/maxbans/LocaleTest.java @@ -4,6 +4,7 @@ import org.junit.Before; import org.junit.Test; import org.maxgamer.maxbans.locale.Locale; +import org.maxgamer.maxbans.service.GeoIPService; import org.maxgamer.maxbans.test.UnitTest; import org.maxgamer.maxbans.util.TemporalDuration; @@ -11,20 +12,24 @@ import java.util.HashMap; import java.util.Map; +import static org.mockito.Mockito.mock; + /** * @author Dirk Jamieson */ public class LocaleTest implements UnitTest { private Locale locale; + private GeoIPService geoIPService; @Before public void init() { Map messages = new HashMap<>(); + geoIPService = mock(GeoIPService.class); messages.put("test.message", "Here is a {{type}} {{mode|message}} {{punc|}}"); messages.put("ban.kick", "You've been banned by {{source}} for {{reason|no reason}}. Expires: {{duration|never}}"); messages.put("greeting", "Hello {{planet|person}}"); - locale = new Locale(messages); + locale = new Locale(geoIPService, messages); } @Test @@ -32,7 +37,8 @@ public void testSubstitution() { String expected = "Here is a test message "; String got = locale.get() .with("type", "test") - .get("test.message"); + .get("test.message") + .toString(); Assert.assertEquals(expected, got); } @@ -43,7 +49,8 @@ public void testSub2() { String got = locale.get() .with("source", "admin") .with("duration", new TemporalDuration(ChronoUnit.HOURS.getDuration())) - .get("ban.kick"); + .get("ban.kick") + .toString(); Assert.assertEquals(expected, got); } @@ -53,7 +60,8 @@ public void testFallbackSubstitution() { String expected = "Hello Sweetie"; String got = locale.get() .with("person", "Sweetie") - .get("greeting"); + .get("greeting") + .toString(); Assert.assertEquals(expected, got); } @@ -62,7 +70,8 @@ public void testFallbackSubstitution() { public void testFallBackWithNoValue() { String expected = "Hello person"; String got = locale.get() - .get("greeting"); + .get("greeting") + .toString(); Assert.assertEquals(expected, got); } diff --git a/src/test/java/org/maxgamer/maxbans/PluginContextTest.java b/src/test/java/org/maxgamer/maxbans/PluginContextTest.java index 83badf8..b72476b 100644 --- a/src/test/java/org/maxgamer/maxbans/PluginContextTest.java +++ b/src/test/java/org/maxgamer/maxbans/PluginContextTest.java @@ -8,7 +8,6 @@ import org.junit.Before; import org.maxgamer.maxbans.config.PluginConfig; import org.maxgamer.maxbans.context.PluginContext; -import org.maxgamer.maxbans.locale.Locale; import org.maxgamer.maxbans.repository.H2Test; import org.maxgamer.maxbans.test.IntegrationTest; @@ -40,13 +39,10 @@ public void init() throws IOException, InterruptedException { MaxBansPlus plugin = mock(MaxBansPlus.class); FileConfiguration configuration = mock(FileConfiguration.class); doReturn(configuration).when(plugin).getConfig(); - Locale locale = new Locale(); YamlConfiguration localeConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("messages.yml"))); - locale.load(localeConfig); PluginManager pluginManager = mock(PluginManager.class); - - context = new PluginContext(plugin, config, locale, server, folder, java.util.logging.Logger.getLogger("Test"), pluginManager); + context = new PluginContext(plugin, config, server, folder, localeConfig, java.util.logging.Logger.getLogger("Test"), pluginManager); } @After diff --git a/src/test/java/org/maxgamer/maxbans/locale/TooltipMessageTest.java b/src/test/java/org/maxgamer/maxbans/locale/TooltipMessageTest.java new file mode 100644 index 0000000..a40f47d --- /dev/null +++ b/src/test/java/org/maxgamer/maxbans/locale/TooltipMessageTest.java @@ -0,0 +1,144 @@ +package org.maxgamer.maxbans.locale; + +import junit.framework.Assert; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.command.CommandSender; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.Mockito.*; + +/** + * TODO: Document this + */ +public class TooltipMessageTest { + private static final String TEMPLATE_ID = "template.id"; + private Locale locale; + private Map messages; + + private CommandSender recipient; + private CommandSender.Spigot recipientSpigot; + + @Before + public void setup() { + locale = mock(Locale.class); + messages = new HashMap<>(); + + doReturn(messages).when(locale).getMessages(); + + recipient = mock(CommandSender.class); + recipientSpigot = mock(CommandSender.Spigot.class); + + doReturn(recipientSpigot).when(recipient).spigot(); + } + + @Test + public void testBasic() { + messages.put(TEMPLATE_ID, "some message"); + TooltipMessage message = new TooltipMessage(locale, new HashMap<>(), TEMPLATE_ID); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BaseComponent.class); + + message.send(recipient); + + verify(recipient, times(1)).spigot(); + verify(locale, times(1)).getMessages(); + verify(recipientSpigot, times(1)).sendMessage(new BaseComponent[]{captor.capture()}); + + List components = captor.getAllValues(); + + Assert.assertEquals("Expect a Single Component", 1, components.size()); + + BaseComponent component = components.get(0); + Assert.assertEquals("Expect white", ChatColor.WHITE, component.getColor()); + Assert.assertEquals("Expect some message", "some message", component.toPlainText()); + } + + @Test + public void testTemplate() { + messages.put(TEMPLATE_ID, "some &amessage"); + + TooltipMessage message = new TooltipMessage(locale, new HashMap<>(), TEMPLATE_ID); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BaseComponent.class); + + message.send(recipient); + verify(recipientSpigot, times(1)).sendMessage(new BaseComponent[]{captor.capture()}); + + List components = captor.getAllValues(); + + Assert.assertEquals("Expect 2 components", 2, components.size()); + + BaseComponent first = components.get(0); + Assert.assertEquals("Expect white", ChatColor.WHITE, first.getColor()); + Assert.assertEquals("Expect 'some '", "some ", first.toPlainText()); + + BaseComponent second = components.get(1); + Assert.assertEquals("Expect green", ChatColor.GREEN, second.getColor()); + Assert.assertEquals("Expect 'message'", "message", second.toPlainText()); + } + + @Test + public void testValueDoesntAffectTrailingColor() { + messages.put(TEMPLATE_ID, "some &b{{thing}} else"); + + BaseComponent[] thing = TextComponent.fromLegacyText(ChatColor.translateAlternateColorCodes('&', "&aTEXT")); + TooltipMessage message = new TooltipMessage(locale, Collections.singletonMap("thing", thing), TEMPLATE_ID); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BaseComponent.class); + + message.send(recipient); + verify(recipientSpigot, times(1)).sendMessage(new BaseComponent[]{captor.capture()}); + + List components = captor.getAllValues(); + + Assert.assertEquals("Expect 3 components", 3, components.size()); + + BaseComponent first = components.get(0); + Assert.assertEquals("Expect white", ChatColor.WHITE, first.getColor()); + Assert.assertEquals("Expect 'some '", "some ", first.toPlainText()); + + BaseComponent second = components.get(1); + Assert.assertEquals("Expect green", ChatColor.GREEN, second.getColor()); + Assert.assertEquals("Expect '&aTEXT'", "TEXT", second.toPlainText()); + + BaseComponent third = components.get(2); + Assert.assertEquals("Expect aqua", ChatColor.AQUA, third.getColor()); + Assert.assertEquals("Expect ' else'", " else", third.toPlainText()); + } + + @Test + public void testLiteralAffectsColorlessValue() { + messages.put(TEMPLATE_ID, "Hello &b{{thing}}"); + + TextComponent thing = new TextComponent(); + thing.setText("World!"); + + TooltipMessage message = new TooltipMessage(locale, Collections.singletonMap("thing", thing), TEMPLATE_ID); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BaseComponent.class); + + message.send(recipient); + verify(recipientSpigot, times(1)).sendMessage(new BaseComponent[]{captor.capture()}); + + List components = captor.getAllValues(); + + Assert.assertEquals("Expect 2 components", 2, components.size()); + + BaseComponent first = components.get(0); + Assert.assertEquals("Expect white", ChatColor.WHITE, first.getColor()); + Assert.assertEquals("Expect 'Hello '", "Hello ", first.toPlainText()); + + BaseComponent second = components.get(1); + Assert.assertEquals("Expect aqua", ChatColor.AQUA, second.getColor()); + Assert.assertEquals("Expect 'World!'", "World!", second.toPlainText()); + } +} diff --git a/src/test/java/org/maxgamer/maxbans/service/AddressServiceTest.java b/src/test/java/org/maxgamer/maxbans/service/AddressServiceTest.java index 1197471..0887435 100644 --- a/src/test/java/org/maxgamer/maxbans/service/AddressServiceTest.java +++ b/src/test/java/org/maxgamer/maxbans/service/AddressServiceTest.java @@ -122,7 +122,7 @@ public void testReport() throws MessageException { } try (TransactionLayer tx = getContext().components().transactor().transact()) { - MessageBuilder builder = users.report(users.get(id), new Locale()); + MessageBuilder builder = users.report(users.get(id), getContext().components().locale()); Assert.assertNull("expect no ban", builder.preview("ban")); Assert.assertNull("expect no mute", builder.preview("mute")); diff --git a/src/test/java/org/maxgamer/maxbans/service/BroadcastServiceTest.java b/src/test/java/org/maxgamer/maxbans/service/BroadcastServiceTest.java deleted file mode 100644 index 12d5111..0000000 --- a/src/test/java/org/maxgamer/maxbans/service/BroadcastServiceTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.maxgamer.maxbans.service; - -import org.bukkit.Server; -import org.bukkit.entity.Player; -import org.junit.Before; -import org.junit.Test; -import org.maxgamer.maxbans.locale.Locale; - -import java.time.Duration; -import java.util.Collections; - -import static org.mockito.Mockito.*; - -/** - * @author netherfoam - */ -public class BroadcastServiceTest { - private Server server; - private Locale locale; - private BroadcastService broadcast; - - @Before - public void init() { - server = mock(Server.class); - locale = new Locale(); - - broadcast = new BroadcastService(server, locale); - } - - /** - * Ensure that sending multiple messages to moderators are throttled by the broadcast system when required - */ - @Test - public void testFirewalled() { - Player player = mock(Player.class); - doReturn(true).when(player).hasPermission(any(String.class)); - doReturn(Collections.singletonList(player)).when(server).getOnlinePlayers(); - - broadcast.moderators("test", Duration.ofMinutes(1), "Hello"); - broadcast.moderators("test", Duration.ofMinutes(1), "Hello"); - - verify(server, times(1)).broadcast(eq("Hello"), any()); - } - - /** - * Ensure that our messages are prefixed and suffixed with the silent marker when sending silent messages - */ - @Test - public void testSilencePrefixSuffix() { - locale.put("silent.prefix", "PRE"); - locale.put("silent.suffix", "SUF"); - - broadcast.broadcast("test", true); - - verify(server, times(1)).broadcast(matches("PRE.*SUF"), anyString()); - } -} diff --git a/src/test/java/org/maxgamer/maxbans/service/HistoryServiceTest.java b/src/test/java/org/maxgamer/maxbans/service/HistoryServiceTest.java index 8e81ca1..b053974 100644 --- a/src/test/java/org/maxgamer/maxbans/service/HistoryServiceTest.java +++ b/src/test/java/org/maxgamer/maxbans/service/HistoryServiceTest.java @@ -5,6 +5,7 @@ import org.maxgamer.maxbans.PluginContextTest; import org.maxgamer.maxbans.exception.CancelledException; import org.maxgamer.maxbans.exception.RejectedException; +import org.maxgamer.maxbans.locale.Message; import org.maxgamer.maxbans.orm.User; import org.maxgamer.maxbans.transaction.TransactionLayer; import org.maxgamer.maxbans.transaction.Transactor; @@ -13,6 +14,7 @@ import java.time.Instant; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; /** * Ensure our history service behaves as expected @@ -20,15 +22,11 @@ public class HistoryServiceTest extends PluginContextTest { private HistoryService historyService; private UserService userService; - private AddressService addressService; - private Transactor transactorService; @Before public void setup() { historyService = getContext().components().services().history(); userService = getContext().components().services().user(); - addressService = getContext().components().services().address(); - transactorService = getContext().components().transactor(); } @Test @@ -39,8 +37,8 @@ public void getBySenderWithContents() throws RejectedException, CancelledExcepti userService.ban(banner, user, "Reason", Duration.ofHours(2)); try (TransactionLayer tx = getContext().components().transactor().transact()) { - List messages = historyService.getHistory(1, banner); - System.out.println(String.join("\n", messages)); + List messages = historyService.getHistory(1, banner); + System.out.println(String.join("\n", messages.stream().map(Message::toString).collect(Collectors.toList()))); } } } diff --git a/src/test/java/org/maxgamer/maxbans/service/LockdownServiceTest.java b/src/test/java/org/maxgamer/maxbans/service/LockdownServiceTest.java index 66cf5ea..15d03d2 100644 --- a/src/test/java/org/maxgamer/maxbans/service/LockdownServiceTest.java +++ b/src/test/java/org/maxgamer/maxbans/service/LockdownServiceTest.java @@ -5,9 +5,12 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; +import org.junit.Before; import org.junit.Test; import org.maxgamer.maxbans.exception.RejectedException; import org.maxgamer.maxbans.locale.Locale; +import org.maxgamer.maxbans.locale.Message; +import org.maxgamer.maxbans.locale.MessageBuilder; import org.maxgamer.maxbans.orm.User; import org.maxgamer.maxbans.test.UnitTest; import org.maxgamer.maxbans.util.Lockdown; @@ -22,14 +25,28 @@ * @author netherfoam */ public class LockdownServiceTest implements UnitTest { + private Locale locale; + + @Before + public void init() { + locale = mock(Locale.class); + MessageBuilder builder = mock(MessageBuilder.class); + doReturn(builder).when(builder).with(anyString(), any(User.class)); + doReturn(builder).when(builder).with(anyString(), any(Object.class)); + doReturn(builder).when(builder).withUserOrConsole(anyString(), any(User.class)); + + doReturn(builder).when(locale).get(); + + Message message = mock(Message.class); + doReturn(message).when(builder).get(anyString()); + } + @Test public void testLockdown() throws RejectedException { Server server = mock(Server.class); UserService users = mock(UserService.class); BroadcastService broadcast = mock(BroadcastService.class); FileConfiguration lockdownYml = YamlConfiguration.loadConfiguration(new File("lockdown.yml")); - Locale locale = new Locale(); - locale.put("lockdown.broadcast", "The server was locked down by {{name|Console}} for {{reason}}"); LockdownService service = new LockdownService(server, users, broadcast, lockdownYml); @@ -43,9 +60,6 @@ public void testKickPlayers() throws RejectedException { UserService users = mock(UserService.class); BroadcastService broadcast = mock(BroadcastService.class); FileConfiguration lockdownYml = YamlConfiguration.loadConfiguration(new File("lockdown.yml")); - Locale locale = new Locale(); - locale.put("lockdown.broadcast", "The server was locked down by {{name|Console}} for {{reason}}"); - locale.put("lockdown.message", "The server was locked down by {{name|Console}} for {{reason}}"); Player player = mock(Player.class); doReturn(Collections.singletonList(player)).when(server).getOnlinePlayers(); @@ -66,9 +80,6 @@ public void testNotKickOldPlayers() throws RejectedException { BroadcastService broadcast = mock(BroadcastService.class); FileConfiguration lockdownYml = YamlConfiguration.loadConfiguration(new File("lockdown.yml")); User user = mock(User.class); - Locale locale = new Locale(); - locale.put("lockdown.broadcast", "The server was locked down by {{name|Console}} for {{reason}}"); - locale.put("lockdown.message", "The server was locked down by {{name|Console}} for {{reason}}"); Player player = mock(Player.class); doReturn(Collections.singletonList(player)).when(server).getOnlinePlayers(); @@ -91,9 +102,6 @@ public void testKickNewPlayers() throws RejectedException { BroadcastService broadcast = mock(BroadcastService.class); FileConfiguration lockdownYml = YamlConfiguration.loadConfiguration(new File("lockdown.yml")); User user = mock(User.class); - Locale locale = new Locale(); - locale.put("lockdown.broadcast", "The server was locked down by {{name|Console}} for {{reason}}"); - locale.put("lockdown.message", "The server was locked down by {{name|Console}} for {{reason}}"); Player player = mock(Player.class); doReturn(Collections.singletonList(player)).when(server).getOnlinePlayers(); @@ -116,9 +124,6 @@ public void testJoin() throws RejectedException { BroadcastService broadcast = mock(BroadcastService.class); FileConfiguration lockdownYml = YamlConfiguration.loadConfiguration(new File("lockdown.yml")); User user = mock(User.class); - Locale locale = new Locale(); - locale.put("lockdown.broadcast", "The server was locked down by {{name|Console}} for {{reason}}"); - locale.put("lockdown.message", "The server was locked down by {{name|Console}} for {{reason}}"); LockdownService service = new LockdownService(server, users, broadcast, lockdownYml); @@ -136,9 +141,6 @@ public void testPersistence() throws RejectedException { BroadcastService broadcast = mock(BroadcastService.class); FileConfiguration lockdownYml = YamlConfiguration.loadConfiguration(new File("lockdown.yml")); - Locale locale = new Locale(); - locale.put("lockdown.broadcast", "The server was locked down by {{name|Console}} for {{reason}}"); - LockdownService service = new LockdownService(server, users, broadcast, lockdownYml); service.lockdown(null, "join", "maintenance", locale); diff --git a/src/test/java/org/maxgamer/maxbans/service/WarningServiceTest.java b/src/test/java/org/maxgamer/maxbans/service/WarningServiceTest.java index a6c9d0c..59f05f3 100644 --- a/src/test/java/org/maxgamer/maxbans/service/WarningServiceTest.java +++ b/src/test/java/org/maxgamer/maxbans/service/WarningServiceTest.java @@ -40,7 +40,7 @@ public void testWarn() throws CancelledException { User user = getContext().components().services().user().create(UUID.randomUUID(), "JoeBlogs", Instant.now()); - Locale locale = new Locale(); + Locale locale = getContext().components().locale(); locale.put("warn.broadcast", "broadcast message"); service.warn(null, user, "Warning", locale); @@ -59,7 +59,7 @@ public void testMultiCommandStrike() throws CancelledException { User user = getContext().components().services().user().create(UUID.randomUUID(), "JoeBlogs", Instant.now()); - Locale locale = new Locale(); + Locale locale = getContext().components().locale(); locale.put("warn.broadcast", "broadcast message"); service.warn(null, user, "Warning", locale); @@ -77,7 +77,7 @@ public void testWarnReset() throws CancelledException { User user = getContext().components().services().user().create(UUID.randomUUID(), "JoeBlogs", Instant.now()); - Locale locale = new Locale(); + Locale locale = getContext().components().locale(); locale.put("warn.broadcast", "broadcast message"); service.warn(null, user, "First", locale);