A lot of changes... I need to make smaller commits in the future!

master
Chikachi 2017-07-28 23:25:59 +02:00
parent 7246f0b001
commit 88c99ffe0e
No known key found for this signature in database
GPG Key ID: 0136086A0AC09F5E
33 changed files with 1217 additions and 289 deletions

View File

@ -1,5 +1,35 @@
# Changelog (MC 1.10.2)
### 3.0.0
- Complete rewrite
- Added support for sending to multiple Discord channels
- Added support for multiple Discord channels config
- Added support for multiple Minecraft dimension config
- Added support for webhook
- Added support for mentioning roles
- Added support for ignore
- Discord users
- Minecraft messages by regex
- Minecraft FakePlayers
- Added support for `/me` messages
- Added support for commands through Discord DM
- **Notice:** Uses user's roles in all guilds for role permissions
- Added integration for DynmapForge
- Added Discord user discriminator to IMC user NBTTagCompound
- Added linking between Discord user and Minecraft user
- Added whitelist/blacklist to IMC to prevent possible spamming mods
- Moved all commands to Minecraft `/discord ...`
- **Hint:** Use tab autocompletion
- When creating commands for Discord, just point towards the Minecraft command
- Added `/discord uptime` command
- Colored tps is now `/discord tps --color`
- Cuts off messages relayed (to Discord) longer than 2000 characters
- **Notice:** This might break some command responses / formatting
- Such as TPS for servers with many dimensions
- Fixed permission missing crashes
- Fixed relaying cancelled events
- Removed support for `&` in formatting
### 2.2.0
- Added `!uptime` command
- Minecraft formatting will be removed from Discord messages

View File

