2021-07-01 15:43:35 +02:00
package net.essentialsx.discord ;
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 ;
2021-10-11 21:54:55 +02:00
import com.earth2me.essentials.IEssentialsModule ;
2021-08-07 23:22:12 +02:00
import com.earth2me.essentials.User ;
2021-07-01 15:43:35 +02:00
import com.earth2me.essentials.utils.FormatUtil ;
2021-10-11 21:54:55 +02:00
import com.earth2me.essentials.utils.NumberUtil ;
2021-07-05 03:57:13 +02:00
import com.earth2me.essentials.utils.VersionUtil ;
2021-07-01 15:43:35 +02:00
import net.dv8tion.jda.api.JDA ;
import net.dv8tion.jda.api.JDABuilder ;
2021-10-11 21:54:55 +02:00
import net.dv8tion.jda.api.entities.Emote ;
2021-07-01 15:43:35 +02:00
import net.dv8tion.jda.api.entities.Guild ;
2021-08-04 05:19:56 +02:00
import net.dv8tion.jda.api.entities.Role ;
2021-07-01 15:43:35 +02:00
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 ;
2021-10-11 21:54:55 +02:00
import net.dv8tion.jda.api.utils.cache.CacheFlag ;
2021-07-05 03:57:13 +02:00
import net.ess3.nms.refl.providers.AchievementListenerProvider ;
import net.ess3.nms.refl.providers.AdvancementListenerProvider ;
2021-10-24 16:27:07 +02:00
import net.ess3.provider.providers.PaperAdvancementListenerProvider ;
2023-05-01 03:30:11 +02:00
import net.essentialsx.api.v2.ChatType ;
2021-07-01 15:43:35 +02:00
import net.essentialsx.api.v2.events.discord.DiscordMessageEvent ;
import net.essentialsx.api.v2.services.discord.DiscordService ;
import net.essentialsx.api.v2.services.discord.InteractionController ;
import net.essentialsx.api.v2.services.discord.InteractionException ;
2022-12-25 22:13:56 +01:00
import net.essentialsx.api.v2.services.discord.InteractionMember ;
2021-08-04 05:19:56 +02:00
import net.essentialsx.api.v2.services.discord.InteractionRole ;
2021-07-01 15:43:35 +02:00
import net.essentialsx.api.v2.services.discord.MessageType ;
import net.essentialsx.api.v2.services.discord.Unsafe ;
import net.essentialsx.discord.interactions.InteractionControllerImpl ;
2022-12-25 22:13:56 +01:00
import net.essentialsx.discord.interactions.InteractionMemberImpl ;
2021-08-04 05:19:56 +02:00
import net.essentialsx.discord.interactions.InteractionRoleImpl ;
2021-07-01 15:43:35 +02:00
import net.essentialsx.discord.interactions.commands.ExecuteCommand ;
import net.essentialsx.discord.interactions.commands.ListCommand ;
import net.essentialsx.discord.interactions.commands.MessageCommand ;
import net.essentialsx.discord.listeners.BukkitListener ;
import net.essentialsx.discord.listeners.DiscordCommandDispatcher ;
import net.essentialsx.discord.listeners.DiscordListener ;
2023-05-01 03:30:11 +02:00
import net.essentialsx.discord.listeners.EssentialsChatListener ;
import net.essentialsx.discord.listeners.BukkitChatListener ;
2021-07-01 15:43:35 +02:00
import net.essentialsx.discord.util.ConsoleInjector ;
import net.essentialsx.discord.util.DiscordUtil ;
2021-08-07 23:22:12 +02:00
import net.essentialsx.discord.util.MessageUtil ;
2021-07-01 15:43:35 +02:00
import org.bukkit.Bukkit ;
2021-08-07 23:22:12 +02:00
import org.bukkit.entity.Player ;
2021-07-01 15:43:35 +02:00
import org.bukkit.event.HandlerList ;
2023-05-01 03:30:11 +02:00
import org.bukkit.event.Listener ;
2021-07-01 15:43:35 +02:00
import org.bukkit.plugin.Plugin ;
import org.bukkit.plugin.ServicePriority ;
import org.jetbrains.annotations.NotNull ;
import javax.security.auth.login.LoginException ;
2021-08-04 05:19:56 +02:00
import java.util.ArrayList ;
import java.util.Collection ;
2021-07-01 15:43:35 +02:00
import java.util.HashMap ;
2021-08-04 05:19:56 +02:00
import java.util.List ;
2021-07-01 15:43:35 +02:00
import java.util.Map ;
import java.util.concurrent.CompletableFuture ;
import java.util.concurrent.ExecutionException ;
import java.util.concurrent.TimeUnit ;
import java.util.concurrent.TimeoutException ;
import java.util.logging.Level ;
import java.util.logging.Logger ;
import java.util.regex.Matcher ;
2021-10-11 21:54:55 +02:00
import java.util.regex.Pattern ;
2021-07-01 15:43:35 +02:00
import static com.earth2me.essentials.I18n.tl ;
2021-10-11 21:54:55 +02:00
public class JDADiscordService implements DiscordService , IEssentialsModule {
2022-06-27 20:54:10 +02:00
private final static Logger logger = EssentialsDiscord . getWrappedLogger ( ) ;
2021-07-01 15:43:35 +02:00
private final EssentialsDiscord plugin ;
private final Unsafe unsafe = this : : getJda ;
private JDA jda ;
private Guild guild ;
private TextChannel primaryChannel ;
private WebhookClient consoleWebhook ;
private String lastConsoleId ;
private final Map < String , MessageType > registeredTypes = new HashMap < > ( ) ;
private final Map < MessageType , String > typeToChannelId = new HashMap < > ( ) ;
private final Map < String , WebhookClient > channelIdToWebhook = new HashMap < > ( ) ;
private ConsoleInjector injector ;
private DiscordCommandDispatcher commandDispatcher ;
private InteractionControllerImpl interactionController ;
2023-05-01 03:30:11 +02:00
private Listener chatListener ;
2021-07-03 20:17:32 +02:00
private boolean invalidStartup = false ;
2021-07-01 15:43:35 +02:00
public JDADiscordService ( EssentialsDiscord plugin ) {
this . plugin = plugin ;
for ( final MessageType type : MessageType . DefaultTypes . values ( ) ) {
registerMessageType ( plugin , type ) ;
}
}
public TextChannel getChannel ( String key , boolean primaryFallback ) {
2021-10-11 21:54:55 +02:00
if ( NumberUtil . isLong ( key ) ) {
return getDefinedChannel ( key , primaryFallback ) ;
2021-07-01 15:43:35 +02:00
}
2021-10-11 21:54:55 +02:00
return getDefinedChannel ( getSettings ( ) . getMessageChannel ( key ) , primaryFallback ) ;
}
public TextChannel getDefinedChannel ( String key , boolean primaryFallback ) {
final long resolvedId = getSettings ( ) . getChannelId ( key ) ;
2021-07-01 15:43:35 +02:00
if ( isDebug ( ) ) {
logger . log ( Level . INFO , " Channel definition " + key + " resolved as " + resolvedId ) ;
}
TextChannel channel = guild . getTextChannelById ( resolvedId ) ;
if ( channel = = null & & primaryFallback ) {
if ( isDebug ( ) ) {
logger . log ( Level . WARNING , " Resolved channel id " + resolvedId + " was not found! Falling back to primary channel. " ) ;
}
channel = primaryChannel ;
}
return channel ;
}
public WebhookMessage getWebhookMessage ( String message ) {
return getWebhookMessage ( message , jda . getSelfUser ( ) . getAvatarUrl ( ) , getSettings ( ) . getConsoleWebhookName ( ) , false ) ;
}
public WebhookMessage getWebhookMessage ( String message , String avatarUrl , String name , boolean groupMentions ) {
return new WebhookMessageBuilder ( )
. setAvatarUrl ( avatarUrl )
. setAllowedMentions ( groupMentions ? DiscordUtil . ALL_MENTIONS_WEBHOOK : DiscordUtil . NO_GROUP_MENTIONS_WEBHOOK )
. setUsername ( name )
. setContent ( message )
. build ( ) ;
}
public void sendMessage ( DiscordMessageEvent event , String message , boolean groupMentions ) {
final TextChannel channel = getChannel ( event . getType ( ) . getKey ( ) , true ) ;
final String strippedContent = FormatUtil . stripFormat ( message ) ;
final String webhookChannelId = typeToChannelId . get ( event . getType ( ) ) ;
if ( webhookChannelId ! = null ) {
final WebhookClient client = channelIdToWebhook . get ( webhookChannelId ) ;
if ( client ! = null ) {
final String avatarUrl = event . getAvatarUrl ( ) ! = null ? event . getAvatarUrl ( ) : jda . getSelfUser ( ) . getAvatarUrl ( ) ;
final String name = event . getName ( ) ! = null ? event . getName ( ) : guild . getSelfMember ( ) . getEffectiveName ( ) ;
client . send ( getWebhookMessage ( strippedContent , avatarUrl , name , groupMentions ) ) ;
return ;
}
}
if ( ! channel . canTalk ( ) ) {
logger . warning ( tl ( " discordNoSendPermission " , channel . getName ( ) ) ) ;
return ;
}
channel . sendMessage ( strippedContent )
. allowedMentions ( groupMentions ? null : DiscordUtil . NO_GROUP_MENTIONS )
. queue ( ) ;
}
public void startup ( ) throws LoginException , InterruptedException {
shutdown ( ) ;
2021-11-25 17:54:14 +01:00
invalidStartup = true ;
2021-07-01 15:43:35 +02:00
logger . log ( Level . INFO , tl ( " discordLoggingIn " ) ) ;
if ( plugin . getSettings ( ) . getBotToken ( ) . replace ( " INSERT-TOKEN-HERE " , " " ) . trim ( ) . isEmpty ( ) ) {
throw new IllegalArgumentException ( tl ( " discordErrorNoToken " ) ) ;
}
jda = JDABuilder . createDefault ( plugin . getSettings ( ) . getBotToken ( ) )
. addEventListeners ( new DiscordListener ( this ) )
2021-10-11 21:54:55 +02:00
. enableCache ( CacheFlag . EMOTE )
. disableCache ( CacheFlag . MEMBER_OVERRIDES , CacheFlag . VOICE_STATE )
2021-07-01 15:43:35 +02:00
. setContextEnabled ( false )
. build ( )
. awaitReady ( ) ;
2021-11-25 17:54:14 +01:00
invalidStartup = false ;
2021-07-01 15:43:35 +02:00
updatePresence ( ) ;
logger . log ( Level . INFO , tl ( " discordLoggingInDone " , jda . getSelfUser ( ) . getAsTag ( ) ) ) ;
if ( jda . getGuilds ( ) . isEmpty ( ) ) {
2021-07-03 20:17:32 +02:00
invalidStartup = true ;
2021-07-01 15:43:35 +02:00
throw new IllegalArgumentException ( tl ( " discordErrorNoGuildSize " ) ) ;
}
guild = jda . getGuildById ( plugin . getSettings ( ) . getGuildId ( ) ) ;
if ( guild = = null ) {
2021-07-03 20:17:32 +02:00
invalidStartup = true ;
2021-07-01 15:43:35 +02:00
throw new IllegalArgumentException ( tl ( " discordErrorNoGuild " ) ) ;
}
interactionController = new InteractionControllerImpl ( this ) ;
2021-07-04 21:42:05 +02:00
// Each will throw an exception if disabled
2021-07-01 15:43:35 +02:00
try {
interactionController . registerCommand ( new ExecuteCommand ( this ) ) ;
2021-07-04 21:42:05 +02:00
} catch ( InteractionException ignored ) {
}
try {
2021-07-01 15:43:35 +02:00
interactionController . registerCommand ( new MessageCommand ( this ) ) ;
2021-07-04 21:42:05 +02:00
} catch ( InteractionException ignored ) {
}
try {
2021-07-01 15:43:35 +02:00
interactionController . registerCommand ( new ListCommand ( this ) ) ;
} catch ( InteractionException ignored ) {
}
2021-10-11 21:54:55 +02:00
// Load emotes into cache, JDA will handle updates from here on out.
guild . retrieveEmotes ( ) . queue ( ) ;
2021-07-01 15:43:35 +02:00
updatePrimaryChannel ( ) ;
updateConsoleRelay ( ) ;
updateTypesRelay ( ) ;
2021-07-28 22:25:47 +02:00
// We will see you in the future :balloon:
// DiscordUtil.cleanWebhooks(guild, DiscordUtil.CONSOLE_RELAY_NAME);
// DiscordUtil.cleanWebhooks(guild, DiscordUtil.ADVANCED_RELAY_NAME);
2021-07-01 15:43:35 +02:00
Bukkit . getPluginManager ( ) . registerEvents ( new BukkitListener ( this ) , plugin ) ;
2021-07-05 03:57:13 +02:00
2023-05-01 03:30:11 +02:00
updateListener ( ) ;
2021-07-05 03:57:13 +02:00
try {
if ( VersionUtil . getServerBukkitVersion ( ) . isHigherThanOrEqualTo ( VersionUtil . v1_12_0_R01 ) ) {
2021-10-24 16:27:07 +02:00
try {
Class . forName ( " io.papermc.paper.advancement.AdvancementDisplay " ) ;
Bukkit . getPluginManager ( ) . registerEvents ( new PaperAdvancementListenerProvider ( ) , plugin ) ;
} catch ( ClassNotFoundException e ) {
Bukkit . getPluginManager ( ) . registerEvents ( new AdvancementListenerProvider ( ) , plugin ) ;
}
2021-07-05 03:57:13 +02:00
} else {
Bukkit . getPluginManager ( ) . registerEvents ( new AchievementListenerProvider ( ) , plugin ) ;
}
} catch ( final Throwable e ) {
logger . log ( Level . WARNING , " Error while loading the achievement/advancement listener. You will not receive achievement/advancement notifications on Discord. " , e ) ;
}
2021-07-01 20:50:34 +02:00
getPlugin ( ) . getEss ( ) . scheduleSyncDelayedTask ( ( ) - > DiscordUtil . dispatchDiscordMessage ( JDADiscordService . this , MessageType . DefaultTypes . SERVER_START , getSettings ( ) . getStartMessage ( ) , true , null , null , null ) ) ;
2021-07-01 15:43:35 +02:00
Bukkit . getServicesManager ( ) . register ( DiscordService . class , this , plugin , ServicePriority . Normal ) ;
}
@Override
public boolean isRegistered ( String key ) {
return registeredTypes . containsKey ( key ) ;
}
@Override
public void registerMessageType ( Plugin plugin , MessageType type ) {
2021-07-28 22:51:27 +02:00
if ( ! type . getKey ( ) . matches ( " ^[a-z][a-z0-9-]*$ " ) ) {
throw new IllegalArgumentException ( " MessageType key must match \" ^[a-z][a-z0-9-]*$ \" " ) ;
2021-07-01 15:43:35 +02:00
}
if ( registeredTypes . containsKey ( type . getKey ( ) ) ) {
throw new IllegalArgumentException ( " A MessageType with that key is already registered! " ) ;
}
registeredTypes . put ( type . getKey ( ) , type ) ;
}
@Override
public void sendMessage ( MessageType type , String message , boolean allowGroupMentions ) {
2022-06-07 20:04:46 +02:00
if ( ! registeredTypes . containsKey ( type . getKey ( ) ) & & ! NumberUtil . isLong ( type . getKey ( ) ) ) {
2021-07-01 15:43:35 +02:00
logger . warning ( " Sending message to channel \" " + type . getKey ( ) + " \" which is an unregistered type! If you are a plugin author, you should be registering your MessageType before using them. " ) ;
}
final DiscordMessageEvent event = new DiscordMessageEvent ( type , FormatUtil . stripFormat ( message ) , allowGroupMentions ) ;
if ( Bukkit . getServer ( ) . isPrimaryThread ( ) ) {
Bukkit . getPluginManager ( ) . callEvent ( event ) ;
} else {
Bukkit . getScheduler ( ) . runTask ( plugin , ( ) - > Bukkit . getPluginManager ( ) . callEvent ( event ) ) ;
}
}
2021-08-07 23:22:12 +02:00
@Override
public void sendChatMessage ( final Player player , final String chatMessage ) {
2023-05-01 03:30:11 +02:00
sendChatMessage ( ChatType . UNKNOWN , player , chatMessage ) ;
}
@Override
public void sendChatMessage ( ChatType chatType , Player player , String chatMessage ) {
2021-08-07 23:22:12 +02:00
final User user = getPlugin ( ) . getEss ( ) . getUser ( player ) ;
2023-05-01 03:30:11 +02:00
final String formattedMessage = MessageUtil . formatMessage ( getSettings ( ) . getMcToDiscordFormat ( player , chatType ) ,
2021-08-07 23:22:12 +02:00
MessageUtil . sanitizeDiscordMarkdown ( player . getName ( ) ) ,
MessageUtil . sanitizeDiscordMarkdown ( player . getDisplayName ( ) ) ,
user . isAuthorized ( " essentials.discord.markdown " ) ? chatMessage : MessageUtil . sanitizeDiscordMarkdown ( chatMessage ) ,
2021-08-09 20:57:03 +02:00
MessageUtil . sanitizeDiscordMarkdown ( getPlugin ( ) . getEss ( ) . getSettings ( ) . getWorldAlias ( player . getWorld ( ) . getName ( ) ) ) ,
2021-08-07 23:22:12 +02:00
MessageUtil . sanitizeDiscordMarkdown ( FormatUtil . stripEssentialsFormat ( getPlugin ( ) . getEss ( ) . getPermissionsHandler ( ) . getPrefix ( player ) ) ) ,
MessageUtil . sanitizeDiscordMarkdown ( FormatUtil . stripEssentialsFormat ( getPlugin ( ) . getEss ( ) . getPermissionsHandler ( ) . getSuffix ( player ) ) ) ) ;
2021-08-09 21:48:43 +02:00
final String avatarUrl = DiscordUtil . getAvatarUrl ( this , player ) ;
2021-08-07 23:22:12 +02:00
2023-04-10 02:27:36 +02:00
final String formattedName = MessageUtil . formatMessage ( getSettings ( ) . getMcToDiscordNameFormat ( player ) ,
2023-04-13 08:15:48 +02:00
player . getName ( ) ,
player . getDisplayName ( ) ,
getPlugin ( ) . getEss ( ) . getSettings ( ) . getWorldAlias ( player . getWorld ( ) . getName ( ) ) ,
FormatUtil . stripEssentialsFormat ( getPlugin ( ) . getEss ( ) . getPermissionsHandler ( ) . getPrefix ( player ) ) ,
FormatUtil . stripEssentialsFormat ( getPlugin ( ) . getEss ( ) . getPermissionsHandler ( ) . getSuffix ( player ) ) ,
2023-04-10 02:27:36 +02:00
guild . getMember ( jda . getSelfUser ( ) ) . getEffectiveName ( ) ) ;
2023-05-01 03:30:11 +02:00
DiscordUtil . dispatchDiscordMessage ( this , chatTypeToMessageType ( chatType ) , formattedMessage , user . isAuthorized ( " essentials.discord.ping " ) , avatarUrl , formattedName , player . getUniqueId ( ) ) ;
}
private MessageType chatTypeToMessageType ( ChatType chatType ) {
switch ( chatType ) {
case SHOUT :
return MessageType . DefaultTypes . SHOUT ;
case QUESTION :
return MessageType . DefaultTypes . QUESTION ;
case LOCAL :
return MessageType . DefaultTypes . LOCAL ;
default :
return MessageType . DefaultTypes . CHAT ;
}
2021-08-07 23:22:12 +02:00
}
2021-07-01 15:43:35 +02:00
@Override
public InteractionController getInteractionController ( ) {
return interactionController ;
}
public void updatePrimaryChannel ( ) {
TextChannel channel = guild . getTextChannelById ( plugin . getSettings ( ) . getPrimaryChannelId ( ) ) ;
if ( channel = = null ) {
channel = guild . getDefaultChannel ( ) ;
2021-10-20 14:09:56 +02:00
if ( channel = = null ) {
2021-07-01 15:43:35 +02:00
throw new RuntimeException ( tl ( " discordErrorNoPerms " ) ) ;
}
2021-10-20 14:09:56 +02:00
logger . warning ( tl ( " discordErrorNoPrimary " , channel . getName ( ) ) ) ;
}
if ( ! channel . canTalk ( ) ) {
throw new RuntimeException ( tl ( " discordErrorNoPrimaryPerms " , channel . getName ( ) ) ) ;
2021-07-01 15:43:35 +02:00
}
primaryChannel = channel ;
}
2021-10-11 21:54:55 +02:00
public String parseMessageEmotes ( String message ) {
for ( final Emote emote : guild . getEmoteCache ( ) ) {
message = message . replaceAll ( " : " + Pattern . quote ( emote . getName ( ) ) + " : " , emote . getAsMention ( ) ) ;
}
return message ;
}
2023-05-01 03:30:11 +02:00
public void updateListener ( ) {
if ( chatListener ! = null ) {
HandlerList . unregisterAll ( chatListener ) ;
chatListener = null ;
}
chatListener = getSettings ( ) . isUseEssentialsEvents ( ) & & plugin . isEssentialsChat ( )
? new EssentialsChatListener ( this )
: new BukkitChatListener ( this ) ;
Bukkit . getPluginManager ( ) . registerEvents ( chatListener , plugin ) ;
}
2021-07-01 15:43:35 +02:00
public void updatePresence ( ) {
jda . getPresence ( ) . setPresence ( plugin . getSettings ( ) . getStatus ( ) , plugin . getSettings ( ) . getStatusActivity ( ) ) ;
}
public void updateTypesRelay ( ) {
2021-07-08 23:15:45 +02:00
if ( ! getSettings ( ) . isShowAvatar ( ) & & ! getSettings ( ) . isShowName ( ) & & ! getSettings ( ) . isShowDisplayName ( ) ) {
2021-07-01 15:43:35 +02:00
for ( WebhookClient webhook : channelIdToWebhook . values ( ) ) {
webhook . close ( ) ;
}
typeToChannelId . clear ( ) ;
channelIdToWebhook . clear ( ) ;
return ;
}
for ( MessageType type : MessageType . DefaultTypes . values ( ) ) {
if ( ! type . isPlayer ( ) ) {
continue ;
}
final TextChannel channel = getChannel ( type . getKey ( ) , true ) ;
if ( channel . getId ( ) . equals ( typeToChannelId . get ( type ) ) ) {
continue ;
}
2021-07-28 22:25:47 +02:00
final Webhook webhook = DiscordUtil . getOrCreateWebhook ( channel , DiscordUtil . ADVANCED_RELAY_NAME ) . join ( ) ;
2021-07-01 15:43:35 +02:00
if ( webhook = = null ) {
final WebhookClient current = channelIdToWebhook . get ( channel . getId ( ) ) ;
if ( current ! = null ) {
current . close ( ) ;
}
2022-11-27 20:29:36 +01:00
channelIdToWebhook . remove ( channel . getId ( ) ) . close ( ) ;
2021-07-01 15:43:35 +02:00
continue ;
}
typeToChannelId . put ( type , channel . getId ( ) ) ;
channelIdToWebhook . put ( channel . getId ( ) , DiscordUtil . getWebhookClient ( webhook . getIdLong ( ) , webhook . getToken ( ) , jda . getHttpClient ( ) ) ) ;
}
}
public void updateConsoleRelay ( ) {
final String consoleDef = getSettings ( ) . getConsoleChannelDef ( ) ;
final Matcher matcher = WebhookClientBuilder . WEBHOOK_PATTERN . matcher ( consoleDef ) ;
final long webhookId ;
final String webhookToken ;
if ( matcher . matches ( ) ) {
webhookId = Long . parseUnsignedLong ( matcher . group ( 1 ) ) ;
webhookToken = matcher . group ( 2 ) ;
if ( commandDispatcher ! = null ) {
jda . removeEventListener ( commandDispatcher ) ;
commandDispatcher = null ;
}
} else {
final TextChannel channel = getChannel ( consoleDef , false ) ;
if ( channel ! = null ) {
if ( getSettings ( ) . isConsoleCommandRelay ( ) ) {
if ( commandDispatcher = = null ) {
commandDispatcher = new DiscordCommandDispatcher ( this ) ;
jda . addEventListener ( commandDispatcher ) ;
}
commandDispatcher . setChannelId ( channel . getId ( ) ) ;
} else if ( commandDispatcher ! = null ) {
jda . removeEventListener ( commandDispatcher ) ;
commandDispatcher = null ;
}
if ( channel . getId ( ) . equals ( lastConsoleId ) ) {
return ;
}
2021-07-28 22:25:47 +02:00
final Webhook webhook = DiscordUtil . getOrCreateWebhook ( channel , DiscordUtil . CONSOLE_RELAY_NAME ) . join ( ) ;
2021-07-01 15:43:35 +02:00
if ( webhook = = null ) {
logger . info ( tl ( " discordErrorLoggerNoPerms " ) ) ;
return ;
}
webhookId = webhook . getIdLong ( ) ;
webhookToken = webhook . getToken ( ) ;
lastConsoleId = channel . getId ( ) ;
} else if ( ! getSettings ( ) . getConsoleChannelDef ( ) . equals ( " none " ) & & ! getSettings ( ) . getConsoleChannelDef ( ) . startsWith ( " 0 " ) ) {
logger . info ( tl ( " discordErrorLoggerInvalidChannel " ) ) ;
shutdownConsoleRelay ( true ) ;
return ;
} else {
// It's either not configured at all or knowingly disabled.
shutdownConsoleRelay ( true ) ;
return ;
}
}
shutdownConsoleRelay ( false ) ;
consoleWebhook = DiscordUtil . getWebhookClient ( webhookId , webhookToken , jda . getHttpClient ( ) ) ;
2022-11-12 00:28:55 +01:00
if ( injector = = null | | injector . isRemoved ( ) ) {
2021-07-01 15:43:35 +02:00
injector = new ConsoleInjector ( this ) ;
injector . start ( ) ;
}
}
private void shutdownConsoleRelay ( final boolean closeInjector ) {
if ( consoleWebhook ! = null & & ! consoleWebhook . isShutdown ( ) ) {
consoleWebhook . close ( ) ;
}
consoleWebhook = null ;
if ( closeInjector ) {
if ( injector ! = null ) {
injector . remove ( ) ;
injector = null ;
}
if ( commandDispatcher ! = null ) {
jda . removeEventListener ( commandDispatcher ) ;
commandDispatcher = null ;
}
}
}
public void shutdown ( ) {
if ( interactionController ! = null ) {
interactionController . shutdown ( ) ;
}
if ( jda ! = null ) {
2021-07-03 20:17:32 +02:00
if ( ! invalidStartup ) {
sendMessage ( MessageType . DefaultTypes . SERVER_STOP , getSettings ( ) . getStopMessage ( ) , true ) ;
DiscordUtil . dispatchDiscordMessage ( JDADiscordService . this , MessageType . DefaultTypes . SERVER_STOP , getSettings ( ) . getStopMessage ( ) , true , null , null , null ) ;
}
2021-07-01 20:50:34 +02:00
2021-07-01 15:43:35 +02:00
shutdownConsoleRelay ( true ) ;
2022-11-27 20:29:36 +01:00
for ( WebhookClient webhook : channelIdToWebhook . values ( ) ) {
webhook . close ( ) ;
}
2021-07-01 15:43:35 +02:00
// Unregister leftover jda listeners
for ( Object obj : jda . getRegisteredListeners ( ) ) {
if ( ! ( obj instanceof EventListener ) ) { // Yeah bro I wish I knew too :/
jda . removeEventListener ( obj ) ;
}
}
// Unregister Bukkit Events
HandlerList . unregisterAll ( plugin ) ;
// Creates a future which will be completed when JDA fully shutdowns
final CompletableFuture < Void > future = new CompletableFuture < > ( ) ;
jda . addEventListener ( new ListenerAdapter ( ) {
@Override
public void onShutdown ( @NotNull ShutdownEvent event ) {
future . complete ( null ) ;
}
} ) ;
// Tell JDA to wrap it up
jda . shutdown ( ) ;
try {
// Wait for JDA to wrap it up
future . get ( 5 , TimeUnit . SECONDS ) ;
} catch ( InterruptedException | ExecutionException | TimeoutException e ) {
logger . warning ( " JDA took longer than expected to shutdown, this may have caused some problems. " ) ;
} finally {
jda = null ;
}
}
}
2022-12-25 22:13:56 +01:00
@Override
public CompletableFuture < InteractionMember > getMemberById ( final String id ) {
final CompletableFuture < InteractionMember > future = new CompletableFuture < > ( ) ;
getGuild ( ) . retrieveMemberById ( id ) . queue ( member - > {
if ( member ! = null ) {
future . complete ( new InteractionMemberImpl ( member ) ) ;
return ;
}
future . complete ( null ) ;
} , fail - > future . complete ( null ) ) ;
return future ;
}
2021-08-04 05:19:56 +02:00
@Override
public InteractionRole getRole ( String id ) {
final Role role = getGuild ( ) . getRoleById ( id ) ;
return role = = null ? null : new InteractionRoleImpl ( role ) ;
}
@Override
public CompletableFuture < Void > modifyMemberRoles ( InteractionMember member , Collection < InteractionRole > addRoles , Collection < InteractionRole > removeRoles ) {
if ( ( addRoles = = null | | addRoles . isEmpty ( ) ) & & ( removeRoles = = null | | removeRoles . isEmpty ( ) ) ) {
return CompletableFuture . completedFuture ( null ) ;
}
final List < Role > add = new ArrayList < > ( ) ;
final List < Role > remove = new ArrayList < > ( ) ;
if ( addRoles ! = null ) {
for ( final InteractionRole role : addRoles ) {
add . add ( ( ( InteractionRoleImpl ) role ) . getJdaObject ( ) ) ;
}
}
if ( removeRoles ! = null ) {
for ( final InteractionRole role : removeRoles ) {
remove . add ( ( ( InteractionRoleImpl ) role ) . getJdaObject ( ) ) ;
}
}
final CompletableFuture < Void > future = new CompletableFuture < > ( ) ;
guild . modifyMemberRoles ( ( ( InteractionMemberImpl ) member ) . getJdaObject ( ) , add , remove ) . queue ( future : : complete ) ;
return future ;
}
2022-12-25 22:26:34 +01:00
@Override
public String getInviteUrl ( ) {
return getSettings ( ) . getDiscordUrl ( ) ;
}
2021-07-01 15:43:35 +02:00
public JDA getJda ( ) {
return jda ;
}
@Override
public Unsafe getUnsafe ( ) {
return unsafe ;
}
public Guild getGuild ( ) {
return guild ;
}
public EssentialsDiscord getPlugin ( ) {
return plugin ;
}
public DiscordSettings getSettings ( ) {
return plugin . getSettings ( ) ;
}
public WebhookClient getConsoleWebhook ( ) {
return consoleWebhook ;
}
2021-07-03 20:17:32 +02:00
public boolean isInvalidStartup ( ) {
return invalidStartup ;
}
2021-07-01 15:43:35 +02:00
public boolean isDebug ( ) {
return plugin . getEss ( ) . getSettings ( ) . isDebug ( ) ;
}
}