Add discordbroadcast command (#4541)

* Add discordbroadcast command

* Update EssentialsDiscord/src/main/resources/plugin.yml

Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>

* Add emoji parsing/tab complete for discordbroadcast command

Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
This commit is contained in:
Josh Roy 2021-10-11 15:54:55 -04:00 committed by GitHub
parent cb7d9baf7a
commit 43f4d306be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 150 additions and 8 deletions

View File

@ -29,7 +29,7 @@ public class AlternativeCommandsHandler {
}
public final void addPlugin(final Plugin plugin) {
if (plugin.getDescription().getMain().contains("com.earth2me.essentials")) {
if (plugin.getDescription().getMain().contains("com.earth2me.essentials") || plugin.getDescription().getMain().contains("net.essentialsx")) {
return;
}
for (final Map.Entry<String, Command> entry : getPluginCommands(plugin).entrySet()) {

View File

@ -104,6 +104,15 @@ public final class NumberUtil {
return true;
}
public static boolean isLong(final String sLong) {
try {
Long.parseLong(sLong);
} catch (final NumberFormatException e) {
return false;
}
return true;
}
public static boolean isPositiveInt(final String sInt) {
if (!isInt(sInt)) {
return false;

View File

@ -233,6 +233,13 @@ destinationNotSet=Destination not set\!
disabled=disabled
disabledToSpawnMob=\u00a74Spawning this mob was disabled in the config file.
disableUnlimited=\u00a76Disabled unlimited placing of\u00a7c {0} \u00a76for\u00a7c {1}\u00a76.
discordbroadcastCommandDescription=Broadcasts a message to the specified Discord channel.
discordbroadcastCommandUsage=/<command> <channel> <msg>
discordbroadcastCommandUsage1=/<command> <channel> <msg>
discordbroadcastCommandUsage1Description=Sends the given message to the specified Discord channel
discordbroadcastInvalidChannel=\u00a74Discord channel \u00a7c{0}\u00a74 does not exist.
discordbroadcastPermission=\u00a74You do not have permission to send messages to the \u00a7c{0}\u00a74 channel.
discordbroadcastSent=\u00a76Message sent to \u00a7c{0}\u00a76!
discordCommandExecuteDescription=Executes a console command on the Minecraft server.
discordCommandExecuteArgumentCommand=The command to be executed
discordCommandExecuteReply=Executing command: "/{0}"

View File

@ -69,6 +69,10 @@ public class DiscordSettings implements IConf {
}
}
public List<String> getChannelNames() {
return new ArrayList<>(nameToChannelIdMap.keySet());
}
public List<String> getKeysFromChannelId(long channelId) {
return channelIdToNamesMap.get(channelId);
}

View File

@ -4,8 +4,13 @@ import com.earth2me.essentials.IEssentials;
import com.earth2me.essentials.IEssentialsModule;
import com.earth2me.essentials.metrics.MetricsWrapper;
import net.essentialsx.discord.interactions.InteractionControllerImpl;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -86,4 +91,17 @@ public class EssentialsDiscord extends JavaPlugin implements IEssentialsModule {
jda.shutdown();
}
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return ess.onCommandEssentials(sender, command, label, args, EssentialsDiscord.class.getClassLoader(), "net.essentialsx.discord.commands.Command",
"essentials.", jda);
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
return ess.onTabCompleteEssentials(sender, command, alias, args, EssentialsDiscord.class.getClassLoader(),
"net.essentialsx.discord.commands.Command", "essentials.", jda);
}
}

View File

@ -4,17 +4,21 @@ import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.WebhookClientBuilder;
import club.minnced.discord.webhook.send.WebhookMessage;
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
import com.earth2me.essentials.IEssentialsModule;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.Webhook;
import net.dv8tion.jda.api.events.ShutdownEvent;
import net.dv8tion.jda.api.hooks.EventListener;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import net.ess3.nms.refl.providers.AchievementListenerProvider;
import net.ess3.nms.refl.providers.AdvancementListenerProvider;
import net.essentialsx.api.v2.events.discord.DiscordMessageEvent;
@ -51,10 +55,11 @@ import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
public class JDADiscordService implements DiscordService {
public class JDADiscordService implements DiscordService, IEssentialsModule {
private final static Logger logger = Logger.getLogger("EssentialsDiscord");
private final EssentialsDiscord plugin;
private final Unsafe unsafe = this::getJda;
@ -80,12 +85,14 @@ public class JDADiscordService implements DiscordService {
}
public TextChannel getChannel(String key, boolean primaryFallback) {
long resolvedId;
try {
resolvedId = Long.parseLong(key);
} catch (NumberFormatException ignored) {
resolvedId = getSettings().getChannelId(getSettings().getMessageChannel(key));
if (NumberUtil.isLong(key)) {
return getDefinedChannel(key, primaryFallback);
}
return getDefinedChannel(getSettings().getMessageChannel(key), primaryFallback);
}
public TextChannel getDefinedChannel(String key, boolean primaryFallback) {
final long resolvedId = getSettings().getChannelId(key);
if (isDebug()) {
logger.log(Level.INFO, "Channel definition " + key + " resolved as " + resolvedId);
@ -149,8 +156,9 @@ public class JDADiscordService implements DiscordService {
jda = JDABuilder.createDefault(plugin.getSettings().getBotToken())
.addEventListeners(new DiscordListener(this))
.enableCache(CacheFlag.EMOTE)
.disableCache(CacheFlag.MEMBER_OVERRIDES, CacheFlag.VOICE_STATE)
.setContextEnabled(false)
.setRawEventsEnabled(true)
.build()
.awaitReady();
updatePresence();
@ -182,6 +190,9 @@ public class JDADiscordService implements DiscordService {
} catch (InteractionException ignored) {
}
// Load emotes into cache, JDA will handle updates from here on out.
guild.retrieveEmotes().queue();
updatePrimaryChannel();
updateConsoleRelay();
@ -274,6 +285,13 @@ public class JDADiscordService implements DiscordService {
primaryChannel = channel;
}
public String parseMessageEmotes(String message) {
for (final Emote emote : guild.getEmoteCache()) {
message = message.replaceAll(":" + Pattern.quote(emote.getName()) + ":", emote.getAsMention());
}
return message;
}
public void updatePresence() {
jda.getPresence().setPresence(plugin.getSettings().getStatus(), plugin.getSettings().getStatusActivity());
}

View File

@ -0,0 +1,81 @@
package net.essentialsx.discord.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.commands.EssentialsCommand;
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
import com.vdurmont.emoji.EmojiParser;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.TextChannel;
import net.essentialsx.discord.JDADiscordService;
import net.essentialsx.discord.util.DiscordUtil;
import net.essentialsx.discord.util.MessageUtil;
import org.bukkit.Server;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.earth2me.essentials.I18n.tl;
public class Commanddiscordbroadcast extends EssentialsCommand {
public Commanddiscordbroadcast() {
super("discordbroadcast");
}
@Override
protected void run(Server server, CommandSource sender, String commandLabel, String[] args) throws Exception {
if (args.length < 2) {
throw new NotEnoughArgumentsException();
}
if (!sender.isAuthorized("essentials.discordbroadcast." + args[0], ess)) {
throw new Exception(tl("discordbroadcastPermission", args[0]));
}
String message = getFinalArg(args, 1);
if (!sender.isAuthorized("essentials.discordbroadcast.markdown", ess)) {
message = MessageUtil.sanitizeDiscordMarkdown(message);
}
final JDADiscordService jda = (JDADiscordService) module;
final TextChannel channel = jda.getDefinedChannel(args[0], false);
if (channel == null) {
throw new Exception(tl("discordbroadcastInvalidChannel", args[0]));
}
if (!channel.canTalk()) {
throw new Exception(tl("discordNoSendPermission", channel.getName()));
}
channel.sendMessage(jda.parseMessageEmotes(message))
.allowedMentions(sender.isAuthorized("essentials.discordbroadcast.ping", ess) ? null : DiscordUtil.NO_GROUP_MENTIONS)
.queue();
sender.sendMessage(tl("discordbroadcastSent", "#" + EmojiParser.parseToAliases(channel.getName())));
}
@Override
protected List<String> getTabCompleteOptions(Server server, CommandSource sender, String commandLabel, String[] args) {
if (args.length == 1) {
final JDADiscordService jda = (JDADiscordService) module;
final List<String> channels = jda.getSettings().getChannelNames();
channels.removeIf(s -> !sender.isAuthorized("essentials.discordbroadcast." + s, ess));
return channels;
} else {
final String curArg = args[args.length - 1];
if (!curArg.isEmpty() && curArg.charAt(0) == ':' && (curArg.length() == 1 || curArg.charAt(curArg.length() - 1) != ':')) {
final JDADiscordService jda = (JDADiscordService) module;
if (jda.getGuild().getEmoteCache().isEmpty()) {
return Collections.emptyList();
}
final List<String> completions = new ArrayList<>();
for (final Emote emote : jda.getGuild().getEmoteCache()) {
completions.add(":" + emote.getName() + ":");
}
return completions;
}
}
return Collections.emptyList();
}
}

View File

@ -8,3 +8,8 @@ authors: [mdcfe, JRoy, pop4959, Glare]
depend: [Essentials]
softdepend: [EssentialsChat, PlaceholderAPI]
api-version: 1.13
commands:
discordbroadcast:
description: Broadcasts a message to the specified Discord channel.
usage: /<command> <channel> <msg>
aliases: [dbroadcast, dbc, dbcast, ediscordbroadcast, edbroadcast, edbc, edbcast]