@ -86,9 +86,10 @@ class CurseForgeDependencyInfo {
// Dependencies on CurseForge
List<CurseForgeDependencyInfo> curseForgeDependencies = new ArrayList<CurseForgeDependencyInfo>()
curseForgeDependencies.add(new CurseForgeDependencyInfo("Dynmap", "2.4-forge-1.10.2", "jar", "2380601"))
dependencies {
compile files('./libs/JDA-3.1.0_204-withDependencies.jar')
compile files('./libs/JDA-3.2.0_226-withDependencies.jar')
compile 'com.vdurmont:emoji-java:3.2.0'
// CurseForge
@ -141,7 +142,7 @@ shadowJar {
relocate "org.apache.commons.logging", "chikachi.discord.repack.org.apache.commons.logging"
dependencies {
include(dependency('net.dv8tion:JDA:3.1.0_204:withDependencies'))
include(dependency('net.dv8tion:JDA:3.2.0_226:withDependencies'))
include(dependency('com.vdurmont:emoji-java:3.2.0'))
}
}

View File

@ -18,12 +18,14 @@ import com.mojang.authlib.GameProfile;
import net.dv8tion.jda.core.entities.MessageChannel;
import net.dv8tion.jda.core.entities.User;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.UUID;
@SuppressWarnings("EntityConstructor")
@ParametersAreNonnullByDefault
public class DiscordCommandSender extends FakePlayer {
private static final UUID playerUUID = UUID.fromString("828653ca-0185-43d4-b26d-620a7f016be6");
@ -34,8 +36,9 @@ public class DiscordCommandSender extends FakePlayer {
this.channel = channel;
}
public DiscordCommandSender(MessageChannel channel, String name) {
super(FMLCommonHandler.instance().getMinecraftServerInstance().worlds[0], new GameProfile(playerUUID, "@" + name));
@SuppressWarnings("unused")
public DiscordCommandSender(WorldServer world, MessageChannel channel, String name) {
super(world, new GameProfile(playerUUID, "@" + name));
this.channel = channel;
}

View File

@ -16,37 +16,74 @@ package chikachi.discord;
import chikachi.discord.command.CommandDiscord;
import chikachi.discord.core.CoreConstants;
import chikachi.discord.core.CoreProxy;
import chikachi.discord.core.Proxy;
import chikachi.discord.core.DiscordClient;
import chikachi.discord.core.Patterns;
import chikachi.discord.listener.DiscordListener;
import chikachi.discord.listener.MinecraftListener;
import com.google.common.base.Joiner;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Mod(modid = CoreConstants.MODID, name = CoreConstants.MODNAME, version = CoreConstants.VERSION, serverSideOnly = true, acceptableRemoteVersions = "*")
public class DiscordIntegration {
@Mod.Instance
public static DiscordIntegration instance;
private static CoreProxy coreProxy = new CoreProxy();
private static Proxy proxy = new Proxy();
@Mod.EventHandler
public void onPreInit(FMLPreInitializationEvent event) {
coreProxy.onPreInit(event.getModConfigurationDirectory());
proxy.onPreInit(event.getModConfigurationDirectory());
addPatterns();
MinecraftForge.EVENT_BUS.register(new MinecraftListener());
}
@Mod.EventHandler
public void onPostInit(FMLPostInitializationEvent event) {
event.buildSoftDependProxy("Dynmap", "chikachi.discord.integration.DynmapIntegration");
}
@Mod.EventHandler
public void onServerAboutToStart(FMLServerAboutToStartEvent event) {
}
@Mod.EventHandler
public void onServerStarting(FMLServerStartingEvent event) {
proxy.onServerStarting();
DiscordClient.getInstance().addEventListener(new DiscordListener());
event.registerServerCommand(new CommandDiscord());
}
@Mod.EventHandler
public void onServerStarted(FMLServerStartedEvent event) {
proxy.onServerStarted();
}
@Mod.EventHandler
public void onServerStopping(FMLServerStoppingEvent event) {
proxy.onServerStopping();
}
@Mod.EventHandler
public void onServerStopped(FMLServerStoppedEvent event) {
proxy.onServerStopped();
}
@Mod.EventHandler
public void imcReceived(FMLInterModComms.IMCEvent event) {
event.getMessages().forEach(IMCHandler::onMessageReceived);
}
public static void addPatterns() {
Patterns.clearCustomPatterns();
@ -67,21 +104,21 @@ public class DiscordIntegration {
switch (modifier) {
case "**":
bold = !bold;
modifier = bold ? TextFormatting.BOLD.toString() : resetString();
this.bold = !this.bold;
modifier = this.bold ? "\u00a7l" : resetString();
break;
case "*":
case "_":
italic = !italic;
modifier = italic ? TextFormatting.ITALIC.toString() : resetString();
this.italic = !this.italic;
modifier = this.italic ? "\u00a7o" : resetString();
break;
case "__":
underline = !underline;
modifier = underline ? TextFormatting.UNDERLINE.toString() : resetString();
this.underline = !this.underline;
modifier = this.underline ? "\u00a7n" : resetString();
break;
case "~~":
strikethrough = !strikethrough;
modifier = strikethrough ? TextFormatting.STRIKETHROUGH.toString() : resetString();
this.strikethrough = !this.strikethrough;
modifier = this.strikethrough ? "\u00a7m" : resetString();
break;
}
@ -90,17 +127,17 @@ public class DiscordIntegration {
private String resetString() {
String text = TextFormatting.RESET.toString();
if (strikethrough) {
text += TextFormatting.STRIKETHROUGH.toString();
if (this.strikethrough) {
text += "\u00a7m";
}
if (underline) {
text += TextFormatting.UNDERLINE.toString();
if (this.underline) {
text += "\u00a7n";
}
if (italic) {
text += TextFormatting.ITALIC.toString();
if (this.italic) {
text += "\u00a7o";
}
if (bold) {
text += TextFormatting.BOLD.toString();
if (this.bold) {
text += "\u00a7l";
}
return text;
}
@ -112,7 +149,7 @@ public class DiscordIntegration {
}
});
Patterns.addDiscordFormattingPattern(Pattern.compile("(?i)(\u00a7[0-9A-FK-OR])"), new Patterns.ReplacementCallback() {
Patterns.addDiscordFormattingPattern(Patterns.minecraftCodePattern, new Patterns.ReplacementCallback() {
private boolean bold = false;
private boolean italic = false;
private boolean underline = false;
@ -130,33 +167,33 @@ public class DiscordIntegration {
for (TextFormatting textFormatting : TextFormatting.values()) {
if (modifier.equalsIgnoreCase(textFormatting.toString())) {
if (textFormatting.equals(TextFormatting.BOLD)) {
bold = true;
this.bold = true;
modifier = "**";
} else if (textFormatting.equals(TextFormatting.ITALIC)) {
italic = true;
this.italic = true;
modifier = "*";
} else if (textFormatting.equals(TextFormatting.UNDERLINE)) {
underline = true;
this.underline = true;
modifier = "__";
} else if (textFormatting.equals(TextFormatting.STRIKETHROUGH)) {
strikethrough = true;
this.strikethrough = true;
modifier = "~~";
} else if (textFormatting.equals(TextFormatting.RESET)) {
modifier = "";
if (bold) {
bold = false;
if (this.bold) {
this.bold = false;
modifier += "**";
}
if (italic) {
italic = false;
if (this.italic) {
this.italic = false;
modifier += "*";
}
if (underline) {
underline = false;
if (this.underline) {
this.underline = false;
modifier += "__";
}
if (strikethrough) {
strikethrough = false;
if (this.strikethrough) {
this.strikethrough = false;
modifier += "~~";
}
} else {
@ -171,57 +208,24 @@ public class DiscordIntegration {
@Override
public String post(String text) {
if (strikethrough) {
if (this.strikethrough) {
text += "~~";
strikethrough = false;
this.strikethrough = false;
}
if (underline) {
if (this.underline) {
text += "__";
underline = false;
this.underline = false;
}
if (italic) {
if (this.italic) {
text += "*";
italic = false;
this.italic = false;
}
if (bold) {
if (this.bold) {
text += "**";
bold = false;
this.bold = false;
}
return text.replaceAll("\\*\\*\\*\\*\\*", "*");
}
});
}
@Mod.EventHandler
public void onServerAboutToStart(FMLServerAboutToStartEvent event) {
}
@Mod.EventHandler
public void onServerStarting(FMLServerStartingEvent event) {
coreProxy.onServerStarting();
DiscordClient.getInstance().addEventListner(new DiscordListener());
event.registerServerCommand(new CommandDiscord());
}
@Mod.EventHandler
public void onServerStarted(FMLServerStartedEvent event) {
coreProxy.onServerStarted();
}
@Mod.EventHandler
public void onServerStopping(FMLServerStoppingEvent event) {
coreProxy.onServerStopping();
}
@Mod.EventHandler
public void onServerStopped(FMLServerStoppedEvent event) {
coreProxy.onServerStopped();
}
@Mod.EventHandler
public void imcReceived(FMLInterModComms.IMCEvent event) {
event.getMessages().forEach(IMCHandler::onMessageReceived);
}
}

View File

@ -14,8 +14,11 @@
package chikachi.discord;
import chikachi.discord.core.DiscordIntegrationLogger;
import chikachi.discord.core.DiscordClient;
import chikachi.discord.core.Message;
import chikachi.discord.core.config.Configuration;
import chikachi.discord.core.config.imc.IMCConfig;
import chikachi.discord.core.config.types.MessageConfig;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fml.common.event.FMLInterModComms;
@ -35,7 +38,7 @@ public class IMCHandler {
return error;
}
public static void onMessageReceived(FMLInterModComms.IMCMessage imcMessage) {
static void onMessageReceived(FMLInterModComms.IMCMessage imcMessage) {
String modId = imcMessage.getSender();
if (imcMessage.isStringMessage()) {
onMessageReceived(modId, imcMessage.key, imcMessage.getStringValue());
@ -45,16 +48,29 @@ public class IMCHandler {
}
@SuppressWarnings("UnusedParameters")
public static void onMessageReceived(String modId, String key, String message) {
private static void onMessageReceived(String modId, String key, String message) {
IMCConfig imcConfig = Configuration.getConfig().imc;
if (key.equalsIgnoreCase("registerListener")) {
if (!registeredIMCMods.contains(modId)) {
DiscordIntegrationLogger.Log(String.format(
"Added %s as listener",
modId
));
if (imcConfig.isAllowed(modId)) {
DiscordIntegrationLogger.Log(
String.format(
"Added %s as listener",
modId
)
);
registeredIMCMods.add(modId);
} else {
registeredIMCMods.add(modId);
} else {
DiscordIntegrationLogger.Log(
String.format(
"%s tried to register as IMC listener but %s",
modId,
imcConfig.isWhitelist() ? "wasn't on the whitelist" : "was on the blacklist"
)
);
}
} else if (imcConfig.isAllowed(modId)) {
FMLInterModComms.sendRuntimeMessage(
DiscordIntegration.instance,
modId,
@ -64,13 +80,15 @@ public class IMCHandler {
}
} else if (key.equalsIgnoreCase("unregisterListener")) {
if (registeredIMCMods.contains(modId)) {
DiscordIntegrationLogger.Log(String.format(
"Removed %s as listener",
modId
));
DiscordIntegrationLogger.Log(
String.format(
"Removed %s as listener",
modId
)
);
registeredIMCMods.remove(modId);
} else {
} else if (imcConfig.isAllowed(modId)) {
FMLInterModComms.sendRuntimeMessage(
DiscordIntegration.instance,
modId,
@ -81,8 +99,9 @@ public class IMCHandler {
}
}
public static void onMessageReceived(String modId, String key, NBTTagCompound message) {
if (key.equalsIgnoreCase("sendMessage")) {
private static void onMessageReceived(String modId, String key, NBTTagCompound message) {
IMCConfig imcConfig = Configuration.getConfig().imc;
if (key.equalsIgnoreCase("sendMessage") && imcConfig.isAllowed(modId)) {
if (!message.hasKey("message") || message.getString("message").trim().length() == 0) {
FMLInterModComms.sendRuntimeMessage(
DiscordIntegration.instance,
@ -112,6 +131,14 @@ public class IMCHandler {
),
message.getLong("channel")
);
} else {
DiscordIntegrationLogger.Log(
String.format(
"%s tried to register as IMC listener but %s",
modId,
imcConfig.isWhitelist() ? "wasn't on the whitelist" : "was on the blacklist"
)
);
}
}
@ -119,10 +146,12 @@ public class IMCHandler {
return registeredIMCMods.size() > 0;
}
@SuppressWarnings("unused")
public static List<String> getRegisteredIMCMods() {
return registeredIMCMods;
}
@SuppressWarnings("unused")
public static void emitMessage(String key, String message) {
registeredIMCMods.forEach(registeredIMCMod -> FMLInterModComms.sendRuntimeMessage(
DiscordIntegration.instance,

View File

@ -15,11 +15,15 @@
package chikachi.discord.command;
import chikachi.discord.core.DiscordClient;
import chikachi.discord.core.config.Configuration;
import chikachi.discord.core.config.linking.LinkingRequest;
import mcp.MethodsReturnNonnullByDefault;
import net.dv8tion.jda.core.entities.User;
import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
@ -27,10 +31,7 @@ import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.*;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@ -42,7 +43,7 @@ public class CommandDiscord extends CommandBase {
@Override
public String getUsage(ICommandSender sender) {
return "";
return "/discord <config|online" + (Configuration.getConfig().discord.allowLinking ? "|link|unlink" : "") + "|tps|unstuck|uptime> [options]";
}
@Override
@ -58,26 +59,100 @@ public class CommandDiscord extends CommandBase {
ArrayList<String> argsList = new ArrayList<>(Arrays.asList(args));
String commandName = argsList.remove(0).toLowerCase();
UUID minecraftUUID;
switch (commandName) {
case "config":
SubCommandConfig.execute(sender, argsList);
break;
case "connect":
/*case "connect":
DiscordClient.getInstance().connect(true);
break;
case "disconnect":
DiscordClient.getInstance().disconnect(true);
break;
break;*/
case "online":
SubCommandOnline.execute(sender);
break;
case "link":
if (!Configuration.getConfig().discord.allowLinking) {
sender.sendMessage(new TextComponentString("\u00A74Linking is not enabled"));
break;
}
if (!(sender instanceof EntityPlayer)) {
sender.sendMessage(new TextComponentString("\u00A74You need to be a player"));
break;
}
minecraftUUID = ((EntityPlayer) sender).getGameProfile().getId();
Long discordId = Configuration.getLinking().getDiscordId(minecraftUUID);
if (discordId != null) {
User discordUser = DiscordClient.getInstance().getJda().getUserById(discordId);
sender.sendMessage(
new TextComponentString(
String.format(
"\u00A7eYou're already linked to %s#%s",
discordUser.getName(),
discordUser.getDiscriminator()
)
)
);
break;
}
if (argsList.size() == 0) {
sender.sendMessage(new TextComponentString("\u00A74Missing code"));
break;
}
Optional<LinkingRequest> requestOptional = Configuration.getLinking().getRequestByCode(argsList.remove(0));
if (requestOptional.isPresent()) {
LinkingRequest request = requestOptional.get();
if (request.hasExpired()) {
sender.sendMessage(new TextComponentString("\u00A74Linking request has expired"));
break;
}
request.executeLinking(minecraftUUID);
sender.sendMessage(new TextComponentString("\u00A7aLinked"));
} else {
sender.sendMessage(new TextComponentString("\u00A74Linking request not found"));
break;
}
break;
case "unlink":
if (!Configuration.getConfig().discord.allowLinking) {
sender.sendMessage(new TextComponentString("\u00A74Linking is not enabled"));
break;
}
if (!(sender instanceof EntityPlayer)) {
sender.sendMessage(new TextComponentString("\u00A74You need to be a player"));
break;
}
minecraftUUID = ((EntityPlayer) sender).getGameProfile().getId();
if (Configuration.getLinking().getDiscordId(minecraftUUID) == null) {
sender.sendMessage(new TextComponentString("\u00A74You aren't linked"));
break;
}
Configuration.getLinking().removeLink(minecraftUUID);
sender.sendMessage(new TextComponentString("\u00A7aUnlinked"));
break;
case "tps":
SubCommandTps.execute(sender, argsList);
break;
case "unstuck":
SubCommandUnstuck.execute(sender, argsList);
break;
case "uptime":
SubCommandUptime.execute(sender);
break;
default:
sender.sendMessage(new TextComponentString("Unknown command"));
break;
@ -94,7 +169,10 @@ public class CommandDiscord extends CommandBase {
int position = args.length;
if (position == 1) {
return getListOfStringsMatchingLastWord(args, "config", "connect", "disconnect", "online", "tps", "unstuck");
if (!Configuration.getConfig().discord.allowLinking) {
return getListOfStringsMatchingLastWord(args, "config", /*"connect", "disconnect",*/ "link", "online", "tps", "unstuck", "uptime", "unlink");
}
return getListOfStringsMatchingLastWord(args, "config", /*"connect", "disconnect",*/ "link", "online", "tps", "unstuck", "uptime", "unlink");
} else if (position == 2) {
if (args[0].equalsIgnoreCase("config")) {
return getListOfStringsMatchingLastWord(args, "load", "reload", "save");
@ -117,4 +195,4 @@ public class CommandDiscord extends CommandBase {
public int compareTo(@NotNull ICommand o) {
return super.compareTo(o);
}
}
}

View File

@ -15,6 +15,7 @@
package chikachi.discord.command;
import chikachi.discord.core.DiscordClient;
import chikachi.discord.core.DiscordIntegrationLogger;
import chikachi.discord.core.config.Configuration;
import net.minecraft.command.ICommandSender;
import net.minecraft.util.text.TextComponentString;
@ -30,7 +31,7 @@ public class SubCommandConfig {
case "reload":
String oldToken = Configuration.getConfig().discord.token;
Configuration.load();
Configuration.loadConfig();
if (!DiscordClient.getInstance().isConnected()) {
// Connect to Discord, if not already connected
@ -40,12 +41,18 @@ public class SubCommandConfig {
DiscordClient.getInstance().disconnect();
DiscordClient.getInstance().connect();
}
sender.sendMessage(new TextComponentString("Config reloaded"));
break;
case "save":
Configuration.save();
Configuration.saveConfig();
sender.sendMessage(new TextComponentString("Config saved"));
break;
case "clean":
Configuration.saveClean();
sender.sendMessage(new TextComponentString("Clean config saved"));
break;
default:
sender.sendMessage(new TextComponentString("Unknown command"));

View File

@ -20,7 +20,6 @@ import com.google.common.base.Joiner;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.fml.common.FMLCommonHandler;
@ -61,15 +60,17 @@ class SubCommandTps {
tpsTimes.add(
String.format(
"%s%s : Mean tick time: %s ms. Mean TPS: %s",
"%s%s : Mean tick time: %s%s ms. Mean TPS: %s%s",
colored && isDiscord ? CoreUtils.tpsToColorString(worldTPS, true) : "",
String.format(
"Dim %s %s",
CoreUtils.padLeft(dimensionId + "", maxDimensionIdLength),
CoreUtils.padRight(dimensionName, maxDimensionNameLength)
),
CoreUtils.padLeft(color + timeFormatter.format(worldTickTime) + TextFormatting.RESET, 6),
CoreUtils.padLeft(color + timeFormatter.format(worldTPS) + TextFormatting.RESET, 6)
CoreUtils.padLeft(color + timeFormatter.format(worldTickTime), 6),
colored && isDiscord ? "" : "\u00a7r",
CoreUtils.padLeft(color + timeFormatter.format(worldTPS), 6),
colored && isDiscord ? "" : "\u00a7r"
)
);
}
@ -81,11 +82,13 @@ class SubCommandTps {
tpsTimes.add(
String.format(
"%s%s : Mean tick time: %s ms. Mean TPS: %s",
"%s%s : Mean tick time: %s%s ms. Mean TPS: %s%s",
colored && isDiscord ? CoreUtils.tpsToColorString(meanTPS, true) : "",
CoreUtils.padRight("Overall", maxDimensionIdLength + maxDimensionNameLength + 5),
CoreUtils.padLeft(color + timeFormatter.format(meanTickTime) + TextFormatting.RESET, 6),
CoreUtils.padLeft(color + timeFormatter.format(meanTPS) + TextFormatting.RESET, 6)
CoreUtils.padLeft(color + timeFormatter.format(meanTickTime), 6),
colored && isDiscord ? "" : "\u00a7r",
CoreUtils.padLeft(color + timeFormatter.format(meanTPS), 6),
colored && isDiscord ? "" : "\u00a7r"
)
);

View File

@ -12,27 +12,21 @@
* along with this program. If not, see http://www.gnu.org/licenses.
*/
package chikachi.discord.core;
package chikachi.discord.command;
public class TeleportResult {
private final boolean success;
private final String errorMessage;
import chikachi.discord.core.Proxy;
import net.minecraft.command.ICommandSender;
import net.minecraft.util.text.TextComponentString;
public TeleportResult() {
this.success = true;
this.errorMessage = "";
}
public TeleportResult(String errorMessage) {
this.success = false;
this.errorMessage = errorMessage;
}
public boolean isSuccess() {
return success;
}
public String getErrorMessage() {
return errorMessage;
class SubCommandUptime {
static void execute(ICommandSender sender) {
sender.sendMessage(
new TextComponentString(
String.format(
"The server have been up for %s",
Proxy.getUptime()
)
)
);
}
}

View File

@ -141,4 +141,8 @@ public class CoreUtils {
public static long mean(long[] values) {
return LongStream.of(values).sum() / values.length;
}
public static String getAvatarUrl(String minecraftUsername) {
return String.format("https://minotar.net/helm/%s/128.png", minecraftUsername);
}
}

View File

@ -22,6 +22,7 @@ import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;
import net.dv8tion.jda.core.entities.SelfUser;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.events.ReadyEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
@ -49,9 +50,9 @@ public class DiscordClient extends ListenerAdapter {
@Override
public void onReady(ReadyEvent event) {
CoreLogger.Log("!!! THIS IS AN ALPHA VERSION !!!", true);
CoreLogger.Log("!!! YOU HAVE BEEN WARNED !!!");
CoreLogger.Log("Logged in as " + getSelf().getName());
DiscordIntegrationLogger.Log("!!! THIS IS AN ALPHA VERSION !!!", true);
DiscordIntegrationLogger.Log("!!! YOU HAVE BEEN WARNED !!!");
DiscordIntegrationLogger.Log("Logged in as " + getSelf().getName());
this.isReady = true;
@ -71,10 +72,11 @@ public class DiscordClient extends ListenerAdapter {
connect(false);
}
public void connect(boolean noMessage) {
@SuppressWarnings("SameParameterValue")
private void connect(boolean noMessage) {
if (this.jda != null) {
if (noMessage) {
CoreLogger.Log("Is already connected", true);
DiscordIntegrationLogger.Log("Is already connected", true);
}
return;
}
@ -83,7 +85,7 @@ public class DiscordClient extends ListenerAdapter {
if (token == null || token.isEmpty()) {
if (noMessage) {
CoreLogger.Log("Missing token", true);
DiscordIntegrationLogger.Log("Missing token", true);
}
return;
}
@ -102,7 +104,7 @@ public class DiscordClient extends ListenerAdapter {
this.jda = builder
.buildAsync();
} catch (LoginException e) {
CoreLogger.Log(
DiscordIntegrationLogger.Log(
String.format(
"Failed to connect to Discord: %s",
e.getMessage()
@ -110,12 +112,12 @@ public class DiscordClient extends ListenerAdapter {
true
);
} catch (Exception e) {
CoreLogger.Log("Failed to connect to Discord", true);
DiscordIntegrationLogger.Log("Failed to connect to Discord", true);
e.printStackTrace();
}
}
public void addEventListner(ListenerAdapter eventListener) {
public void addEventListener(ListenerAdapter eventListener) {
if (eventListener != null) {
if (this.eventListeners.contains(eventListener)) {
return;
@ -137,21 +139,25 @@ public class DiscordClient extends ListenerAdapter {
disconnect(false);
}
public void disconnect(boolean noMessage) {
void disconnect(boolean noMessage) {
if (this.jda == null) {
if (!noMessage) {
CoreLogger.Log("Is already disconnected", true);
DiscordIntegrationLogger.Log("Is already disconnected", true);
}
return;
}
this.jda.shutdown(false);
if (!noMessage) {
CoreLogger.Log("Disconnected from Discord", true);
DiscordIntegrationLogger.Log("Disconnected from Discord", true);
}
this.jda = null;
}
public JDA getJda() {
return this.jda;
}
public SelfUser getSelf() {
if (this.jda == null) {
return null;
@ -160,6 +166,14 @@ public class DiscordClient extends ListenerAdapter {
return this.jda.getSelfUser();
}
public User getUser(long userId) {
if (this.jda == null) {
return null;
}
return this.jda.getUserById(userId);
}
void broadcast(MessageConfig message, List<Long> channels) {
broadcast(new Message(message), channels);
}
@ -169,13 +183,31 @@ public class DiscordClient extends ListenerAdapter {
}
public void broadcast(Message message, List<Long> channels) {
if (channels == null || channels.size() == 0 || this.jda == null || this.jda.getStatus() != JDA.Status.CONNECTED) {
if (channels == null || channels.size() == 0 || this.jda == null || (!this.isReady && this.jda.getStatus() != JDA.Status.CONNECTED)) {
return;
}
for (Long channelId : channels) {
TextChannel channel = this.jda.getTextChannelById(channelId);
if (channel != null) {
if (channel == null) {
DiscordIntegrationLogger.Log(
String.format(
"Could not find channel %s",
channelId
)
);
} else {
if (!channel.canTalk()) {
DiscordIntegrationLogger.Log(
String.format(
"Missing permission to write in channel %s (%s)",
channel.getName(),
channelId
)
);
continue;
}
if (Configuration.getConfig().discord.channels.channels.containsKey(channelId)) {
if (Configuration.getConfig().discord.channels.channels.get(channelId).webhook.trim().length() > 0) {
WebhookMessage webhookMessage = message.toWebhook(channel);
@ -185,7 +217,13 @@ public class DiscordClient extends ListenerAdapter {
}
}
channel.sendMessage(message.getFormattedTextDiscord(channel)).queue();
String text = message.getFormattedTextDiscord(channel);
if (text.length() > 2000) {
text = text.substring(0, 1997) + "...";
}
channel.sendMessage(text).queue();
}
}
}

View File

@ -18,8 +18,8 @@ import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class CoreLogger {
private static final Logger logger = LogManager.getLogger(CoreConstants.MODNAME + "Core");
public class DiscordIntegrationLogger {
private static final Logger logger = LogManager.getLogger(CoreConstants.MODNAME);
public static void Log(String message) {
Log(message, false);

View File

@ -16,6 +16,7 @@ package chikachi.discord.core;
import chikachi.discord.core.config.Configuration;
import chikachi.discord.core.config.types.MessageConfig;
import com.vdurmont.emoji.EmojiParser;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.Channel;
import net.dv8tion.jda.core.entities.Member;
@ -33,6 +34,7 @@ public class Message {
private String prefix = null;
private MessageConfig message = null;
private HashMap<String, String> arguments = null;
private boolean parsing = true;
public Message() {
}
@ -70,12 +72,12 @@ public class Message {
this.arguments.put("USER", getAuthor());
}
public WebhookMessage toWebhook(TextChannel channel) {
WebhookMessage webhookMessage = new WebhookMessage();
webhookMessage.content = formatText(message.webhook, channel);
webhookMessage.username = this.author;
webhookMessage.avatar_url = this.avatarUrl;
return webhookMessage;
WebhookMessage toWebhook(TextChannel channel) {
return new WebhookMessage(
formatText(message.webhook, channel),
this.author,
this.avatarUrl
);
}
public Message setMessage(MessageConfig message) {
@ -98,7 +100,7 @@ public class Message {
return this;
}
public String getAuthor() {
private String getAuthor() {
return this.author;
}
@ -107,6 +109,15 @@ public class Message {
return this;
}
private boolean isParsing() {
return this.parsing;
}
public Message setParsing(boolean parsing) {
this.parsing = parsing;
return this;
}
private String formatText(String text, Channel channel) {
return formatText(text, channel, true);
}
@ -133,6 +144,22 @@ public class Message {
while (m.find()) {
String name = m.group(1);
if (name.equalsIgnoreCase("everyone")) {
if (Configuration.getConfig().minecraft.dimensions.generic.canMentionEveryone) {
return "@everyone";
} else {
return name;
}
}
if (name.equalsIgnoreCase("here")) {
if (Configuration.getConfig().minecraft.dimensions.generic.canMentionHere) {
return "@here";
} else {
return name;
}
}
if (Configuration.getConfig().minecraft.dimensions.generic.canMentionUsers) {
Optional<Member> theMember = channel.getGuild().getMembersByName(name, true)
.stream()
@ -167,7 +194,24 @@ public class Message {
}
}
return (this.prefix != null && this.prefix.trim().length() > 0 ? this.prefix.trim() + " " : "") + (isDiscord ? Patterns.minecraftToDiscord(message) : Patterns.discordToMinecraft(message));
if (this.isParsing()) {
if (isDiscord) {
message = CoreUtils.Replace(CoreConstants.minecraftToDiscordEmotes, message);
message = EmojiParser.parseToUnicode(message);
message = Patterns.minecraftToDiscord(message);
} else {
message = EmojiParser.parseToAliases(message, EmojiParser.FitzpatrickAction.REMOVE);
message = CoreUtils.Replace(CoreConstants.discordToMinecraftEmotes, message);
message = Patterns.discordToMinecraft(message);
}
}
return String.format(
"%s%s",
this.prefix != null && this.prefix.trim().length() > 0 ? this.prefix.trim() + " " : "",
message
);
}
private String getUnformattedText() {

View File

@ -24,6 +24,7 @@ import java.util.regex.Pattern;
public class Patterns {
static final Pattern tagPattern = Pattern.compile("@([^\\s]+)");
public static final Pattern minecraftCodePattern = Pattern.compile("(?i)(\u00a7[0-9A-FK-OR])");
private static final HashMap<Pattern, ReplacementCallback> discordFormattingPatterns = new HashMap<>();
private static final HashMap<Pattern, ReplacementCallback> minecraftFormattingPatterns = new HashMap<>();

View File

@ -18,10 +18,12 @@ import chikachi.discord.core.config.Configuration;
import chikachi.discord.core.config.minecraft.MinecraftConfig;
import java.io.File;
import java.util.Date;
public class CoreProxy {
public class Proxy {
private static boolean preInit = false;
private static boolean serverStopping = false;
private static long started;
public void onPreInit(File configurationPath) {
if (preInit) {
@ -35,6 +37,7 @@ public class CoreProxy {
public void onServerStarting() {
DiscordClient.getInstance().connect();
started = new Date().getTime();
}
public void onServerStarted() {
@ -72,4 +75,30 @@ public class CoreProxy {
DiscordClient.getInstance().disconnect(true);
}
public static String getUptime() {
if (started == 0) {
return "UNKNOWN";
}
long diff = new Date().getTime() - started;
int seconds = (int) Math.floorDiv(diff, 1000);
if (seconds < 60) {
return seconds + " second" + (seconds == 1 ? "" : "s");
}
int minutes = Math.floorDiv(seconds, 60);
seconds -= minutes * 60;
if (minutes < 60) {
return minutes + " minute" + (minutes == 1 ? "" : "s") + ", " + seconds + " second" + (seconds == 1 ? "" : "s");
}
int hours = Math.floorDiv(minutes, 60);
minutes -= hours * 60;
if (hours < 60) {
return hours + " hour" + (hours == 1 ? "" : "s") + ", " + minutes + " minute" + (minutes == 1 ? "" : "s") + ", " + seconds + " second" + (seconds == 1 ? "" : "s");
}
int days = Math.floorDiv(hours, 24);
hours -= days * 60;
return days + " day" + (days == 1 ? "" : "s") + ", " + hours + " hour" + (hours == 1 ? "" : "s") + ", " + minutes + " minute" + (minutes == 1 ? "" : "s") + ", " + seconds + " second" + (seconds == 1 ? "" : "s");
}
}

View File

@ -25,10 +25,16 @@ import org.json.JSONObject;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WebhookMessage {
public String content;
public String username;
public String avatar_url;
class WebhookMessage {
private String content;
private String username;
private String avatarUrl;
WebhookMessage(String content, String username, String avatarUrl) {
this.content = content;
this.username = username;
this.avatarUrl = avatarUrl;
}
boolean queue(JDA jda, Long channelId) {
if (this.content == null || this.content.trim().length() == 0) {
@ -36,7 +42,7 @@ public class WebhookMessage {
}
String webhook = Configuration.getConfig().discord.channels.channels.get(channelId).webhook.trim();
Matcher matcher = Pattern.compile("https://(ptb\\.|)discordapp\\.com/api/webhooks/([0-9]+)/([a-zA-Z0-9\\-_]+)").matcher(webhook);
Matcher matcher = Pattern.compile("https://(ptb\\.)?discordapp\\.com/api/webhooks/([0-9]+)/([a-zA-Z0-9\\-_]+)").matcher(webhook);
if (matcher.matches()) {
String webhookId = matcher.group(2);
String webhookToken = matcher.group(3);
@ -47,10 +53,17 @@ public class WebhookMessage {
if (this.username != null) {
json.put("username", this.username);
}
if (this.avatar_url != null) {
json.put("avatar_url", this.avatar_url);
if (this.avatarUrl != null) {
json.put("avatar_url", this.avatarUrl);
}
json.put("content", Patterns.minecraftToDiscord(this.content));
String text = this.content;
if (text.length() > 2000) {
text = text.substring(0, 1997) + "...";
}
json.put("content", text);
new RestAction<Void>(jda, route, json) {
protected void handleResponse(Response response, Request<Void> request) {

View File

@ -16,6 +16,7 @@ package chikachi.discord.core.config;
import chikachi.discord.core.config.discord.DiscordConfig;
import chikachi.discord.core.config.minecraft.MinecraftConfig;
import chikachi.discord.core.config.imc.IMCConfig;
import com.google.gson.annotations.Since;
public class ConfigWrapper {
@ -23,6 +24,8 @@ public class ConfigWrapper {
public DiscordConfig discord;
@Since(3.0)
public MinecraftConfig minecraft;
@Since(3.0)
public IMCConfig imc;
public void fillFields() {
if (this.discord == null) {
@ -34,5 +37,10 @@ public class ConfigWrapper {
this.minecraft = new MinecraftConfig();
}
this.minecraft.fillFields();
if (this.imc == null) {
this.imc = new IMCConfig();
}
this.imc.fillFields();
}
}

View File

@ -15,7 +15,8 @@
package chikachi.discord.core.config;
import chikachi.discord.core.CoreConstants;
import chikachi.discord.core.CoreLogger;
import chikachi.discord.core.DiscordIntegrationLogger;
import chikachi.discord.core.config.linking.LinkingWrapper;
import chikachi.discord.core.config.types.*;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@ -25,11 +26,16 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Pattern;
public class Configuration {
private static File directory;
private static File configFile;
private static File linkingFile;
private static ConfigWrapper config;
private static LinkingWrapper linking;
public static void onPreInit(String directoryPath) {
directory = new File(directoryPath);
@ -38,8 +44,10 @@ public class Configuration {
directory.mkdirs();
configFile = new File(directory, CoreConstants.MODID + ".json");
linkingFile = new File(directory, CoreConstants.MODID + "_links.json");
load();
loadConfig();
loadLinking();
}
private static Gson createGson() {
@ -47,13 +55,14 @@ public class Configuration {
.registerTypeAdapter(ChannelConfigType.class, new ChannelConfigTypeAdapter())
.registerTypeAdapter(DimensionConfigType.class, new DimensionConfigTypeAdapter())
.registerTypeAdapter(MessageConfig.class, new MessageConfigAdapter())
.registerTypeAdapter(Pattern.class, new PatternAdapter())
.setVersion(3.0)
.serializeNulls()
.setPrettyPrinting()
.create();
}
public static void load() {
public static void loadConfig() {
if (configFile == null) {
return;
}
@ -63,7 +72,7 @@ public class Configuration {
if (!configFile.exists()) {
config = new ConfigWrapper();
config.fillFields();
save();
saveConfig();
} else {
FileReader fileReader = null;
try {
@ -75,7 +84,7 @@ public class Configuration {
config.fillFields();
} catch (Exception e) {
if (e instanceof JsonSyntaxException) {
CoreLogger.Log("Config had invalid syntax - Please check it using a JSON tool ( https://jsonlint.com/ ) or make sure it have the right content", true);
DiscordIntegrationLogger.Log("Config had invalid syntax - Please check it using a JSON tool ( https://jsonlint.com/ ) or make sure it have the right content", true);
}
e.printStackTrace();
@ -93,16 +102,61 @@ public class Configuration {
}
}
}
CoreLogger.Log(gson.toJson(config));
}
public static void save() {
public static void saveConfig() {
saveToFile(configFile, config);
}
public static void loadLinking() {
if (linkingFile == null) {
return;
}
Gson gson = createGson();
if (!linkingFile.exists()) {
linking = new LinkingWrapper();
saveLinking();
} else {
FileReader fileReader = null;
try {
fileReader = new FileReader(linkingFile);
linking = gson.fromJson(fileReader, LinkingWrapper.class);
if (linking == null) {
linking = new LinkingWrapper();
}
} catch (Exception e) {
if (e instanceof JsonSyntaxException) {
DiscordIntegrationLogger.Log("Linking file is corrupt", true);
}
e.printStackTrace();
if (linking == null) {
linking = new LinkingWrapper();
}
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException ignored) {
}
}
}
}
}
public static void saveLinking() {
saveToFile(linkingFile, linking);
}
private static void saveToFile(File file, Object data) {
Gson gson = createGson();
try {
FileWriter writer = new FileWriter(configFile);
writer.write(gson.toJson(config));
FileWriter writer = new FileWriter(file);
writer.write(gson.toJson(data));
writer.close();
} catch (IOException e) {
e.printStackTrace();
@ -126,4 +180,8 @@ public class Configuration {
public static ConfigWrapper getConfig() {
return config;
}
public static LinkingWrapper getLinking() {
return linking;
}
}

View File

@ -14,11 +14,14 @@
package chikachi.discord.core.config.discord;
import chikachi.discord.core.DiscordClient;
import chikachi.discord.core.config.Configuration;
import com.google.common.base.Joiner;
import net.dv8tion.jda.core.entities.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "unused"})
public class CommandConfig {
@ -27,6 +30,7 @@ public class CommandConfig {
private boolean enabled;
private List<String> aliases = new ArrayList<>();
private List<String> permissions = new ArrayList<>();
private static Pattern specificArgPattern = Pattern.compile("\\{ARG_([0-9]+)\\}", Pattern.CASE_INSENSITIVE);
public String getName() {
return name;
@ -46,11 +50,11 @@ public class CommandConfig {
int argsCount = args.size();
if (argsCount > 0) {
for (int i = 0; i < argsCount; i++) {
cmd = cmd.replace("%" + (i + 1) + "%", args.get(i));
cmd = cmd.replace("(?i){ARG_" + (i + 1) + "}", args.get(i));
}
cmd = cmd.replace("%args%", Joiner.on(' ').join(args));
cmd = cmd.replace("(?i){ARGS}", Joiner.on(' ').join(args));
}
cmd = cmd.replaceAll("/%([0-9]+|args)%/", "");
cmd = cmd.replaceAll("(?i)\\{(ARG_[0-9]+|ARGS)\\}", "");
return cmd;
}
@ -64,17 +68,25 @@ public class CommandConfig {
return true;
}
List<Role> roles = null;
final List<Role> roles = new ArrayList<>();
if (channel instanceof TextChannel) {
Member member = ((TextChannel) channel).getGuild().getMember(user);
if (member != null) {
roles = member.getRoles();
roles.addAll(member.getRoles());
}
} else if (channel instanceof PrivateChannel && Configuration.getConfig().discord.channels.generic.allowDMCommands) {
DiscordClient.getInstance().getJda().getGuilds()
.forEach(guild -> {
Member member = guild.getMember(user);
if (member != null) {
roles.addAll(member.getRoles());
}
});
}
for (String permission : permissions) {
if (permission.startsWith("role:")) {
if (roles != null) {
if (roles.size() == 0) {
if (roles.stream().anyMatch(role -> role.getName().equalsIgnoreCase(permission.substring(5)) || role.getId().equals(permission.substring(5)))) {
return true;
}

View File

@ -25,6 +25,10 @@ public class DiscordChannelGenericConfig {
@Since(3.0)
public Boolean canExecuteCommands;
@Since(3.0)
public Boolean stripMinecraftCodes;
@Since(3.0)
public Boolean allowDMCommands;
@Since(3.0)
public DimensionConfigType relayChat;
@Since(3.0)
public DiscordMessagesConfig messages;
@ -40,6 +44,14 @@ public class DiscordChannelGenericConfig {
if (this.canExecuteCommands == null) {
this.canExecuteCommands = false;
}
if (this.stripMinecraftCodes == null) {
this.stripMinecraftCodes = true;
}
if (this.allowDMCommands == null) {
this.allowDMCommands = false;
}
}
if (this.relayChat == null) {

View File

@ -25,6 +25,8 @@ public class DiscordConfig {
@Since(3.0)
public boolean ignoresBots = true;
@Since(3.0)
public boolean allowLinking = true;
@Since(3.0)
public ArrayList<String> ignoresUsers = new ArrayList<>();
@Since(3.0)
public DiscordMainChannelConfig channels = new DiscordMainChannelConfig();

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2017 Chikachi
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*/
package chikachi.discord.core.config.imc;
import com.google.gson.annotations.Since;
import java.util.ArrayList;
import java.util.List;
public class IMCConfig {
@Since(3.0)
public boolean enabled = true;
@Since(3.0)
public String mode = "whitelist";
@Since(3.0)
public List<String> list = new ArrayList<>();
public void fillFields() {
if (this.mode == null) {
this.mode = "whitelist";
}
if (this.mode.equalsIgnoreCase("b") || this.mode.equalsIgnoreCase("bl") || this.mode.equalsIgnoreCase("black") || this.mode.equalsIgnoreCase("blacklist")) {
this.mode = "blacklist";
} else {
this.mode = "whitelist";
}
if (this.list == null) {
this.list = new ArrayList<>();
}
}
public boolean isAllowed(String modId) {
if (this.mode.equalsIgnoreCase("whitelist")) {
return this.list.contains(modId);
} else {
return !this.list.contains(modId);
}
}
public boolean isWhitelist() {
return this.mode.equalsIgnoreCase("whitelist");
}
public boolean isBlacklist() {
return this.mode.equalsIgnoreCase("blacklist");
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2017 Chikachi
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*/
package chikachi.discord.core.config.linking;
import chikachi.discord.core.config.Configuration;
import com.google.gson.annotations.Since;
import java.util.Date;
import java.util.Random;
import java.util.UUID;
public class LinkingRequest {
private static Random rand = new Random();
@Since(3.0)
private long discordId;
@Since(3.0)
private String code;
@Since(3.0)
private long expires;
private LinkingRequest() {
}
static LinkingRequest create(long discordId) {
LinkingRequest request = new LinkingRequest();
request.discordId = discordId;
request.generateCode();
Configuration.getLinking().addRequest(request);
return request;
}
public void generateCode() {
this.code = String.format("%04d", rand.nextInt(10000));
this.expires = new Date(System.currentTimeMillis() + 5 * 60 * 1000).getTime();
}
public long getDiscordId() {
return discordId;
}
public String getCode() {
return code;
}
public boolean hasExpired() {
return this.expires <= new Date().getTime();
}
public String expiresIn() {
int seconds = (int) Math.max(0, Math.floorDiv(this.expires - new Date().getTime(), (int) 1e3));
int minutes = Math.floorDiv(seconds, 60);
seconds -= minutes * 60;
return String.format("%02d:%02d", minutes, seconds);
}
public void executeLinking(UUID minecraftUUID) {
Configuration.getLinking().executeRequest(this, minecraftUUID);
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2017 Chikachi
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*/
package chikachi.discord.core.config.linking;
import chikachi.discord.core.config.Configuration;
import com.google.gson.annotations.Since;
import java.util.*;
public class LinkingWrapper {
@Since(3.0)
private HashMap<UUID, Long> linked = new HashMap<>();
@Since(3.0)
private List<LinkingRequest> requests = new ArrayList<>();
void addRequest(LinkingRequest request) {
Configuration.getLinking().requests.add(request);
Configuration.saveLinking();
}
void executeRequest(LinkingRequest request, UUID minecraftUUID) {
LinkingWrapper linkingWrapper = Configuration.getLinking();
linkingWrapper.linked.put(minecraftUUID, request.getDiscordId());
linkingWrapper.requests.remove(request);
Configuration.saveLinking();
}
public boolean isLinked(UUID minecraftId, long discordId) {
return this.linked.containsKey(minecraftId) && this.linked.get(minecraftId) == discordId;
}
public UUID getMinecraftId(long discordId) {
if (this.linked.containsValue(discordId)) {
Optional<Map.Entry<UUID, Long>> link = this.linked
.entrySet()
.stream()
.filter(uuidLongEntry -> uuidLongEntry.getValue() == discordId)
.findFirst();
if (link.isPresent()) {
return link.get().getKey();
}
}
return null;
}
public Long getDiscordId(UUID minecraftId) {
if (this.linked.containsKey(minecraftId)) {
return this.linked.get(minecraftId);
}
return null;
}
public LinkingRequest getRequest(long discordUserId) {
Optional<LinkingRequest> request = this.requests
.stream()
.filter(linkingRequest -> linkingRequest.getDiscordId() == discordUserId)
.findFirst();
return request.orElseGet(() -> LinkingRequest.create(discordUserId));
}
public Optional<LinkingRequest> getRequestByCode(String code) {
return this.requests
.stream()
.filter(linkingRequest -> linkingRequest.getCode().equalsIgnoreCase(code))
.findFirst();
}
public void removeLink(UUID minecraftUUID) {
this.linked.remove(minecraftUUID);
Configuration.saveLinking();
}
}

View File

@ -19,11 +19,17 @@ import com.google.gson.annotations.Since;
public class MinecraftConfig {
@Since(3.0)
public MinecraftMainDimensionConfig dimensions = new MinecraftMainDimensionConfig();
@Since(3.0)
public MinecraftIntegrationConfig integrations = new MinecraftIntegrationConfig();
public void fillFields() {
if (this.dimensions == null) {
this.dimensions = new MinecraftMainDimensionConfig();
}
this.dimensions.fillFields();
if (this.integrations == null) {
this.integrations = new MinecraftIntegrationConfig();
}
}
}

View File

@ -17,10 +17,22 @@ package chikachi.discord.core.config.minecraft;
import chikachi.discord.core.config.types.ChannelConfigType;
import com.google.gson.annotations.Since;
import java.util.regex.Pattern;
public class MinecraftGenericConfig extends MinecraftDimensionConfig {
@Since(3.0)
public boolean ignoreFakePlayerChat = true;
@Since(3.0)
public boolean relaySayCommand = true;
@Since(3.0)
public boolean relayMeCommand = true;
@Since(3.0)
public boolean canMentionEveryone = false;
@Since(3.0)
public boolean canMentionHere = false;
@Since(3.0)
public Pattern[] messageIgnoreRegex = new Pattern[0];
@Since(3.0)
public ChannelConfigType relayServerStart = new ChannelConfigType();
@Since(3.0)
public ChannelConfigType relayServerStop = new ChannelConfigType();
@ -42,4 +54,20 @@ public class MinecraftGenericConfig extends MinecraftDimensionConfig {
this.relayServerCrash = new ChannelConfigType();
}
}
public boolean isMessageIgnored(String message) {
if (this.messageIgnoreRegex.length > 0) {
Pattern[] ignoreRegex = this.messageIgnoreRegex;
for (Pattern anIgnoreRegex : ignoreRegex) {
if (anIgnoreRegex != null) {
if (anIgnoreRegex.matcher(message).find()) {
return true;
}
}
}
}
return false;
}
}

View File

@ -12,21 +12,11 @@
* along with this program. If not, see http://www.gnu.org/licenses.
*/
package chikachi.discord;
package chikachi.discord.core.config.minecraft;
import chikachi.discord.core.CoreConstants;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.google.gson.annotations.Since;
public class DiscordIntegrationLogger {
private static final Logger logger = LogManager.getLogger(CoreConstants.MODNAME);
public static void Log(String message) {
Log(message, false);
}
public static void Log(String message, boolean warning) {
logger.log(warning ? Level.WARN : Level.INFO, String.format("[%s] %s", CoreConstants.VERSION, message));
}
public class MinecraftIntegrationConfig {
@Since(3.0)
public boolean dynmapEnabled = true;
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2017 Chikachi
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*/
package chikachi.discord.core.config.types;
import com.google.gson.*;
import java.lang.reflect.Type;
import java.util.regex.Pattern;
public class PatternAdapter implements JsonSerializer<Pattern>, JsonDeserializer<Pattern> {
@Override
public Pattern deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return json.isJsonPrimitive() && json.getAsJsonPrimitive().isString() ? Pattern.compile(json.getAsString()) : null;
}
@Override
public JsonElement serialize(Pattern src, Type typeOfSrc, JsonSerializationContext context) {
if (src == null) {
return null;
}
return new JsonPrimitive(src.toString());
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2017 Chikachi
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*/
package chikachi.discord.integration;
import chikachi.discord.core.DiscordClient;
import chikachi.discord.core.DiscordIntegrationLogger;
import chikachi.discord.core.Message;
import chikachi.discord.core.config.Configuration;
import chikachi.discord.core.config.minecraft.MinecraftGenericConfig;
import net.minecraftforge.fml.common.Optional;
import org.dynmap.DynmapCommonAPI;
import org.dynmap.DynmapCommonAPIListener;
import java.util.HashMap;
@SuppressWarnings("unused")
@Optional.Interface(iface = "org.dynmap.DynmapCommonAPIListener", modid = "Dynmap")
public class DynmapIntegration extends DynmapCommonAPIListener {
public DynmapIntegration() {
DynmapCommonAPIListener.register(this);
}
@Override
@Optional.Method(modid = "Dynmap")
public void apiEnabled(DynmapCommonAPI dynmapCommonAPI) {
}
@Override
@Optional.Method(modid = "Dynmap")
public boolean webChatEvent(String source, String name, String message) {
if (Configuration.getConfig().minecraft.integrations.dynmapEnabled) {
MinecraftGenericConfig genericConfig = Configuration.getConfig().minecraft.dimensions.generic;
HashMap<String, String> arguments = new HashMap<>();
arguments.put("MESSAGE", message);
DiscordClient.getInstance().broadcast(
new Message()
.setAuthor("[Dynmap]" + (name != null && name.trim().length() > 0 ? " " + name : ""))
.setMessage(genericConfig.messages.chatMessage)
.setArguments(arguments),
genericConfig.relayChat.getChannels(
genericConfig.discordChannel
)
);
}
return true;
}
}

View File

@ -15,15 +15,20 @@
package chikachi.discord.listener;
import chikachi.discord.DiscordCommandSender;
import chikachi.discord.DiscordIntegrationLogger;
import chikachi.discord.IMCHandler;
import chikachi.discord.core.DiscordClient;
import chikachi.discord.core.DiscordIntegrationLogger;
import chikachi.discord.core.Message;
import chikachi.discord.core.Patterns;
import chikachi.discord.core.config.ConfigWrapper;
import chikachi.discord.core.config.Configuration;
import chikachi.discord.core.config.discord.CommandConfig;
import chikachi.discord.core.config.discord.DiscordChannelGenericConfig;
import chikachi.discord.core.config.discord.DiscordConfig;
import chikachi.discord.core.config.linking.LinkingRequest;
import com.mojang.authlib.GameProfile;
import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.ChannelType;
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
import net.minecraft.entity.player.EntityPlayerMP;
@ -32,10 +37,7 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.fml.common.FMLCommonHandler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
public class DiscordListener extends ListenerAdapter {
@ -59,83 +61,162 @@ public class DiscordListener extends ListenerAdapter {
return;
}
Long channelId = event.getChannel().getIdLong();
DiscordChannelGenericConfig channelConfig;
ArrayList<Integer> dimensions;
if (discordConfig.channels.channels.containsKey(channelId)) {
channelConfig = discordConfig.channels.channels.get(channelId);
dimensions = channelConfig.relayChat.getDimensions(discordConfig.channels.generic.relayChat);
} else {
// Don't relay messages from channels not configured
return;
}
if (dimensions == null) {
return;
}
String content = event.getMessage().getContent().trim();
if (IMCHandler.haveListeners()) {
NBTTagCompound eventTagCompound = new NBTTagCompound();
eventTagCompound.setString("type", "chat");
if (event.getChannelType() == ChannelType.TEXT) {
Long channelId = event.getChannel().getIdLong();
NBTTagCompound userTagComponent = new NBTTagCompound();
userTagComponent.setString("id", event.getAuthor().getId());
userTagComponent.setString("username", event.getAuthor().getName());
eventTagCompound.setTag("user", userTagComponent);
eventTagCompound.setString("message", content);
IMCHandler.emitMessage("event", eventTagCompound);
}
String prefix = channelConfig.commandPrefix != null ? channelConfig.commandPrefix : discordConfig.channels.generic.commandPrefix;
if (content.startsWith(prefix)) {
List<String> args = new ArrayList<>(Arrays.asList(content.substring(prefix.length()).split(" ")));
String cmd = args.remove(0);
List<CommandConfig> commands = Configuration.getConfig().discord.getCommandConfigs();
for (CommandConfig command : commands) {
if (command.shouldExecute(cmd, event.getAuthor(), event.getChannel())) {
FMLCommonHandler.instance().getMinecraftServerInstance().getCommandManager().executeCommand(
new DiscordCommandSender(event.getChannel(), event.getAuthor()),
command.buildCommand(args)
);
return;
DiscordChannelGenericConfig channelConfig;
ArrayList<Integer> dimensions;
boolean stripMinecraftCodes = discordConfig.channels.generic.stripMinecraftCodes;
if (discordConfig.channels.channels.containsKey(channelId)) {
channelConfig = discordConfig.channels.channels.get(channelId);
dimensions = channelConfig.relayChat.getDimensions(discordConfig.channels.generic.relayChat);
if (channelConfig.stripMinecraftCodes != null) {
stripMinecraftCodes = channelConfig.stripMinecraftCodes;
}
} else {
// Don't relay messages from channels not configured
return;
}
return;
}
if (dimensions == null) {
return;
}
if (IMCHandler.haveListeners()) {
NBTTagCompound eventTagCompound = new NBTTagCompound();
eventTagCompound.setString("type", "chat");
NBTTagCompound userTagComponent = new NBTTagCompound();
userTagComponent.setString("id", event.getAuthor().getId());
userTagComponent.setString("username", event.getAuthor().getName());
userTagComponent.setString("discriminator", event.getAuthor().getDiscriminator());
eventTagCompound.setTag("user", userTagComponent);
eventTagCompound.setString("message", content);
IMCHandler.emitMessage("event", eventTagCompound);
}
String prefix = channelConfig.commandPrefix != null ? channelConfig.commandPrefix : discordConfig.channels.generic.commandPrefix;
if (content.startsWith(prefix)) {
List<String> args = new ArrayList<>(Arrays.asList(content.substring(prefix.length()).split(" ")));
tryExecuteCommand(event, args);
return;
}
MinecraftServer minecraftServer = FMLCommonHandler.instance().getMinecraftServerInstance();
List<EntityPlayerMP> players;
if (dimensions.size() == 0) {
players = minecraftServer.getPlayerList().getPlayers();
} else {
players = minecraftServer.getPlayerList().getPlayers()
.stream()
.filter(player -> dimensions.contains(player.dimension))
.collect(Collectors.toList());
}
if (stripMinecraftCodes) {
content = Patterns.minecraftCodePattern.matcher(content).replaceAll("");
}
HashMap<String, String> arguments = new HashMap<>();
arguments.put(
"MESSAGE",
content
);
Message message = new Message()
.setAuthor(event.getAuthor().getName())
.setMessage(config.discord.channels.generic.messages.chatMessage)
.setArguments(arguments);
for (EntityPlayerMP player : players) {
DiscordIntegrationLogger.Log(message.getFormattedTextMinecraft());
player.sendMessage(new TextComponentString(message.getFormattedTextMinecraft()));
}
} else if (event.getChannelType() == ChannelType.PRIVATE && Configuration.getConfig().discord.channels.generic.allowDMCommands) {
String prefix = discordConfig.channels.generic.commandPrefix;
if (content.startsWith(prefix)) {
List<String> args = new ArrayList<>(Arrays.asList(content.substring(prefix.length()).split(" ")));
tryExecuteCommand(event, args);
}
}
}
private void tryExecuteCommand(MessageReceivedEvent event, List<String> args) {
MinecraftServer minecraftServer = FMLCommonHandler.instance().getMinecraftServerInstance();
List<EntityPlayerMP> players;
if (dimensions.size() == 0) {
players = minecraftServer.getPlayerList().getPlayers();
} else {
players = minecraftServer.getPlayerList().getPlayers()
.stream()
.filter(player -> dimensions.contains(player.dimension))
.collect(Collectors.toList());
String cmd = args.remove(0);
if (Configuration.getConfig().discord.allowLinking) {
if (cmd.equalsIgnoreCase("link")) {
UUID minecraftUUID = Configuration.getLinking().getMinecraftId(event.getAuthor().getIdLong());
if (minecraftUUID != null) {
GameProfile minecraftProfile = minecraftServer.getPlayerProfileCache().getProfileByUUID(minecraftUUID);
event.getAuthor().openPrivateChannel()
.queue(privateChannel -> privateChannel.sendMessage(
String.format(
"You are already linked to %s",
minecraftProfile == null ? "a Minecraft account" : minecraftProfile.getName()
)
).queue());
return;
}
LinkingRequest request = Configuration.getLinking().getRequest(event.getAuthor().getIdLong());
if (request.hasExpired()) {
request.generateCode();
}
event.getAuthor().openPrivateChannel()
.queue(privateChannel -> privateChannel.sendMessage(
String.format(
"Use `/discord link %s` on the Minecraft server to link your Discord user with your Minecraft user.\nThe code expires in %s!",
request.getCode(),
request.expiresIn()
)
).queue());
if (event.getMember().getPermissions(event.getTextChannel()).contains(Permission.MESSAGE_MANAGE)) {
event.getMessage().delete().queue();
}
Configuration.saveLinking();
return;
}
if (cmd.equalsIgnoreCase("unlink")) {
UUID minecraftUUID = Configuration.getLinking().getMinecraftId(event.getAuthor().getIdLong());
if (minecraftUUID == null) {
event.getAuthor().openPrivateChannel()
.queue(privateChannel -> privateChannel.sendMessage(
"You aren't linked"
).queue());
} else {
Configuration.getLinking().removeLink(minecraftUUID);
event.getAuthor().openPrivateChannel()
.queue(privateChannel -> privateChannel.sendMessage(
"Unlinked"
).queue());
}
if (event.getMember().getPermissions(event.getTextChannel()).contains(Permission.MESSAGE_MANAGE)) {
event.getMessage().delete().queue();
}
return;
}
}
HashMap<String, String> arguments = new HashMap<>();
arguments.put(
"MESSAGE",
event.getMessage().getContent()
);
Message message = new Message()
.setAuthor(event.getAuthor().getName())
.setMessage(config.discord.channels.generic.messages.chatMessage)
.setArguments(arguments);
for (EntityPlayerMP player : players) {
DiscordIntegrationLogger.Log(message.getFormattedTextMinecraft());
player.sendMessage(new TextComponentString(message.getFormattedTextMinecraft()));
List<CommandConfig> commands = Configuration.getConfig().discord.getCommandConfigs();
for (CommandConfig command : commands) {
if (command.shouldExecute(cmd, event.getAuthor(), event.getChannel())) {
FMLCommonHandler.instance().getMinecraftServerInstance().getCommandManager().executeCommand(
new DiscordCommandSender(event.getChannel(), event.getAuthor()),
command.buildCommand(args)
);
return;
}
}
}
}

View File

@ -14,6 +14,7 @@
package chikachi.discord.listener;
import chikachi.discord.core.CoreUtils;
import chikachi.discord.core.DiscordClient;
import chikachi.discord.core.Message;
import chikachi.discord.core.config.Configuration;
@ -21,6 +22,7 @@ import chikachi.discord.core.config.minecraft.MinecraftConfig;
import chikachi.discord.core.config.minecraft.MinecraftDimensionConfig;
import chikachi.discord.core.config.types.MessageConfig;
import com.google.common.base.Joiner;
import net.dv8tion.jda.core.entities.User;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@ -54,12 +56,29 @@ public class MinecraftListener {
MessageConfig messageConfig;
if (commandName.equalsIgnoreCase("say")) {
if (sender != null && Configuration.getConfig().minecraft.dimensions.generic.ignoreFakePlayerChat && sender instanceof FakePlayer)
if (commandName.equalsIgnoreCase("say") || commandName.equalsIgnoreCase("me")) {
boolean isSayCommand = commandName.equalsIgnoreCase("say");
if (isSayCommand && !Configuration.getConfig().minecraft.dimensions.generic.relaySayCommand) {
return;
}
if (!isSayCommand && !Configuration.getConfig().minecraft.dimensions.generic.relayMeCommand) {
return;
}
if (sender != null && Configuration.getConfig().minecraft.dimensions.generic.ignoreFakePlayerChat && sender instanceof FakePlayer) {
return;
}
String message = Joiner.on(" ").join(event.getParameters());
if (Configuration.getConfig().minecraft.dimensions.generic.isMessageIgnored(message)) {
return;
}
HashMap<String, String> arguments = new HashMap<>();
arguments.put("MESSAGE", Joiner.on(" ").join(event.getParameters()));
arguments.put("MESSAGE", isSayCommand ? message : "_" + message + "_");
String prefix = minecraftConfig.dimensions.generic.chatPrefix;
messageConfig = minecraftConfig.dimensions.generic.messages.chatMessage;
@ -75,6 +94,7 @@ public class MinecraftListener {
if (dimensionConfig.chatPrefix != null && dimensionConfig.chatPrefix.trim().length() > 0) {
prefix = dimensionConfig.chatPrefix;
}
if (dimensionConfig.messages.chatMessage != null) {
messageConfig = dimensionConfig.messages.chatMessage;
}
@ -93,15 +113,40 @@ public class MinecraftListener {
channels = genericConfig.relayChat.getChannels(genericConfig.discordChannel);
}
String authorName = null;
String avatarUrl = null;
//noinspection Duplicates
if (sender != null) {
authorName = sender.getName();
if (sender instanceof EntityPlayer) {
avatarUrl = CoreUtils.getAvatarUrl(sender.getName());
Long discordId = Configuration.getLinking().getDiscordId(((EntityPlayer) sender).getGameProfile().getId());
if (discordId != null) {
User discordUser = DiscordClient.getInstance().getUser(discordId);
if (discordUser != null) {
authorName = discordUser.getName();
avatarUrl = discordUser.getAvatarUrl();
}
}
}
}
DiscordClient.getInstance().broadcast(
new Message()
.setAuthor(sender != null ? sender.getName() : null)
.setAvatarUrl(sender != null && sender instanceof EntityPlayer ? "https://minotar.net/avatar/" + sender.getName() + "/128.png" : null)
.setAuthor(authorName)
.setAvatarUrl(avatarUrl)
.setMessage(messageConfig)
.setArguments(arguments)
.setPrefix(prefix),
channels
);
} else if (commandName.equalsIgnoreCase("discord")) {
// Do not relay linking commands
if (event.getParameters().length > 0 && event.getParameters()[0].equalsIgnoreCase("link")) {
return;
}
}
ArrayList<Long> channels;
@ -136,12 +181,33 @@ public class MinecraftListener {
arguments.put("COMMAND", event.getCommand().getName());
arguments.put("ARGUMENTS", Joiner.on(" ").join(event.getParameters()));
String authorName = null;
String avatarUrl = null;
//noinspection Duplicates
if (sender != null) {
authorName = sender.getName();
if (sender instanceof EntityPlayer) {
avatarUrl = CoreUtils.getAvatarUrl(sender.getName());
Long discordId = Configuration.getLinking().getDiscordId(((EntityPlayer) sender).getGameProfile().getId());
if (discordId != null) {
User discordUser = DiscordClient.getInstance().getUser(discordId);
if (discordUser != null) {
authorName = discordUser.getName();
avatarUrl = discordUser.getAvatarUrl();
}
}
}
}
DiscordClient.getInstance().broadcast(
new Message()
.setAuthor(sender != null ? sender.getName() : null)
.setAvatarUrl(sender != null && sender instanceof EntityPlayer ? "https://minotar.net/avatar/" + sender.getName() + "/128.png" : null)
.setAuthor(authorName)
.setAvatarUrl(avatarUrl)
.setMessage(messageConfig)
.setArguments(arguments),
.setArguments(arguments)
.setParsing(false),
channels
);
}
@ -150,8 +216,13 @@ public class MinecraftListener {
public void onChatMessage(ServerChatEvent event) {
if (event.isCanceled() || event.getPlayer() == null) return;
if (Configuration.getConfig().minecraft.dimensions.generic.ignoreFakePlayerChat && event.getPlayer() instanceof FakePlayer)
if (Configuration.getConfig().minecraft.dimensions.generic.ignoreFakePlayerChat && event.getPlayer() instanceof FakePlayer) {
return;
}
if (Configuration.getConfig().minecraft.dimensions.generic.isMessageIgnored(event.getMessage())) {
return;
}
HashMap<String, String> arguments = new HashMap<>();
arguments.put("MESSAGE", event.getMessage());
@ -162,10 +233,23 @@ public class MinecraftListener {
MessageConfig messageConfig = dimensionConfig.messages.chatMessage != null ? dimensionConfig.messages.chatMessage : genericConfig.messages.chatMessage;
String authorName = event.getUsername();
String avatarUrl = CoreUtils.getAvatarUrl(authorName);
Long discordId = Configuration.getLinking().getDiscordId(event.getPlayer().getGameProfile().getId());
//noinspection Duplicates
if (discordId != null) {
User discordUser = DiscordClient.getInstance().getUser(discordId);
if (discordUser != null) {
authorName = discordUser.getName();
avatarUrl = discordUser.getAvatarUrl();
}
}
DiscordClient.getInstance().broadcast(
new Message()
.setAuthor(event.getUsername())
.setAvatarUrl("https://minotar.net/avatar/" + event.getUsername() + "/128.png")
.setAuthor(authorName)
.setAvatarUrl(avatarUrl)
.setMessage(messageConfig)
.setArguments(arguments)
.setPrefix(dimensionConfig.chatPrefix != null && dimensionConfig.chatPrefix.trim().length() > 0 ? dimensionConfig.chatPrefix : genericConfig.chatPrefix),
@ -206,10 +290,23 @@ public class MinecraftListener {
MessageConfig messageConfig = dimensionConfig.messages.achievement != null ? dimensionConfig.messages.achievement : genericConfig.messages.achievement;
String authorName = entityPlayer.getDisplayNameString();
String avatarUrl = CoreUtils.getAvatarUrl(authorName);
Long discordId = Configuration.getLinking().getDiscordId(entityPlayer.getGameProfile().getId());
//noinspection Duplicates
if (discordId != null) {
User discordUser = DiscordClient.getInstance().getUser(discordId);
if (discordUser != null) {
authorName = discordUser.getName();
avatarUrl = discordUser.getAvatarUrl();
}
}
DiscordClient.getInstance().broadcast(
new Message()
.setAuthor(entityPlayer.getDisplayNameString())
.setAvatarUrl("https://minotar.net/avatar/" + entityPlayer.getName() + "/128.png")
.setAuthor(authorName)
.setAvatarUrl(avatarUrl)
.setMessage(messageConfig)
.setArguments(arguments),
dimensionConfig.relayAchievements.getChannels(
@ -233,10 +330,23 @@ public class MinecraftListener {
MessageConfig messageConfig = dimensionConfig.messages.playerJoin != null ? dimensionConfig.messages.playerJoin : genericConfig.messages.playerJoin;
String authorName = event.player.getDisplayNameString();
String avatarUrl = CoreUtils.getAvatarUrl(authorName);
Long discordId = Configuration.getLinking().getDiscordId(event.player.getGameProfile().getId());
//noinspection Duplicates
if (discordId != null) {
User discordUser = DiscordClient.getInstance().getUser(discordId);
if (discordUser != null) {
authorName = discordUser.getName();
avatarUrl = discordUser.getAvatarUrl();
}
}
DiscordClient.getInstance().broadcast(
new Message()
.setAuthor(event.player.getDisplayNameString())
.setAvatarUrl("https://minotar.net/avatar/" + event.player.getName() + "/128.png")
.setAuthor(authorName)
.setAvatarUrl(avatarUrl)
.setMessage(messageConfig),
dimensionConfig.relayPlayerJoin.getChannels(
genericConfig.relayPlayerJoin.getChannels(
@ -258,10 +368,23 @@ public class MinecraftListener {
MessageConfig messageConfig = dimensionConfig.messages.playerLeave != null ? dimensionConfig.messages.playerLeave : genericConfig.messages.playerLeave;
String authorName = event.player.getDisplayNameString();
String avatarUrl = CoreUtils.getAvatarUrl(authorName);
Long discordId = Configuration.getLinking().getDiscordId(event.player.getGameProfile().getId());
//noinspection Duplicates
if (discordId != null) {
User discordUser = DiscordClient.getInstance().getUser(discordId);
if (discordUser != null) {
authorName = discordUser.getName();
avatarUrl = discordUser.getAvatarUrl();
}
}
DiscordClient.getInstance().broadcast(
new Message()
.setAuthor(event.player.getDisplayNameString())
.setAvatarUrl("https://minotar.net/avatar/" + event.player.getName() + "/128.png")
.setAuthor(authorName)
.setAvatarUrl(avatarUrl)
.setMessage(messageConfig),
dimensionConfig.relayPlayerLeave.getChannels(
genericConfig.relayPlayerLeave.getChannels(
@ -291,10 +414,23 @@ public class MinecraftListener {
MessageConfig messageConfig = dimensionConfig.messages.playerDeath != null ? dimensionConfig.messages.playerDeath : genericConfig.messages.playerDeath;
String authorName = entityPlayer.getDisplayNameString();
String avatarUrl = CoreUtils.getAvatarUrl(authorName);
Long discordId = Configuration.getLinking().getDiscordId(entityPlayer.getGameProfile().getId());
//noinspection Duplicates
if (discordId != null) {
User discordUser = DiscordClient.getInstance().getUser(discordId);
if (discordUser != null) {
authorName = discordUser.getName();
avatarUrl = discordUser.getAvatarUrl();
}
}
DiscordClient.getInstance().broadcast(
new Message()
.setAuthor(entityPlayer.getDisplayNameString())
.setAvatarUrl("https://minotar.net/avatar/" + entityPlayer.getName() + "/128.png")
.setAuthor(authorName)
.setAvatarUrl(avatarUrl)
.setMessage(messageConfig)
.setArguments(arguments),
dimensionConfig.relayPlayerDeath.getChannels(

View File

@ -1,7 +1,7 @@
[{
"modid": "DiscordIntegration",
"name": "DiscordIntegration",
"description": "MC <=> Discord communication",
"description": "MC <=> Discord integration",
"version": "${version}",
"mcversion": "${mcversion}",
"url": "https://discordintegration.net",