use of github.scarsz.discordsrv.objects.MessageFormat in project DiscordSRV by Scarsz.
the class MessageFormatResolver method getMessageFromConfiguration.
public static MessageFormat getMessageFromConfiguration(DynamicConfig config, String key) {
if (!config.getOptional(key).isPresent()) {
return null;
}
Optional<Boolean> enabled = config.getOptionalBoolean(key + ".Enabled");
if (enabled.isPresent() && !enabled.get()) {
return null;
}
MessageFormat messageFormat = new MessageFormat();
if (config.getOptional(key + ".Embed").isPresent() && config.getOptionalBoolean(key + ".Embed.Enabled").orElse(true)) {
Optional<String> hexColor = config.getOptionalString(key + ".Embed.Color");
if (hexColor.isPresent()) {
String hex = hexColor.get().trim();
if (!hex.startsWith("#"))
hex = "#" + hex;
if (hex.length() == 7) {
messageFormat.setColor(new Color(Integer.valueOf(hex.substring(1, 3), 16), Integer.valueOf(hex.substring(3, 5), 16), Integer.valueOf(hex.substring(5, 7), 16)));
} else {
DiscordSRV.debug("Invalid color hex: " + hex + " (in " + key + ".Embed.Color)");
}
} else {
config.getOptionalInt(key + ".Embed.Color").map(Color::new).ifPresent(messageFormat::setColor);
}
if (config.getOptional(key + ".Embed.Author").isPresent()) {
config.getOptionalString(key + ".Embed.Author.Name").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setAuthorName);
config.getOptionalString(key + ".Embed.Author.Url").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setAuthorUrl);
config.getOptionalString(key + ".Embed.Author.ImageUrl").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setAuthorImageUrl);
}
config.getOptionalString(key + ".Embed.ThumbnailUrl").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setThumbnailUrl);
config.getOptionalString(key + ".Embed.Title.Text").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setTitle);
config.getOptionalString(key + ".Embed.Title.Url").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setTitleUrl);
config.getOptionalString(key + ".Embed.Description").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setDescription);
Optional<List<String>> fieldsOptional = config.getOptionalStringList(key + ".Embed.Fields");
if (fieldsOptional.isPresent()) {
List<MessageEmbed.Field> fields = new ArrayList<>();
for (String s : fieldsOptional.get()) {
if (s.contains(";")) {
String[] parts = s.split(";");
if (parts.length < 2) {
continue;
}
boolean inline = parts.length < 3 || Boolean.parseBoolean(parts[2]);
fields.add(new MessageEmbed.Field(parts[0], parts[1], inline, true));
} else {
boolean inline = Boolean.parseBoolean(s);
fields.add(new MessageEmbed.Field("\u200e", "\u200e", inline, true));
}
}
messageFormat.setFields(fields);
}
config.getOptionalString(key + ".Embed.ImageUrl").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setImageUrl);
if (config.getOptional(key + ".Embed.Footer").isPresent()) {
config.getOptionalString(key + ".Embed.Footer.Text").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setFooterText);
config.getOptionalString(key + ".Embed.Footer.IconUrl").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setFooterIconUrl);
}
Optional<Boolean> timestampOptional = config.getOptionalBoolean(key + ".Embed.Timestamp");
if (timestampOptional.isPresent()) {
if (timestampOptional.get()) {
messageFormat.setTimestamp(new Date().toInstant());
}
} else {
Optional<Long> epochOptional = config.getOptionalLong(key + ".Embed.Timestamp");
epochOptional.ifPresent(timestamp -> messageFormat.setTimestamp(new Date(timestamp).toInstant()));
}
}
if (config.getOptional(key + ".Webhook").isPresent() && config.getOptionalBoolean(key + ".Webhook.Enable").orElse(false)) {
messageFormat.setUseWebhooks(true);
config.getOptionalString(key + ".Webhook.AvatarUrl").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setWebhookAvatarUrl);
config.getOptionalString(key + ".Webhook.Name").filter(StringUtils::isNotBlank).ifPresent(messageFormat::setWebhookName);
}
Optional<String> content = config.getOptionalString(key + ".Content");
if (content.isPresent() && StringUtils.isNotBlank(content.get())) {
messageFormat.setContent(content.get());
}
return messageFormat.isAnyContent() ? messageFormat : null;
}
use of github.scarsz.discordsrv.objects.MessageFormat in project DiscordSRV by Scarsz.
the class DiscordSRV method sendLeaveMessage.
/**
* Triggers a leave message for the given player to be sent to Discord. Useful for fake leave messages.
*
* @param player the player
* @param quitMessage the leave/quit message (that is usually provided by Bukkit's {@link PlayerQuitEvent#getQuitMessage()})
* @see #sendJoinMessage(Player, String)
*/
public void sendLeaveMessage(Player player, String quitMessage) {
if (player == null)
throw new IllegalArgumentException("player cannot be null");
MessageFormat messageFormat = getMessageFromConfiguration("MinecraftPlayerLeaveMessage");
if (messageFormat == null || !messageFormat.isAnyContent()) {
debug("Not sending leave message due to it being disabled");
return;
}
TextChannel textChannel = getOptionalTextChannel("leave");
if (textChannel == null) {
DiscordSRV.debug("Not sending quit message, text channel is null");
return;
}
final String displayName = StringUtils.isNotBlank(player.getDisplayName()) ? MessageUtil.strip(player.getDisplayName()) : "";
final String message = StringUtils.isNotBlank(quitMessage) ? quitMessage : "";
final String name = player.getName();
String avatarUrl = getAvatarUrl(player);
String botAvatarUrl = DiscordUtil.getJda().getSelfUser().getEffectiveAvatarUrl();
String botName = getMainGuild() != null ? getMainGuild().getSelfMember().getEffectiveName() : DiscordUtil.getJda().getSelfUser().getName();
BiFunction<String, Boolean, String> translator = (content, needsEscape) -> {
if (content == null)
return null;
content = content.replaceAll("%time%|%date%", TimeUtil.timeStamp()).replace("%message%", MessageUtil.strip(needsEscape ? DiscordUtil.escapeMarkdown(message) : message)).replace("%username%", MessageUtil.strip(needsEscape ? DiscordUtil.escapeMarkdown(name) : name)).replace("%displayname%", needsEscape ? DiscordUtil.escapeMarkdown(displayName) : displayName).replace("%usernamenoescapes%", name).replace("%displaynamenoescapes%", displayName).replace("%embedavatarurl%", avatarUrl).replace("%botavatarurl%", botAvatarUrl).replace("%botname%", botName);
content = DiscordUtil.translateEmotes(content, textChannel.getGuild());
content = PlaceholderUtil.replacePlaceholdersToDiscord(content, player);
return content;
};
Message discordMessage = translateMessage(messageFormat, translator);
if (discordMessage == null)
return;
String webhookName = translator.apply(messageFormat.getWebhookName(), false);
String webhookAvatarUrl = translator.apply(messageFormat.getWebhookAvatarUrl(), false);
if (messageFormat.isUseWebhooks()) {
WebhookUtil.deliverMessage(textChannel, webhookName, webhookAvatarUrl, discordMessage.getContentRaw(), discordMessage.getEmbeds().stream().findFirst().orElse(null));
} else {
DiscordUtil.queueMessage(textChannel, discordMessage, true);
}
}
use of github.scarsz.discordsrv.objects.MessageFormat in project DiscordSRV by Scarsz.
the class DiscordSRV method sendJoinMessage.
/**
* Triggers a join message for the given player to be sent to Discord. Useful for fake join messages.
*
* @param player the player
* @param joinMessage the join message (that is usually provided by Bukkit's {@link PlayerJoinEvent#getJoinMessage()})
* @see #sendLeaveMessage(Player, String)
*/
public void sendJoinMessage(Player player, String joinMessage) {
if (player == null)
throw new IllegalArgumentException("player cannot be null");
MessageFormat messageFormat = player.hasPlayedBefore() ? getMessageFromConfiguration("MinecraftPlayerJoinMessage") : getMessageFromConfiguration("MinecraftPlayerFirstJoinMessage");
if (messageFormat == null || !messageFormat.isAnyContent()) {
debug("Not sending join message due to it being disabled");
return;
}
TextChannel textChannel = getOptionalTextChannel("join");
if (textChannel == null) {
DiscordSRV.debug("Not sending join message, text channel is null");
return;
}
final String displayName = StringUtils.isNotBlank(player.getDisplayName()) ? MessageUtil.strip(player.getDisplayName()) : "";
final String message = StringUtils.isNotBlank(joinMessage) ? joinMessage : "";
final String name = player.getName();
final String avatarUrl = getAvatarUrl(player);
final String botAvatarUrl = DiscordUtil.getJda().getSelfUser().getEffectiveAvatarUrl();
String botName = getMainGuild() != null ? getMainGuild().getSelfMember().getEffectiveName() : DiscordUtil.getJda().getSelfUser().getName();
BiFunction<String, Boolean, String> translator = (content, needsEscape) -> {
if (content == null)
return null;
content = content.replaceAll("%time%|%date%", TimeUtil.timeStamp()).replace("%message%", MessageUtil.strip(needsEscape ? DiscordUtil.escapeMarkdown(message) : message)).replace("%username%", needsEscape ? DiscordUtil.escapeMarkdown(name) : name).replace("%displayname%", needsEscape ? DiscordUtil.escapeMarkdown(displayName) : displayName).replace("%usernamenoescapes%", name).replace("%displaynamenoescapes%", displayName).replace("%embedavatarurl%", avatarUrl).replace("%botavatarurl%", botAvatarUrl).replace("%botname%", botName);
content = DiscordUtil.translateEmotes(content, textChannel.getGuild());
content = PlaceholderUtil.replacePlaceholdersToDiscord(content, player);
return content;
};
Message discordMessage = translateMessage(messageFormat, translator);
if (discordMessage == null)
return;
String webhookName = translator.apply(messageFormat.getWebhookName(), false);
String webhookAvatarUrl = translator.apply(messageFormat.getWebhookAvatarUrl(), false);
if (messageFormat.isUseWebhooks()) {
WebhookUtil.deliverMessage(textChannel, webhookName, webhookAvatarUrl, discordMessage.getContentRaw(), discordMessage.getEmbeds().stream().findFirst().orElse(null));
} else {
DiscordUtil.queueMessage(textChannel, discordMessage, true);
}
}
use of github.scarsz.discordsrv.objects.MessageFormat in project DiscordSRV by Scarsz.
the class AlertListener method process.
private void process(Object event, Dynamic alert, Set<String> triggers, int alertIndex) {
Player player = event instanceof PlayerEvent ? ((PlayerEvent) event).getPlayer() : null;
if (player == null) {
// this will check to see if a #getPlayer() method exists on events coming through
try {
Method getPlayerMethod = event.getClass().getMethod("getPlayer");
if (getPlayerMethod.getReturnType().equals(Player.class)) {
player = (Player) getPlayerMethod.invoke(event);
}
} catch (Exception ignored) {
// we tried ¯\_(ツ)_/¯
}
}
CommandSender sender = null;
String command = null;
List<String> args = new LinkedList<>();
if (event instanceof PlayerCommandPreprocessEvent) {
sender = player;
command = ((PlayerCommandPreprocessEvent) event).getMessage().substring(1);
} else if (event instanceof ServerCommandEvent) {
sender = ((ServerCommandEvent) event).getSender();
command = ((ServerCommandEvent) event).getCommand();
}
if (StringUtils.isNotBlank(command)) {
String[] split = command.split(" ", 2);
String commandBase = split[0];
if (split.length == 2)
args.addAll(Arrays.asList(split[1].split(" ")));
// transform "discordsrv:discord" to just "discord" for example
if (commandBase.contains(":"))
commandBase = commandBase.substring(commandBase.lastIndexOf(":") + 1);
command = commandBase + (split.length == 2 ? (" " + split[1]) : "");
}
MessageFormat messageFormat = DiscordSRV.getPlugin().getMessageFromConfiguration("Alerts." + alertIndex);
for (String trigger : triggers) {
String eventName = getEventName(event);
if (trigger.startsWith("/")) {
if (StringUtils.isBlank(command) || !command.toLowerCase().split("\\s+|$", 2)[0].equals(trigger.substring(1)))
continue;
} else {
// make sure the called event matches what this alert is supposed to trigger on
if (!eventName.equalsIgnoreCase(trigger))
continue;
}
// make sure alert should run even if event is cancelled
if (event instanceof Cancellable && ((Cancellable) event).isCancelled()) {
Dynamic ignoreCancelledDynamic = alert.get("IgnoreCancelled");
boolean ignoreCancelled = ignoreCancelledDynamic.isPresent() ? ignoreCancelledDynamic.as(Boolean.class) : true;
if (ignoreCancelled) {
DiscordSRV.debug(Debug.ALERTS, "Not running alert for event " + eventName + ": event was cancelled");
return;
}
}
Dynamic textChannelsDynamic = alert.get("Channel");
if (textChannelsDynamic == null) {
DiscordSRV.debug(Debug.ALERTS, "Not running alert for trigger " + trigger + ": no target channel was defined");
return;
}
Set<String> channels = new HashSet<>();
if (textChannelsDynamic.isList()) {
textChannelsDynamic.children().map(Weak::asString).filter(Objects::nonNull).forEach(channels::add);
} else if (textChannelsDynamic.isString()) {
channels.add(textChannelsDynamic.asString());
}
Function<Function<String, Collection<TextChannel>>, Set<TextChannel>> channelResolver = converter -> {
Set<TextChannel> textChannels = new HashSet<>();
channels.forEach(channel -> textChannels.addAll(converter.apply(channel)));
textChannels.removeIf(Objects::isNull);
return textChannels;
};
Set<TextChannel> textChannels = channelResolver.apply(s -> {
TextChannel target = DiscordSRV.getPlugin().getDestinationTextChannelForGameChannelName(s);
return Collections.singleton(target);
});
if (textChannels.isEmpty()) {
textChannels.addAll(channelResolver.apply(s -> DiscordUtil.getJda().getTextChannelsByName(s, false)));
}
if (textChannels.isEmpty()) {
textChannels.addAll(channelResolver.apply(s -> NumberUtils.isDigits(s) ? Collections.singleton(DiscordUtil.getJda().getTextChannelById(s)) : Collections.emptyList()));
}
if (textChannels.size() == 0) {
DiscordSRV.debug(Debug.ALERTS, "Not running alert for trigger " + trigger + ": no target channel was defined/found (channels: " + channels + ")");
return;
}
for (TextChannel textChannel : textChannels) {
// check alert conditions
boolean allConditionsMet = true;
Dynamic conditionsDynamic = alert.dget("Conditions");
if (conditionsDynamic.isPresent()) {
Iterator<Dynamic> conditions = conditionsDynamic.children().iterator();
while (conditions.hasNext()) {
Dynamic dynamic = conditions.next();
String expression = dynamic.convert().intoString();
try {
Boolean value = new SpELExpressionBuilder(expression).withPluginVariables().withVariable("event", event).withVariable("server", Bukkit.getServer()).withVariable("discordsrv", DiscordSRV.getPlugin()).withVariable("player", player).withVariable("sender", sender).withVariable("command", command).withVariable("args", args).withVariable("allArgs", String.join(" ", args)).withVariable("channel", textChannel).withVariable("jda", DiscordUtil.getJda()).evaluate(event, Boolean.class);
DiscordSRV.debug(Debug.ALERTS, "Condition \"" + expression + "\" -> " + value);
if (value != null && !value) {
allConditionsMet = false;
break;
}
} catch (ParseException e) {
DiscordSRV.error("Error while parsing expression \"" + expression + "\" for trigger \"" + trigger + "\" -> " + e.getMessage());
} catch (SpelEvaluationException e) {
DiscordSRV.error("Error while evaluating expression \"" + expression + "\" for trigger \"" + trigger + "\" -> " + e.getMessage());
}
}
if (!allConditionsMet)
continue;
}
CommandSender finalSender = sender;
String finalCommand = command;
Player finalPlayer = player;
BiFunction<String, Boolean, String> translator = (content, needsEscape) -> {
if (content == null)
return null;
// evaluate any SpEL expressions
Map<String, Object> variables = new HashMap<>();
variables.put("event", event);
variables.put("server", Bukkit.getServer());
variables.put("discordsrv", DiscordSRV.getPlugin());
variables.put("player", finalPlayer);
variables.put("sender", finalSender);
variables.put("command", finalCommand);
variables.put("args", args);
variables.put("allArgs", String.join(" ", args));
variables.put("channel", textChannel);
variables.put("jda", DiscordUtil.getJda());
content = NamedValueFormatter.formatExpressions(content, event, variables);
// replace any normal placeholders
content = NamedValueFormatter.format(content, key -> {
switch(key) {
case "tps":
return Lag.getTPSString();
case "time":
case "date":
return TimeUtil.timeStamp();
case "ping":
return finalPlayer != null ? PlayerUtil.getPing(finalPlayer) : "-1";
case "name":
case "username":
return finalPlayer != null ? finalPlayer.getName() : "";
case "displayname":
return finalPlayer != null ? MessageUtil.strip(needsEscape ? DiscordUtil.escapeMarkdown(finalPlayer.getDisplayName()) : finalPlayer.getDisplayName()) : "";
case "world":
return finalPlayer != null ? finalPlayer.getWorld().getName() : "";
case "embedavatarurl":
return finalPlayer != null ? DiscordSRV.getAvatarUrl(finalPlayer) : DiscordUtil.getJda().getSelfUser().getEffectiveAvatarUrl();
case "botavatarurl":
return DiscordUtil.getJda().getSelfUser().getEffectiveAvatarUrl();
case "botname":
return DiscordSRV.getPlugin().getMainGuild() != null ? DiscordSRV.getPlugin().getMainGuild().getSelfMember().getEffectiveName() : DiscordUtil.getJda().getSelfUser().getName();
default:
return "{" + key + "}";
}
});
content = DiscordUtil.translateEmotes(content, textChannel.getGuild());
content = PlaceholderUtil.replacePlaceholdersToDiscord(content, finalPlayer);
return content;
};
Message message = DiscordSRV.translateMessage(messageFormat, translator);
if (message == null) {
DiscordSRV.debug(Debug.ALERTS, "Not sending alert because it is configured to have no message content");
return;
}
if (messageFormat.isUseWebhooks()) {
WebhookUtil.deliverMessage(textChannel, translator.apply(messageFormat.getWebhookName(), false), translator.apply(messageFormat.getWebhookAvatarUrl(), false), message.getContentRaw(), message.getEmbeds().stream().findFirst().orElse(null));
} else {
DiscordUtil.queueMessage(textChannel, message);
}
}
}
}
use of github.scarsz.discordsrv.objects.MessageFormat in project DiscordSRV by Scarsz.
the class PlayerJoinLeaveListener method onPlayerJoin.
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer();
// if player is OP & update is available tell them
if (GamePermissionUtil.hasPermission(player, "discordsrv.updatenotification") && DiscordSRV.updateIsAvailable) {
MessageUtil.sendMessage(player, DiscordSRV.getPlugin().getDescription().getVersion().endsWith("-SNAPSHOT") ? ChatColor.GRAY + "There is a newer development build of DiscordSRV available. Download it at https://snapshot.discordsrv.com/" : ChatColor.AQUA + "An update to DiscordSRV is available. Download it at https://www.spigotmc.org/resources/discordsrv.18494/ or https://get.discordsrv.com");
}
if (DiscordSRV.getPlugin().isGroupRoleSynchronizationEnabled()) {
// trigger a synchronization for the player
Bukkit.getScheduler().runTaskAsynchronously(DiscordSRV.getPlugin(), () -> DiscordSRV.getPlugin().getGroupSynchronizationManager().resync(player, GroupSynchronizationManager.SyncDirection.AUTHORITATIVE, true, GroupSynchronizationManager.SyncCause.PLAYER_JOIN));
}
if (PlayerUtil.isVanished(player)) {
DiscordSRV.debug(Debug.MINECRAFT_TO_DISCORD, "Not sending a join message for " + event.getPlayer().getName() + " because a vanish plugin reported them as vanished");
return;
}
MessageFormat messageFormat = event.getPlayer().hasPlayedBefore() ? DiscordSRV.getPlugin().getMessageFromConfiguration("MinecraftPlayerJoinMessage") : DiscordSRV.getPlugin().getMessageFromConfiguration("MinecraftPlayerFirstJoinMessage");
// make sure join messages enabled
if (messageFormat == null)
return;
final String name = player.getName();
// check if player has permission to not have join messages
if (GamePermissionUtil.hasPermission(event.getPlayer(), "discordsrv.silentjoin")) {
DiscordSRV.info(LangUtil.InternalMessage.SILENT_JOIN.toString().replace("{player}", name));
return;
}
// player doesn't have silent join permission, send join message
// schedule command to run in a second to be able to capture display name
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordSRV.getPlugin(), () -> DiscordSRV.getPlugin().sendJoinMessage(event.getPlayer(), event.getJoinMessage()), 20);
// if enabled, set the player's discord nickname as their ign
if (DiscordSRV.config().getBoolean("NicknameSynchronizationEnabled")) {
Bukkit.getScheduler().runTaskAsynchronously(DiscordSRV.getPlugin(), () -> {
final String discordId = DiscordSRV.getPlugin().getAccountLinkManager().getDiscordId(player.getUniqueId());
DiscordSRV.getPlugin().getNicknameUpdater().setNickname(DiscordUtil.getMemberById(discordId), player);
});
}
}
Aggregations