Fix even more returns and Discord->MC chat

This commit is contained in:
Norbi Peti 2021-12-31 00:38:28 +01:00
parent 9f3ca37929
commit cafd8096fa
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
7 changed files with 47 additions and 64 deletions

View file

@ -53,17 +53,10 @@ object DPUtils {
private def escape(message: String) = { //var ts = new TreeSet<>(); private def escape(message: String) = { //var ts = new TreeSet<>();
val ts = new util.TreeSet[Array[Int]](Comparator.comparingInt((a: Array[Int]) => a(0)): Comparator[Array[Int]]) //Compare the start, then check the end val ts = new util.TreeSet[Array[Int]](Comparator.comparingInt((a: Array[Int]) => a(0)): Comparator[Array[Int]]) //Compare the start, then check the end
var matcher = URL_PATTERN.matcher(message) var matcher = URL_PATTERN.matcher(message)
while ( { while (matcher.find) ts.add(Array[Int](matcher.start, matcher.end))
matcher.find
}) ts.add(Array[Int](matcher.start, matcher.end))
matcher = FORMAT_PATTERN.matcher(message) matcher = FORMAT_PATTERN.matcher(message)
/*Function<MatchResult, String> aFunctionalInterface = result -> val sb = new StringBuffer
Optional.ofNullable(ts.floor(new int[]{result.start(), 0})).map(a -> a[1]).orElse(0) < result.start() while (matcher.find) matcher.appendReplacement(sb, if (Option(ts.floor(Array[Int](matcher.start, 0))).map( //Find a URL start <= our start
? "\\\\" + result.group() : result.group();
return matcher.replaceAll(aFunctionalInterface); //Find nearest URL match and if it's not reaching to the char then escape*/ val sb = new StringBuffer
while ( {
matcher.find
}) matcher.appendReplacement(sb, if (Option(ts.floor(Array[Int](matcher.start, 0))).map( //Find a URL start <= our start
(a: Array[Int]) => a(1)).getOrElse(-1) < matcher.start //Check if URL end < our start (a: Array[Int]) => a(1)).getOrElse(-1) < matcher.start //Check if URL end < our start
) "\\\\" + matcher.group else matcher.group) ) "\\\\" + matcher.group else matcher.group)
matcher.appendTail(sb) matcher.appendTail(sb)
@ -71,13 +64,14 @@ object DPUtils {
} }
def getLogger: Logger = { def getLogger: Logger = {
if (DiscordPlugin.plugin == null || DiscordPlugin.plugin.getLogger == null) return Logger.getLogger("DiscordPlugin") if (DiscordPlugin.plugin == null || DiscordPlugin.plugin.getLogger == null) Logger.getLogger("DiscordPlugin")
DiscordPlugin.plugin.getLogger else DiscordPlugin.plugin.getLogger
} }
def channelData(config: IHaveConfig, key: String): ReadOnlyConfigData[SMono[MessageChannel]] = def channelData(config: IHaveConfig, key: String): ReadOnlyConfigData[SMono[MessageChannel]] =
config.getReadOnlyDataPrimDef(key, 0L, (id: Any) => config.getReadOnlyDataPrimDef(key, 0L, (id: Any) =>
getMessageChannel(key, Snowflake.of(id.asInstanceOf[Long])), (_: SMono[MessageChannel]) => 0L) //We can afford to search for the channel in the cache once (instead of using mainServer) getMessageChannel(key, Snowflake.of(id.asInstanceOf[Long])), (_: SMono[MessageChannel]) => 0L) //We can afford to search for the channel in the cache once (instead of using mainServer)
def roleData(config: IHaveConfig, key: String, defName: String): ReadOnlyConfigData[SMono[Role]] = def roleData(config: IHaveConfig, key: String, defName: String): ReadOnlyConfigData[SMono[Role]] =
roleData(config, key, defName, SMono.just(DiscordPlugin.mainServer)) roleData(config, key, defName, SMono.just(DiscordPlugin.mainServer))

View file

@ -42,8 +42,8 @@ import java.util.Optional
private[discordplugin] var SafeMode = true private[discordplugin] var SafeMode = true
def getPrefix: Char = { def getPrefix: Char = {
if (plugin == null) return '/' if (plugin == null) '/'
plugin.prefix.get else plugin.prefix.get
} }
private[discordplugin] var mainServer: Guild = null private[discordplugin] var mainServer: Guild = null
@ -174,7 +174,7 @@ import java.util.Optional
getLogger.severe("Main server not found! Invite the bot and do /discord restart") getLogger.severe("Main server not found! Invite the bot and do /discord restart")
DiscordPlugin.dc.getApplicationInfo.subscribe((info: ApplicationInfo) => getLogger.severe("Click here: https://discordapp.com/oauth2/authorize?client_id=" + info.getId.asString + "&scope=bot&permissions=268509264")) DiscordPlugin.dc.getApplicationInfo.subscribe((info: ApplicationInfo) => getLogger.severe("Click here: https://discordapp.com/oauth2/authorize?client_id=" + info.getId.asString + "&scope=bot&permissions=268509264"))
saveConfig() //Put default there saveConfig() //Put default there
return //We should have all guilds by now, no need to retry return () //We should have all guilds by now, no need to retry
} }
DiscordPlugin.mainServer = event.get(0).getGuild DiscordPlugin.mainServer = event.get(0).getGuild
getLogger.warning("Main server set to first one: " + DiscordPlugin.mainServer.getName) getLogger.warning("Main server set to first one: " + DiscordPlugin.mainServer.getName)
@ -186,7 +186,7 @@ import java.util.Optional
//Won't disable, just prints the warning here //Won't disable, just prints the warning here
if (MinecraftChatModule.state eq DPState.STOPPING_SERVER) { if (MinecraftChatModule.state eq DPState.STOPPING_SERVER) {
stopStarting() stopStarting()
return //Reusing that field to check if stopping while still initializing return () //Reusing that field to check if stopping while still initializing
} }
CommonListeners.register(DiscordPlugin.dc.getEventDispatcher) CommonListeners.register(DiscordPlugin.dc.getEventDispatcher)
TBMCCoreAPI.RegisterEventsForExceptions(new MCListener, this) TBMCCoreAPI.RegisterEventsForExceptions(new MCListener, this)
@ -236,7 +236,7 @@ import java.util.Optional
e.printStackTrace() e.printStackTrace()
} }
} }
if (!ChromaBot.enabled) return //Failed to load if (!ChromaBot.enabled) return () //Failed to load
val timings = new Timings val timings = new Timings
timings.printElapsed("Disable start") timings.printElapsed("Disable start")
timings.printElapsed("Updating player list") timings.printElapsed("Updating player list")

View file

@ -27,8 +27,8 @@ class DiscordSender(user: User, channel: MessageChannel, pname: String) extends
override def isPermissionSet(perm: Permission): Boolean = this.perm.isPermissionSet(perm) override def isPermissionSet(perm: Permission): Boolean = this.perm.isPermissionSet(perm)
override def hasPermission(name: String): Boolean = { override def hasPermission(name: String): Boolean = {
if (name.contains("essentials") && !(name == "essentials.list")) return false if (name.contains("essentials") && !(name == "essentials.list")) false
perm.hasPermission(name) else perm.hasPermission(name)
} }
override def hasPermission(perm: Permission): Boolean = this.perm.hasPermission(perm) override def hasPermission(perm: Permission): Boolean = this.perm.hasPermission(perm)

View file

@ -47,14 +47,9 @@ abstract class DiscordSenderBase protected(var user: User, var channel: MessageC
this synchronized { this synchronized {
msgtosend += "\n" + sendmsg msgtosend += "\n" + sendmsg
if (sendtask == null) sendtask = Bukkit.getScheduler.runTaskLaterAsynchronously(DiscordPlugin.plugin, () => { if (sendtask == null) sendtask = Bukkit.getScheduler.runTaskLaterAsynchronously(DiscordPlugin.plugin, () => {
def foo(): Unit = { channel.createMessage((if (user != null) user.getMention + "\n" else "") + msgtosend.trim).subscribe()
channel.createMessage((if (user != null) user.getMention + "\n" sendtask = null
else "") + msgtosend.trim).subscribe() msgtosend = ""
sendtask = null
msgtosend = ""
}
foo()
}, 4) // Waits a 0.2 second to gather all/most of the different messages }, 4) // Waits a 0.2 second to gather all/most of the different messages
} }
} catch { } catch {

View file

@ -7,11 +7,13 @@ import buttondevteam.discordplugin.util.Timings
import buttondevteam.discordplugin.{DPUtils, DiscordPlugin} import buttondevteam.discordplugin.{DPUtils, DiscordPlugin}
import buttondevteam.lib.TBMCCoreAPI import buttondevteam.lib.TBMCCoreAPI
import buttondevteam.lib.architecture.Component import buttondevteam.lib.architecture.Component
import discord4j.core.`object`.entity.Message
import discord4j.core.`object`.entity.channel.{MessageChannel, PrivateChannel} import discord4j.core.`object`.entity.channel.{MessageChannel, PrivateChannel}
import discord4j.core.event.EventDispatcher import discord4j.core.event.EventDispatcher
import discord4j.core.event.domain.PresenceUpdateEvent import discord4j.core.event.domain.PresenceUpdateEvent
import discord4j.core.event.domain.message.MessageCreateEvent import discord4j.core.event.domain.message.MessageCreateEvent
import discord4j.core.event.domain.role.{RoleCreateEvent, RoleDeleteEvent, RoleUpdateEvent} import discord4j.core.event.domain.role.{RoleCreateEvent, RoleDeleteEvent, RoleUpdateEvent}
import reactor.core.Disposable
import reactor.core.scala.publisher.{SFlux, SMono} import reactor.core.scala.publisher.{SFlux, SMono}
object CommonListeners { object CommonListeners {
@ -26,44 +28,20 @@ object CommonListeners {
- Minecraft chat (is enabled in the channel and message isn't [/]mcchat) - Minecraft chat (is enabled in the channel and message isn't [/]mcchat)
- CommandListener (with the correct prefix in #bot, or in private) - CommandListener (with the correct prefix in #bot, or in private)
*/ */
def register(dispatcher: EventDispatcher) = { def register(dispatcher: EventDispatcher): Unit = {
dispatcher.on(classOf[MessageCreateEvent]).flatMap((event: MessageCreateEvent) => { dispatcher.on(classOf[MessageCreateEvent]).flatMap((event: MessageCreateEvent) => {
def foo(event: MessageCreateEvent): SMono[Boolean] = { SMono.just(event.getMessage).filter(_ => !DiscordPlugin.SafeMode)
timings.printElapsed("Message received") .filter(message => message.getAuthor.filter(!_.isBot).isPresent)
val `def` = SMono.empty .filter(message => !FunModule.executeMemes(message))
if (DiscordPlugin.SafeMode) return `def` .flatMap(handleMessage(event))
val author = event.getMessage.getAuthor }).onErrorContinue((err, _) => TBMCCoreAPI.SendException("An error occured while handling a message!", err, DiscordPlugin.plugin)).subscribe()
if (!author.isPresent || author.get.isBot) return `def`
if (FunModule.executeMemes(event.getMessage)) return `def`
val commandChannel = DiscordPlugin.plugin.commandChannel.get
SMono(event.getMessage.getChannel).map((mch: MessageChannel) => (commandChannel != null && mch.getId.asLong == commandChannel.asLong) //If mentioned, that's higher than chat
|| mch.isInstanceOf[PrivateChannel] || event.getMessage.getContent.contains("channelcon")).flatMap(
(shouldRun: Boolean) => { //Only 'channelcon' is allowed in other channels
def foo(shouldRun: Boolean): SMono[Boolean] = { //Only continue if this doesn't handle the event
if (!shouldRun) return SMono.just(true) //The condition is only for the first command execution, not mcchat
CommandListener.runCommand(event.getMessage, commandChannel, mentionedonly = true) //#bot is handled here
}
foo(shouldRun)
}).filterWhen(_ => {
timings.printElapsed("mcchat")
val mcchat = Component.getComponents.get(classOf[MinecraftChatModule])
if (mcchat != null && mcchat.isEnabled) { //ComponentManager.isEnabled() searches the component again
return mcchat.asInstanceOf[MinecraftChatModule].getListener.handleDiscord(event) //Also runs Discord commands in chat channels
}
SMono.just(true) //Wasn't handled, continue
}).filterWhen(_ => CommandListener.runCommand(event.getMessage, commandChannel, mentionedonly = false))
}
foo(event)
}).onErrorContinue((err: Throwable, _) => TBMCCoreAPI.SendException("An error occured while handling a message!", err, DiscordPlugin.plugin)).subscribe()
dispatcher.on(classOf[PresenceUpdateEvent]).subscribe((event: PresenceUpdateEvent) => { dispatcher.on(classOf[PresenceUpdateEvent]).subscribe((event: PresenceUpdateEvent) => {
if (!DiscordPlugin.SafeMode) if (!DiscordPlugin.SafeMode)
FunModule.handleFullHouse(event) FunModule.handleFullHouse(event)
}) })
SFlux(dispatcher.on(classOf[RoleCreateEvent])).subscribe(GameRoleModule.handleRoleEvent _) SFlux(dispatcher.on(classOf[RoleCreateEvent])).subscribe(GameRoleModule.handleRoleEvent)
SFlux(dispatcher.on(classOf[RoleDeleteEvent])).subscribe(GameRoleModule.handleRoleEvent _) SFlux(dispatcher.on(classOf[RoleDeleteEvent])).subscribe(GameRoleModule.handleRoleEvent)
SFlux(dispatcher.on(classOf[RoleUpdateEvent])).subscribe(GameRoleModule.handleRoleEvent _) SFlux(dispatcher.on(classOf[RoleUpdateEvent])).subscribe(GameRoleModule.handleRoleEvent)
} }
var debug = false var debug = false
@ -71,4 +49,20 @@ object CommonListeners {
def debug(debug: String): Unit = if (CommonListeners.debug) { //Debug def debug(debug: String): Unit = if (CommonListeners.debug) { //Debug
DPUtils.getLogger.info(debug) DPUtils.getLogger.info(debug)
} }
private def handleMessage(event: MessageCreateEvent) = {
(message: Message) => {
val commandChannel = Option(DiscordPlugin.plugin.commandChannel.get)
SMono(message.getChannel).filter(mch => commandChannel.isDefined && mch.getId.asLong() == commandChannel.get.asLong() //If mentioned, that's higher than chat
|| mch.isInstanceOf[PrivateChannel] || message.getContent.contains("channelcon")).flatMap(_ => { //Only 'channelcon' is allowed in other channels
//Only continue if this doesn't handle the event
CommandListener.runCommand(message, commandChannel.get, mentionedonly = true) //#bot is handled here
}).`then`(SMono.just(true)) //The condition is only for the first command execution, not mcchat
.filterWhen(_ => {
Option(Component.getComponents.get(classOf[MinecraftChatModule])).filter(_.isEnabled)
.map(_.asInstanceOf[MinecraftChatModule].getListener.handleDiscord(event)) //Also runs Discord commands in chat channels
.getOrElse(SMono.just(true)) //Wasn't handled, continue
}).filterWhen(_ => CommandListener.runCommand(event.getMessage, commandChannel.get, mentionedonly = false))
}
}
} }

View file

@ -14,14 +14,14 @@ import discord4j.core.`object`.entity.channel.PrivateChannel
)) ))
class MCChatCommand(private val module: MinecraftChatModule) extends ICommand2DC { class MCChatCommand(private val module: MinecraftChatModule) extends ICommand2DC {
@Command2.Subcommand override def `def`(sender: Command2DCSender): Boolean = { @Command2.Subcommand override def `def`(sender: Command2DCSender): Boolean = {
if (!(module.allowPrivateChat.get)) { if (!module.allowPrivateChat.get) {
sender.sendMessage("using the private chat is not allowed on this Minecraft server.") sender.sendMessage("using the private chat is not allowed on this Minecraft server.")
return true return true
} }
val message = sender.getMessage val message = sender.getMessage
val channel = message.getChannel.block val channel = message.getChannel.block
@SuppressWarnings(Array("OptionalGetWithoutIsPresent")) val author = message.getAuthor.get @SuppressWarnings(Array("OptionalGetWithoutIsPresent")) val author = message.getAuthor.get
if (!((channel.isInstanceOf[PrivateChannel]))) { if (!channel.isInstanceOf[PrivateChannel]) {
DPUtils.reply(message, channel, "this command can only be issued in a direct message with the bot.").subscribe() DPUtils.reply(message, channel, "this command can only be issued in a direct message with the bot.").subscribe()
return true return true
} }

View file

@ -28,7 +28,7 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
} }
@EventHandler(priority = EventPriority.MONITOR) def onPlayerJoin(e: PlayerJoinEvent): Unit = { @EventHandler(priority = EventPriority.MONITOR) def onPlayerJoin(e: PlayerJoinEvent): Unit = {
if (e.getPlayer.isInstanceOf[DiscordConnectedPlayer]) return // Don't show the joined message for the fake player if (e.getPlayer.isInstanceOf[DiscordConnectedPlayer]) return () // Don't show the joined message for the fake player
Bukkit.getScheduler.runTaskAsynchronously(DiscordPlugin.plugin, () => { Bukkit.getScheduler.runTaskAsynchronously(DiscordPlugin.plugin, () => {
def foo(): Unit = { def foo(): Unit = {
val p = e.getPlayer val p = e.getPlayer
@ -54,7 +54,7 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), player, ChannelconBroadcast.JOINLEAVE, hookmsg = true).subscribe() MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), player, ChannelconBroadcast.JOINLEAVE, hookmsg = true).subscribe()
@EventHandler(priority = EventPriority.MONITOR) def onPlayerLeave(e: PlayerQuitEvent): Unit = { @EventHandler(priority = EventPriority.MONITOR) def onPlayerLeave(e: PlayerQuitEvent): Unit = {
if (e.getPlayer.isInstanceOf[DiscordConnectedPlayer]) return // Only care about real users if (e.getPlayer.isInstanceOf[DiscordConnectedPlayer]) return () // Only care about real users
MCChatUtils.OnlineSenders.filterInPlace((_, userMap) => userMap.entrySet.stream.noneMatch(_.getValue.getUniqueId.equals(e.getPlayer.getUniqueId))) MCChatUtils.OnlineSenders.filterInPlace((_, userMap) => userMap.entrySet.stream.noneMatch(_.getValue.getUniqueId.equals(e.getPlayer.getUniqueId)))
Bukkit.getScheduler.runTaskAsynchronously(DiscordPlugin.plugin, () => MCChatUtils.LoggedInPlayers.get(e.getPlayer.getUniqueId).foreach(MCChatUtils.callLoginEvents)) Bukkit.getScheduler.runTaskAsynchronously(DiscordPlugin.plugin, () => MCChatUtils.LoggedInPlayers.get(e.getPlayer.getUniqueId).foreach(MCChatUtils.callLoginEvents))
Bukkit.getScheduler.runTaskLaterAsynchronously(DiscordPlugin.plugin, () => ChromaBot.updatePlayerList(), 5) Bukkit.getScheduler.runTaskLaterAsynchronously(DiscordPlugin.plugin, () => ChromaBot.updatePlayerList(), 5)