Fixed many issues, default config values, improvements #123
10 changed files with 91 additions and 42 deletions
|
@ -96,13 +96,16 @@ public final class DPUtils {
|
|||
*/
|
||||
public static ReadOnlyConfigData<Mono<Role>> roleData(IHaveConfig config, String key, String defName, Mono<Guild> guild) {
|
||||
return config.getReadOnlyDataPrimDef(key, defName, name -> {
|
||||
if (!(name instanceof String)) return Mono.empty();
|
||||
return guild.flatMapMany(Guild::getRoles).filter(r -> r.getName().equals(name)).next();
|
||||
if (!(name instanceof String) || ((String) name).length() == 0) return Mono.empty();
|
||||
return guild.flatMapMany(Guild::getRoles).filter(r -> r.getName().equals(name)).onErrorResume(e -> {
|
||||
getLogger().warning("Failed to get role data for " + key + "=" + name + " - " + e.getMessage());
|
||||
return Mono.empty();
|
||||
}).next();
|
||||
}, r -> defName);
|
||||
}
|
||||
|
||||
public static ConfigData<Snowflake> snowflakeData(IHaveConfig config, String key, long defID) {
|
||||
return config.getDataPrimDef(key, defID, id -> Snowflake.of((long) id), Snowflake::asLong);
|
||||
public static ReadOnlyConfigData<Snowflake> snowflakeData(IHaveConfig config, String key, long defID) {
|
||||
return config.getReadOnlyDataPrimDef(key, defID, id -> Snowflake.of((long) id), Snowflake::asLong);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -55,6 +55,9 @@ public class DiscordPlugin extends ButtonPlugin {
|
|||
@Getter
|
||||
private Command2DC manager;
|
||||
|
||||
/**
|
||||
* The prefix to use with Discord commands like /role. It only works in the bot channel.
|
||||
*/
|
||||
private ConfigData<Character> prefix() {
|
||||
return getIConfig().getData("prefix", '/', str -> ((String) str).charAt(0), Object::toString);
|
||||
}
|
||||
|
@ -64,6 +67,9 @@ public class DiscordPlugin extends ButtonPlugin {
|
|||
return plugin.prefix().get();
|
||||
}
|
||||
|
||||
/**
|
||||
* The main server where the roles and other information is pulled from. It's automatically set to the first server the bot's invited to.
|
||||
*/
|
||||
private ConfigData<Optional<Guild>> mainServer() {
|
||||
return getIConfig().getDataPrimDef("mainServer", 0L,
|
||||
id -> {
|
||||
|
@ -76,12 +82,16 @@ public class DiscordPlugin extends ButtonPlugin {
|
|||
g -> g.map(gg -> gg.getId().asLong()).orElse(0L));
|
||||
}
|
||||
|
||||
/**
|
||||
* The (bot) channel to use for Discord commands like /role.
|
||||
*/
|
||||
public ConfigData<Snowflake> commandChannel() {
|
||||
return DPUtils.snowflakeData(getIConfig(), "commandChannel", 239519012529111040L);
|
||||
return DPUtils.snowflakeData(getIConfig(), "commandChannel", 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the role doesn't exist, then it will only allow for the owner.
|
||||
* The role that allows using mod-only Discord commands.
|
||||
* If empty (''), then it will only allow for the owner.
|
||||
*/
|
||||
public ConfigData<Mono<Role>> modRole() {
|
||||
return DPUtils.roleData(getIConfig(), "modRole", "Moderator");
|
||||
|
@ -164,7 +174,7 @@ public class DiscordPlugin extends ButtonPlugin {
|
|||
}
|
||||
SafeMode = false;
|
||||
DPUtils.disableIfConfigErrorRes(null, commandChannel(), DPUtils.getMessageChannel(commandChannel()));
|
||||
DPUtils.disableIfConfigError(null, modRole()); //Won't disable, just prints the warning here
|
||||
//Won't disable, just prints the warning here
|
||||
|
||||
Component.registerComponent(this, new GeneralEventBroadcasterModule());
|
||||
Component.registerComponent(this, new MinecraftChatModule());
|
||||
|
|
|
@ -5,6 +5,7 @@ import buttondevteam.discordplugin.DiscordPlayer;
|
|||
import buttondevteam.discordplugin.DiscordPlugin;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ComponentMetadata;
|
||||
import buttondevteam.lib.architecture.ConfigData;
|
||||
import buttondevteam.lib.architecture.ReadOnlyConfigData;
|
||||
import buttondevteam.lib.player.ChromaGamerBase;
|
||||
|
@ -15,12 +16,13 @@ import com.google.gson.JsonParser;
|
|||
import discord4j.core.object.entity.Message;
|
||||
import discord4j.core.object.entity.MessageChannel;
|
||||
import lombok.val;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Posts new posts from Reddit to the specified channel(s). It will pin the regular posts (not the mod posts).
|
||||
*/
|
||||
@ComponentMetadata(enabledByDefault = false)
|
||||
public class AnnouncerModule extends Component<DiscordPlugin> {
|
||||
/**
|
||||
* Channel to post new posts.
|
||||
|
@ -51,7 +53,13 @@ public class AnnouncerModule extends Component<DiscordPlugin> {
|
|||
return getConfig().getData("lastSeenTime", 0L);
|
||||
}
|
||||
|
||||
private static final String SubredditURL = "https://www.reddit.com/r/ChromaGamers";
|
||||
/**
|
||||
* The subreddit to pull the posts from
|
||||
*/
|
||||
private ConfigData<String> subredditURL() {
|
||||
return getConfig().getData("subredditURL", "https://www.reddit.com/r/ChromaGamers");
|
||||
}
|
||||
|
||||
private static boolean stop = false;
|
||||
|
||||
@Override
|
||||
|
@ -62,11 +70,6 @@ public class AnnouncerModule extends Component<DiscordPlugin> {
|
|||
if (keepPinned == 0) return;
|
||||
Flux<Message> msgs = channel().get().flatMapMany(MessageChannel::getPinnedMessages);
|
||||
msgs.subscribe(Message::unpin);
|
||||
val yc = YamlConfiguration.loadConfiguration(new File("plugins/DiscordPlugin", "config.yml")); //Name change
|
||||
if (lastAnnouncementTime().get() == 0) //Load old data
|
||||
lastAnnouncementTime().set(yc.getLong("lastannouncementtime"));
|
||||
if (lastSeenTime().get() == 0)
|
||||
lastSeenTime().set(yc.getLong("lastseentime"));
|
||||
new Thread(this::AnnouncementGetterThreadMethod).start();
|
||||
}
|
||||
|
||||
|
@ -82,7 +85,7 @@ public class AnnouncerModule extends Component<DiscordPlugin> {
|
|||
Thread.sleep(10000);
|
||||
continue;
|
||||
}
|
||||
String body = TBMCCoreAPI.DownloadString(SubredditURL + "/new/.json?limit=10");
|
||||
String body = TBMCCoreAPI.DownloadString(subredditURL().get() + "/new/.json?limit=10");
|
||||
JsonArray json = new JsonParser().parse(body).getAsJsonObject().get("data").getAsJsonObject()
|
||||
.get("children").getAsJsonArray();
|
||||
StringBuilder msgsb = new StringBuilder();
|
||||
|
|
|
@ -6,6 +6,10 @@ import buttondevteam.lib.TBMCCoreAPI;
|
|||
import buttondevteam.lib.architecture.Component;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Uses a bit of a hacky method of getting all broadcasted messages, including advancements and any other message that's for everyone.
|
||||
* If this component is enabled then these messages will show up on Discord.
|
||||
*/
|
||||
public class GeneralEventBroadcasterModule extends Component<DiscordPlugin> {
|
||||
private static @Getter boolean hooked = false;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package buttondevteam.discordplugin.commands;
|
|||
import buttondevteam.discordplugin.DPUtils;
|
||||
import buttondevteam.lib.chat.Command2Sender;
|
||||
import discord4j.core.object.entity.Message;
|
||||
import discord4j.core.object.entity.User;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
|
@ -30,4 +31,9 @@ public class Command2DCSender implements Command2Sender {
|
|||
public void sendMessage(String[] message) {
|
||||
sendMessage(String.join("\n", message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return message.getAuthor().map(User::getUsername).orElse("Discord");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Listens for errors from the Chroma plugins and posts them to Discord, ignoring repeating errors so it's not that spammy.
|
||||
*/
|
||||
public class ExceptionListenerModule extends Component<DiscordPlugin> implements Listener {
|
||||
private List<Throwable> lastthrown = new ArrayList<>();
|
||||
private List<String> lastsourcemsg = new ArrayList<>();
|
||||
|
@ -84,10 +87,16 @@ public class ExceptionListenerModule extends Component<DiscordPlugin> implements
|
|||
return Mono.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel to post the errors to.
|
||||
*/
|
||||
private ReadOnlyConfigData<Mono<MessageChannel>> channel() {
|
||||
return DPUtils.channelData(getConfig(), "channel");
|
||||
}
|
||||
|
||||
/**
|
||||
* The role to ping if an error occurs. Set to empty ('') to disable.
|
||||
*/
|
||||
private ConfigData<Mono<Role>> pingRole(Mono<Guild> guild) {
|
||||
return DPUtils.roleData(getConfig(), "pingRole", "Coder", guild);
|
||||
}
|
||||
|
|
|
@ -26,23 +26,24 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* All kinds of random things.
|
||||
* The YEEHAW event uses an emoji named :YEEHAW: if available
|
||||
*/
|
||||
public class FunModule extends Component<DiscordPlugin> implements Listener {
|
||||
private static final String[] serverReadyStrings = new String[]{"In one week from now", // Ali
|
||||
"Between now and the heat-death of the universe.", // Ghostise
|
||||
"Soon™", "Ask again this time next month", // Ghostise
|
||||
"In about 3 seconds", // Nicolai
|
||||
"After we finish 8 plugins", // Ali
|
||||
"Tomorrow.", // Ali
|
||||
"After one tiiiny feature", // Ali
|
||||
"Next commit", // Ali
|
||||
"After we finish strangling Towny", // Ali
|
||||
"When we kill every *fucking* bug", // Ali
|
||||
"Once the server stops screaming.", // Ali
|
||||
"After HL3 comes out", // Ali
|
||||
"Next time you ask", // Ali
|
||||
"When will *you* be open?" // Ali
|
||||
private static final String[] serverReadyStrings = new String[]{"in one week from now", // Ali
|
||||
"between now and the heat-death of the universe.", // Ghostise
|
||||
"soon™", "ask again this time next month", // Ghostise
|
||||
"in about 3 seconds", // Nicolai
|
||||
"after we finish 8 plugins", // Ali
|
||||
"tomorrow.", // Ali
|
||||
"after one tiiiny feature", // Ali
|
||||
"next commit", // Ali
|
||||
"after we finish strangling Towny", // Ali
|
||||
"when we kill every *fucking* bug", // Ali
|
||||
"once the server stops screaming.", // Ali
|
||||
"after HL3 comes out", // Ali
|
||||
"next time you ask", // Ali
|
||||
"when will *you* be open?" // Ali
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -52,14 +53,14 @@ public class FunModule extends Component<DiscordPlugin> implements Listener {
|
|||
return getConfig().getData("serverReady", () -> new String[]{"when will the server be open",
|
||||
"when will the server be ready", "when will the server be done", "when will the server be complete",
|
||||
"when will the server be finished", "when's the server ready", "when's the server open",
|
||||
"Vhen vill ze server be open?"});
|
||||
"vhen vill ze server be open?"});
|
||||
}
|
||||
|
||||
/**
|
||||
* Answers for a recognized question. Selected randomly.
|
||||
*/
|
||||
private ConfigData<ArrayList<String>> serverReadyAnswers() {
|
||||
return getConfig().getData("serverReadyAnswers", () -> Lists.newArrayList(serverReadyStrings)); //TODO: Test
|
||||
return getConfig().getData("serverReadyAnswers", () -> Lists.newArrayList(serverReadyStrings));
|
||||
}
|
||||
|
||||
private static final Random serverReadyRandom = new Random();
|
||||
|
@ -119,11 +120,17 @@ public class FunModule extends Component<DiscordPlugin> implements Listener {
|
|||
ListC = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If all of the people who have this role are online, the bot will post a full house.
|
||||
*/
|
||||
private ConfigData<Mono<Role>> fullHouseDevRole(Mono<Guild> guild) {
|
||||
return DPUtils.roleData(getConfig(), "fullHouseDevRole", "Developer", guild);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The channel to post the full house to.
|
||||
*/
|
||||
private ReadOnlyConfigData<Mono<MessageChannel>> fullHouseChannel() {
|
||||
return DPUtils.channelData(getConfig(), "fullHouseChannel");
|
||||
}
|
||||
|
|
|
@ -102,7 +102,8 @@ public class MCChatListener implements Listener {
|
|||
if (lastmsgdata.message == null
|
||||
|| !authorPlayer.equals(lastmsgdata.message.getEmbeds().get(0).getAuthor().map(Embed.Author::getName).orElse(null))
|
||||
|| lastmsgdata.time / 1000000000f < nanoTime / 1000000000f - 120
|
||||
|| !lastmsgdata.mcchannel.ID.equals(e.getChannel().ID)) {
|
||||
|| !lastmsgdata.mcchannel.ID.equals(e.getChannel().ID)
|
||||
|| lastmsgdata.content.length() + e.getMessage().length() + 1 > 2048) {
|
||||
lastmsgdata.message = lastmsgdata.channel.createEmbed(embed).block();
|
||||
lastmsgdata.time = nanoTime;
|
||||
lastmsgdata.mcchannel = e.getChannel();
|
||||
|
|
|
@ -28,12 +28,7 @@ import java.util.stream.Collectors;
|
|||
* Provides Minecraft chat connection to Discord. Commands may be used either in a public chat (limited) or in a DM.
|
||||
*/
|
||||
public class MinecraftChatModule extends Component<DiscordPlugin> {
|
||||
private @Getter
|
||||
MCChatListener listener;
|
||||
|
||||
/*public MCChatListener getListener() { //It doesn't want to generate
|
||||
return listener; - And now ButtonProcessor didn't look beyond this - return instead of continue...
|
||||
}*/
|
||||
private @Getter MCChatListener listener;
|
||||
|
||||
/**
|
||||
* A list of commands that can be used in public chats - Warning: Some plugins will treat players as OPs, always test before allowing a command!
|
||||
|
@ -46,8 +41,8 @@ public class MinecraftChatModule extends Component<DiscordPlugin> {
|
|||
/**
|
||||
* The channel to use as the public Minecraft chat - everything public gets broadcasted here
|
||||
*/
|
||||
public ConfigData<Snowflake> chatChannel() {
|
||||
return DPUtils.snowflakeData(getConfig(), "chatChannel", 239519012529111040L);
|
||||
public ReadOnlyConfigData<Snowflake> chatChannel() {
|
||||
return DPUtils.snowflakeData(getConfig(), "chatChannel", 0L);
|
||||
}
|
||||
|
||||
public Mono<MessageChannel> chatChannelMono() {
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.lang.reflect.Method;
|
|||
public class DiscordMCCommand extends ICommand2MC {
|
||||
@Command2.Subcommand
|
||||
public boolean accept(Player player) {
|
||||
if (checkSafeMode(player)) return true;
|
||||
String did = ConnectCommand.WaitingToConnect.get(player.getName());
|
||||
if (did == null) {
|
||||
player.sendMessage("§cYou don't have a pending connection to Discord.");
|
||||
|
@ -45,6 +46,7 @@ public class DiscordMCCommand extends ICommand2MC {
|
|||
|
||||
@Command2.Subcommand
|
||||
public boolean decline(Player player) {
|
||||
if (checkSafeMode(player)) return true;
|
||||
String did = ConnectCommand.WaitingToConnect.remove(player.getName());
|
||||
if (did == null) {
|
||||
player.sendMessage("§cYou don't have a pending connection to Discord.");
|
||||
|
@ -101,6 +103,7 @@ public class DiscordMCCommand extends ICommand2MC {
|
|||
"Shows an invite link to the server"
|
||||
})
|
||||
public void invite(CommandSender sender) {
|
||||
if (checkSafeMode(sender)) return;
|
||||
String invi = DiscordPlugin.plugin.inviteLink().get();
|
||||
if (invi.length() > 0) {
|
||||
sender.sendMessage("§bInvite link: " + invi);
|
||||
|
@ -132,4 +135,12 @@ public class DiscordMCCommand extends ICommand2MC {
|
|||
return super.getHelpText(method, ann);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkSafeMode(CommandSender sender) {
|
||||
if (DiscordPlugin.SafeMode) {
|
||||
sender.sendMessage("§cThe plugin isn't initialized. Check console for details.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue