Tailrec announcer method, fix some compile issues
This commit is contained in:
parent
d416eef144
commit
7296ebd2f8
18 changed files with 272 additions and 292 deletions
|
@ -13,7 +13,7 @@ import java.util
|
||||||
class DiscordSender(user: User, channel: MessageChannel, pname: String) extends DiscordSenderBase(user, channel) with CommandSender {
|
class DiscordSender(user: User, channel: MessageChannel, pname: String) extends DiscordSenderBase(user, channel) with CommandSender {
|
||||||
private val perm = new PermissibleBase(this)
|
private val perm = new PermissibleBase(this)
|
||||||
private val name: String = Option(pname)
|
private val name: String = Option(pname)
|
||||||
.orElse(Option(user).map(u => SMono(u.asMember(DiscordPlugin.mainServer.getId))
|
.orElse(Option(user).flatMap(u => SMono(u.asMember(DiscordPlugin.mainServer.getId))
|
||||||
.onErrorResume(_ => SMono.empty).blockOption()
|
.onErrorResume(_ => SMono.empty).blockOption()
|
||||||
.map(u => u.getDisplayName)))
|
.map(u => u.getDisplayName)))
|
||||||
.getOrElse("Discord user")
|
.getOrElse("Discord user")
|
||||||
|
|
|
@ -44,7 +44,8 @@ abstract class DiscordSenderBase protected(var user: User, var channel: MessageC
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val sendmsg = DPUtils.sanitizeString(message)
|
val sendmsg = DPUtils.sanitizeString(message)
|
||||||
this synchronized msgtosend += "\n" + sendmsg
|
this synchronized {
|
||||||
|
msgtosend += "\n" + sendmsg
|
||||||
if (sendtask == null) sendtask = Bukkit.getScheduler.runTaskLaterAsynchronously(DiscordPlugin.plugin, () => {
|
if (sendtask == null) sendtask = Bukkit.getScheduler.runTaskLaterAsynchronously(DiscordPlugin.plugin, () => {
|
||||||
def foo(): Unit = {
|
def foo(): Unit = {
|
||||||
channel.createMessage((if (user != null) user.getMention + "\n"
|
channel.createMessage((if (user != null) user.getMention + "\n"
|
||||||
|
@ -55,10 +56,11 @@ abstract class DiscordSenderBase protected(var user: User, var channel: MessageC
|
||||||
|
|
||||||
foo()
|
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 {
|
||||||
case e: Exception =>
|
case e: Exception =>
|
||||||
TBMCCoreAPI.SendException("An error occured while sending message to DiscordSender", e, DiscordPlugin.plugin)
|
TBMCCoreAPI.SendException("An error occured while sending message to DiscordSender", e, DiscordPlugin.plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def sendMessage(messages: Array[String]): Unit = sendMessage(String.join("\n", messages))
|
override def sendMessage(messages: Array[String]): Unit = sendMessage(String.join("\n", messages: _*))
|
||||||
}
|
}
|
|
@ -5,9 +5,10 @@ import buttondevteam.lib.TBMCCoreAPI
|
||||||
import buttondevteam.lib.architecture.{Component, ComponentMetadata}
|
import buttondevteam.lib.architecture.{Component, ComponentMetadata}
|
||||||
import buttondevteam.lib.player.ChromaGamerBase
|
import buttondevteam.lib.player.ChromaGamerBase
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import discord4j.core.`object`.entity.Message
|
|
||||||
import discord4j.core.`object`.entity.channel.MessageChannel
|
import discord4j.core.`object`.entity.channel.MessageChannel
|
||||||
import reactor.core.publisher.Flux
|
import reactor.core.scala.publisher.SMono
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts new posts from Reddit to the specified channel(s). It will pin the regular posts (not the mod posts).
|
* Posts new posts from Reddit to the specified channel(s). It will pin the regular posts (not the mod posts).
|
||||||
|
@ -39,23 +40,19 @@ import reactor.core.publisher.Flux
|
||||||
override protected def enable(): Unit = {
|
override protected def enable(): Unit = {
|
||||||
if (DPUtils.disableIfConfigError(this, channel, modChannel)) return
|
if (DPUtils.disableIfConfigError(this, channel, modChannel)) return
|
||||||
AnnouncerModule.stop = false //If not the first time
|
AnnouncerModule.stop = false //If not the first time
|
||||||
val kp = keepPinned.get
|
val kp: Short = keepPinned.get
|
||||||
if (kp eq 0) return
|
if (kp <= 0) return
|
||||||
val msgs: Flux[Message] = channel.get.flatMapMany(_.getPinnedMessages).takeLast(kp)
|
val msgs = channel.get.flatMapMany(_.getPinnedMessages).takeLast(kp)
|
||||||
msgs.subscribe(_.unpin)
|
msgs.subscribe(_.unpin)
|
||||||
new Thread(() => this.AnnouncementGetterThreadMethod()).start()
|
new Thread(() => this.AnnouncementGetterThreadMethod()).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def disable(): Unit = AnnouncerModule.stop = true
|
override protected def disable(): Unit = AnnouncerModule.stop = true
|
||||||
|
|
||||||
private def AnnouncementGetterThreadMethod(): Unit = while ( {
|
@tailrec
|
||||||
!AnnouncerModule.stop
|
private def AnnouncementGetterThreadMethod() {
|
||||||
}) {
|
if (AnnouncerModule.stop) return
|
||||||
try {
|
if (isEnabled) try { //If not enabled, just wait
|
||||||
if (!isEnabled) { //noinspection BusyWait
|
|
||||||
Thread.sleep(10000)
|
|
||||||
continue //todo: continue is not supported
|
|
||||||
}
|
|
||||||
val body = TBMCCoreAPI.DownloadString(subredditURL.get + "/new/.json?limit=10")
|
val body = TBMCCoreAPI.DownloadString(subredditURL.get + "/new/.json?limit=10")
|
||||||
val json = new JsonParser().parse(body).getAsJsonObject.get("data").getAsJsonObject.get("children").getAsJsonArray
|
val json = new JsonParser().parse(body).getAsJsonObject.get("data").getAsJsonObject.get("children").getAsJsonArray
|
||||||
val msgsb = new StringBuilder
|
val msgsb = new StringBuilder
|
||||||
|
@ -66,30 +63,32 @@ import reactor.core.publisher.Flux
|
||||||
val data = item.get("data").getAsJsonObject
|
val data = item.get("data").getAsJsonObject
|
||||||
var author = data.get("author").getAsString
|
var author = data.get("author").getAsString
|
||||||
val distinguishedjson = data.get("distinguished")
|
val distinguishedjson = data.get("distinguished")
|
||||||
var distinguished = null
|
val distinguished = if (distinguishedjson.isJsonNull) null else distinguishedjson.getAsString
|
||||||
if (distinguishedjson.isJsonNull) distinguished = null
|
|
||||||
else distinguished = distinguishedjson.getAsString
|
|
||||||
val permalink = "https://www.reddit.com" + data.get("permalink").getAsString
|
val permalink = "https://www.reddit.com" + data.get("permalink").getAsString
|
||||||
val date = data.get("created_utc").getAsLong
|
val date = data.get("created_utc").getAsLong
|
||||||
if (date > lastSeenTime.get) lastSeenTime.set(date)
|
if (date > lastSeenTime.get) lastSeenTime.set(date)
|
||||||
else if (date > lastAnnouncementTime.get) { //noinspection ConstantConditions
|
else if (date > lastAnnouncementTime.get) { //noinspection ConstantConditions
|
||||||
do {
|
{
|
||||||
val reddituserclass = ChromaGamerBase.getTypeForFolder("reddit")
|
val reddituserclass = ChromaGamerBase.getTypeForFolder("reddit")
|
||||||
if (reddituserclass == null) break //todo: break is not supported
|
if (reddituserclass != null) {
|
||||||
val user = ChromaGamerBase.getUser(author, reddituserclass)
|
val user = ChromaGamerBase.getUser(author, reddituserclass)
|
||||||
val id = user.getConnectedID(classOf[DiscordPlayer])
|
val id = user.getConnectedID(classOf[DiscordPlayer])
|
||||||
if (id != null) author = "<@" + id + ">"
|
if (id != null) author = "<@" + id + ">"
|
||||||
} while ( {
|
}
|
||||||
false
|
}
|
||||||
})
|
|
||||||
if (!author.startsWith("<")) author = "/u/" + author
|
if (!author.startsWith("<")) author = "/u/" + author
|
||||||
(if (distinguished != null && distinguished == "moderator") modmsgsb
|
(if (distinguished != null && distinguished == "moderator") modmsgsb else msgsb)
|
||||||
else msgsb).append("A new post was submitted to the subreddit by ").append(author).append("\n").append(permalink).append("\n")
|
.append("A new post was submitted to the subreddit by ").append(author).append("\n")
|
||||||
|
.append(permalink).append("\n")
|
||||||
lastanntime = date
|
lastanntime = date
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msgsb.length > 0) channel.get.flatMap((ch: MessageChannel) => ch.createMessage(msgsb.toString)).flatMap(Message.pin).subscribe
|
|
||||||
if (modmsgsb.length > 0) modChannel.get.flatMap((ch: MessageChannel) => ch.createMessage(modmsgsb.toString)).flatMap(Message.pin).subscribe
|
def sendMsg(ch: SMono[MessageChannel], msg: String) =
|
||||||
|
ch.asJava().flatMap(c => c.createMessage(msg)).flatMap(_.pin).subscribe
|
||||||
|
|
||||||
|
if (msgsb.nonEmpty) sendMsg(channel.get(), msgsb.toString())
|
||||||
|
if (modmsgsb.nonEmpty) sendMsg(modChannel.get(), modmsgsb.toString())
|
||||||
if (lastAnnouncementTime.get ne lastanntime) lastAnnouncementTime.set(lastanntime) // If sending succeeded
|
if (lastAnnouncementTime.get ne lastanntime) lastAnnouncementTime.set(lastanntime) // If sending succeeded
|
||||||
} catch {
|
} catch {
|
||||||
case e: Exception =>
|
case e: Exception =>
|
||||||
|
@ -100,5 +99,6 @@ import reactor.core.publisher.Flux
|
||||||
case ex: InterruptedException =>
|
case ex: InterruptedException =>
|
||||||
Thread.currentThread.interrupt()
|
Thread.currentThread.interrupt()
|
||||||
}
|
}
|
||||||
|
AnnouncementGetterThreadMethod()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ import lombok.RequiredArgsConstructor
|
||||||
this.message.getChannel.flatMap((ch: MessageChannel) => ch.createMessage(this.message.getAuthor.map((u: User) => DPUtils.nickMention(u.getId) + ", ").orElse("") + msg)).subscribe
|
this.message.getChannel.flatMap((ch: MessageChannel) => ch.createMessage(this.message.getAuthor.map((u: User) => DPUtils.nickMention(u.getId) + ", ").orElse("") + msg)).subscribe
|
||||||
}
|
}
|
||||||
|
|
||||||
override def sendMessage(message: Array[String]): Unit = sendMessage(String.join("\n", message))
|
override def sendMessage(message: Array[String]): Unit = sendMessage(String.join("\n", message: _*))
|
||||||
|
|
||||||
override def getName = message.getAuthor.map(_.getUsername).orElse("Discord")
|
override def getName: String = Option(message.getAuthor.orElse(null)).map(_.getUsername).getOrElse("Discord")
|
||||||
}
|
}
|
|
@ -7,8 +7,9 @@ import com.google.common.collect.HashBiMap
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
@CommandClass(helpText = Array(Array("Connect command", //
|
@CommandClass(helpText = Array("Connect command", //
|
||||||
"This command lets you connect your account with a Minecraft account. This allows using the private Minecraft chat and other things."))) object ConnectCommand {
|
"This command lets you connect your account with a Minecraft account." +
|
||||||
|
" This allows using the private Minecraft chat and other things.")) object ConnectCommand {
|
||||||
/**
|
/**
|
||||||
* Key: Minecraft name<br>
|
* Key: Minecraft name<br>
|
||||||
* Value: Discord ID
|
* Value: Discord ID
|
||||||
|
|
|
@ -3,24 +3,27 @@ package buttondevteam.discordplugin.commands
|
||||||
import buttondevteam.discordplugin.DiscordPlugin
|
import buttondevteam.discordplugin.DiscordPlugin
|
||||||
import buttondevteam.discordplugin.listeners.CommonListeners
|
import buttondevteam.discordplugin.listeners.CommonListeners
|
||||||
import buttondevteam.lib.chat.{Command2, CommandClass}
|
import buttondevteam.lib.chat.{Command2, CommandClass}
|
||||||
|
import discord4j.common.util.Snowflake
|
||||||
import discord4j.core.`object`.entity.{Member, User}
|
import discord4j.core.`object`.entity.{Member, User}
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.scala.publisher.SMono
|
||||||
|
|
||||||
@CommandClass(helpText = Array(Array("Switches debug mode.")))
|
@CommandClass(helpText = Array("Switches debug mode."))
|
||||||
class DebugCommand extends ICommand2DC {
|
class DebugCommand extends ICommand2DC {
|
||||||
@Command2.Subcommand
|
@Command2.Subcommand
|
||||||
override def `def`(sender: Command2DCSender): Boolean = {
|
override def `def`(sender: Command2DCSender): Boolean = {
|
||||||
sender.getMessage.getAuthorAsMember.switchIfEmpty(sender.getMessage.getAuthor.map //Support DMs
|
SMono(sender.getMessage.getAuthorAsMember)
|
||||||
((u: User) => u.asMember(DiscordPlugin.mainServer.getId)).orElse(Mono.empty)).flatMap((m: Member) => DiscordPlugin.plugin.modRole.get.map((mr) => m.getRoleIds.stream.anyMatch((r: Snowflake) => r == mr.getId)).switchIfEmpty(Mono.fromSupplier(() => DiscordPlugin.mainServer.getOwnerId.asLong eq m.getId.asLong)))
|
.switchIfEmpty(Option(sender.getMessage.getAuthor.orElse(null)) //Support DMs
|
||||||
.onErrorReturn(false) //Role not found
|
.map((u: User) => SMono(u.asMember(DiscordPlugin.mainServer.getId))).getOrElse(SMono.empty))
|
||||||
.subscribe((success: Any) => {
|
.flatMap((m: Member) => DiscordPlugin.plugin.modRole.get
|
||||||
def foo(success: Any) = {
|
.map(mr => m.getRoleIds.stream.anyMatch((r: Snowflake) => r == mr.getId))
|
||||||
if (success) sender.sendMessage("debug " + (if (CommonListeners.debug) "enabled"
|
.switchIfEmpty(SMono.fromCallable(() => DiscordPlugin.mainServer.getOwnerId.asLong eq m.getId.asLong)))
|
||||||
else "disabled"))
|
.onErrorResume(_ => SMono.just(false)) //Role not found
|
||||||
else sender.sendMessage("you need to be a moderator to use this command.")
|
.subscribe(success => {
|
||||||
}
|
if (success) {
|
||||||
|
CommonListeners.debug = !CommonListeners.debug;
|
||||||
foo(success)
|
sender.sendMessage("debug " + (if (CommonListeners.debug) "enabled" else "disabled"))
|
||||||
|
} else
|
||||||
|
sender.sendMessage("you need to be a moderator to use this command.")
|
||||||
})
|
})
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ package buttondevteam.discordplugin.commands
|
||||||
|
|
||||||
import buttondevteam.lib.chat.{Command2, CommandClass}
|
import buttondevteam.lib.chat.{Command2, CommandClass}
|
||||||
|
|
||||||
@CommandClass(helpText = Array(Array("Help command", //
|
@CommandClass(helpText = Array("Help command", //
|
||||||
"Shows some info about a command or lists the available commands.")))
|
"Shows some info about a command or lists the available commands."))
|
||||||
class HelpCommand extends ICommand2DC {
|
class HelpCommand extends ICommand2DC {
|
||||||
@Command2.Subcommand
|
@Command2.Subcommand
|
||||||
def `def`(sender: Command2DCSender, @Command2.TextArg @Command2.OptionalArg args: String): Boolean = {
|
def `def`(sender: Command2DCSender, @Command2.TextArg @Command2.OptionalArg args: String): Boolean = {
|
||||||
|
|
|
@ -4,13 +4,12 @@ import buttondevteam.discordplugin.{DiscordPlayer, DiscordPlugin}
|
||||||
import buttondevteam.lib.chat.{Command2, CommandClass}
|
import buttondevteam.lib.chat.{Command2, CommandClass}
|
||||||
import buttondevteam.lib.player.ChromaGamerBase
|
import buttondevteam.lib.player.ChromaGamerBase
|
||||||
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget
|
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget
|
||||||
import discord4j.core.`object`.entity.{Member, Message, User}
|
import discord4j.core.`object`.entity.{Message, User}
|
||||||
|
import reactor.core.scala.publisher.SFlux
|
||||||
|
|
||||||
import java.util
|
@CommandClass(helpText = Array("User information", //
|
||||||
|
|
||||||
@CommandClass(helpText = Array(Array("User information", //
|
|
||||||
"Shows some information about users, from Discord, from Minecraft or from Reddit if they have these accounts connected.",
|
"Shows some information about users, from Discord, from Minecraft or from Reddit if they have these accounts connected.",
|
||||||
"If used without args, shows your info.")))
|
"If used without args, shows your info."))
|
||||||
class UserinfoCommand extends ICommand2DC {
|
class UserinfoCommand extends ICommand2DC {
|
||||||
@Command2.Subcommand
|
@Command2.Subcommand
|
||||||
def `def`(sender: Command2DCSender, @Command2.OptionalArg @Command2.TextArg user: String): Boolean = {
|
def `def`(sender: Command2DCSender, @Command2.OptionalArg @Command2.TextArg user: String): Boolean = {
|
||||||
|
@ -25,16 +24,11 @@ class UserinfoCommand extends ICommand2DC {
|
||||||
else if (user.contains("#")) {
|
else if (user.contains("#")) {
|
||||||
val targettag = user.split("#")
|
val targettag = user.split("#")
|
||||||
val targets = getUsers(message, targettag(0))
|
val targets = getUsers(message, targettag(0))
|
||||||
if (targets.size == 0) {
|
if (targets.isEmpty) {
|
||||||
channel.createMessage("The user cannot be found (by name): " + user).subscribe
|
channel.createMessage("The user cannot be found (by name): " + user).subscribe
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
for (ptarget <- targets) {
|
targets.collectFirst(_.getDiscriminator.equalsIgnoreCase(targettag(1)))
|
||||||
if (ptarget.getDiscriminator.equalsIgnoreCase(targettag(1))) {
|
|
||||||
target = ptarget
|
|
||||||
break //todo: break is not supported
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
channel.createMessage("The user cannot be found (by discriminator): " + user + "(Found " + targets.size + " users with the name.)").subscribe
|
channel.createMessage("The user cannot be found (by discriminator): " + user + "(Found " + targets.size + " users with the name.)").subscribe
|
||||||
return true
|
return true
|
||||||
|
@ -42,7 +36,7 @@ class UserinfoCommand extends ICommand2DC {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val targets = getUsers(message, user)
|
val targets = getUsers(message, user)
|
||||||
if (targets.size == 0) {
|
if (targets.isEmpty) {
|
||||||
channel.createMessage("The user cannot be found on Discord: " + user).subscribe
|
channel.createMessage("The user cannot be found on Discord: " + user).subscribe
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -50,7 +44,7 @@ class UserinfoCommand extends ICommand2DC {
|
||||||
channel.createMessage("Multiple users found with that (nick)name. Please specify the whole tag, like ChromaBot#6338 or use a ping.").subscribe
|
channel.createMessage("Multiple users found with that (nick)name. Please specify the whole tag, like ChromaBot#6338 or use a ping.").subscribe
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
target = targets.get(0)
|
target = targets.head
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
|
@ -65,12 +59,11 @@ class UserinfoCommand extends ICommand2DC {
|
||||||
}
|
}
|
||||||
|
|
||||||
private def getUsers(message: Message, args: String) = {
|
private def getUsers(message: Message, args: String) = {
|
||||||
var targets: util.List[User]
|
|
||||||
val guild = message.getGuild.block
|
val guild = message.getGuild.block
|
||||||
if (guild == null) { //Private channel
|
if (guild == null) { //Private channel
|
||||||
targets = DiscordPlugin.dc.getUsers.filter((u) => u.getUsername.equalsIgnoreCase(args)).collectList.block
|
SFlux(DiscordPlugin.dc.getUsers).filter(u => u.getUsername.equalsIgnoreCase(args)).collectSeq().block()
|
||||||
}
|
}
|
||||||
else targets = guild.getMembers.filter((m: Member) => m.getUsername.equalsIgnoreCase(args)).map((m: Member) => m.asInstanceOf[User]).collectList.block
|
else
|
||||||
targets
|
SFlux(guild.getMembers).filter(_.getUsername.equalsIgnoreCase(args)).map(_.asInstanceOf[User]).collectSeq().block()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ package buttondevteam.discordplugin.commands
|
||||||
import buttondevteam.discordplugin.DiscordPlugin
|
import buttondevteam.discordplugin.DiscordPlugin
|
||||||
import buttondevteam.lib.chat.{Command2, CommandClass}
|
import buttondevteam.lib.chat.{Command2, CommandClass}
|
||||||
|
|
||||||
@CommandClass(helpText = Array(Array("Version", "Returns the plugin's version")))
|
@CommandClass(helpText = Array("Version", "Returns the plugin's version"))
|
||||||
object VersionCommand {
|
object VersionCommand {
|
||||||
def getVersion: Array[String] = {
|
def getVersion: Array[String] = {
|
||||||
val desc = DiscordPlugin.plugin.getDescription
|
val desc = DiscordPlugin.plugin.getDescription
|
||||||
|
@ -11,7 +11,7 @@ object VersionCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@CommandClass(helpText = Array(Array("Version", "Returns the plugin's version")))
|
@CommandClass(helpText = Array("Version", "Returns the plugin's version"))
|
||||||
class VersionCommand extends ICommand2DC {
|
class VersionCommand extends ICommand2DC {
|
||||||
@Command2.Subcommand override def `def`(sender: Command2DCSender): Boolean = {
|
@Command2.Subcommand override def `def`(sender: Command2DCSender): Boolean = {
|
||||||
sender.sendMessage(VersionCommand.getVersion)
|
sender.sendMessage(VersionCommand.getVersion)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import discord4j.core.`object`.entity.{Guild, Role}
|
||||||
import org.apache.commons.lang.exception.ExceptionUtils
|
import org.apache.commons.lang.exception.ExceptionUtils
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.event.{EventHandler, Listener}
|
import org.bukkit.event.{EventHandler, Listener}
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.scala.publisher.SMono
|
||||||
|
|
||||||
import java.util
|
import java.util
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
|
@ -20,29 +20,24 @@ import java.util.stream.Collectors
|
||||||
object ExceptionListenerModule {
|
object ExceptionListenerModule {
|
||||||
private def SendException(e: Throwable, sourcemessage: String): Unit = {
|
private def SendException(e: Throwable, sourcemessage: String): Unit = {
|
||||||
if (instance == null) return
|
if (instance == null) return
|
||||||
try getChannel.flatMap((channel: MessageChannel) => {
|
try getChannel.flatMap(channel => {
|
||||||
def foo(channel: MessageChannel) = {
|
val coderRole = channel match {
|
||||||
var coderRole: Mono[Role] = channel match {
|
case ch: GuildChannel => instance.pingRole(SMono(ch.getGuild)).get
|
||||||
case ch: GuildChannel => instance.pingRole(ch.getGuild).get
|
case _ => SMono.empty
|
||||||
case _ => Mono.empty
|
|
||||||
}
|
}
|
||||||
coderRole.map((role: Role) => if (TBMCCoreAPI.IsTestServer) new StringBuilder
|
coderRole.map((role: Role) => if (TBMCCoreAPI.IsTestServer) new StringBuilder
|
||||||
else new StringBuilder(role.getMention).append("\n")).defaultIfEmpty(new StringBuilder).flatMap((sb: StringBuilder) => {
|
else new StringBuilder(role.getMention).append("\n"))
|
||||||
def foo(sb: StringBuilder) = {
|
.defaultIfEmpty(new StringBuilder).flatMap(sb => {
|
||||||
sb.append(sourcemessage).append("\n")
|
sb.append(sourcemessage).append("\n")
|
||||||
sb.append("```").append("\n")
|
sb.append("```").append("\n")
|
||||||
var stackTrace = util.Arrays.stream(ExceptionUtils.getStackTrace(e).split("\\n")).filter((s: String) => !s.contains("\tat ") || s.contains("\tat buttondevteam.")).collect(Collectors.joining("\n"))
|
var stackTrace = util.Arrays.stream(ExceptionUtils.getStackTrace(e).split("\\n"))
|
||||||
|
.filter(s => !s.contains("\tat ") || s.contains("\tat buttondevteam."))
|
||||||
|
.collect(Collectors.joining("\n"))
|
||||||
if (sb.length + stackTrace.length >= 1980) stackTrace = stackTrace.substring(0, 1980 - sb.length)
|
if (sb.length + stackTrace.length >= 1980) stackTrace = stackTrace.substring(0, 1980 - sb.length)
|
||||||
sb.append(stackTrace).append("\n")
|
sb.append(stackTrace).append("\n")
|
||||||
sb.append("```")
|
sb.append("```")
|
||||||
channel.createMessage(sb.toString)
|
SMono(channel.createMessage(sb.toString))
|
||||||
}
|
|
||||||
|
|
||||||
foo(sb)
|
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
foo(channel)
|
|
||||||
}).subscribe
|
}).subscribe
|
||||||
catch {
|
catch {
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
|
@ -52,9 +47,9 @@ object ExceptionListenerModule {
|
||||||
|
|
||||||
private var instance: ExceptionListenerModule = null
|
private var instance: ExceptionListenerModule = null
|
||||||
|
|
||||||
def getChannel: Mono[MessageChannel] = {
|
def getChannel: SMono[MessageChannel] = {
|
||||||
if (instance != null) return instance.channel.get
|
if (instance != null) return instance.channel.get
|
||||||
Mono.empty
|
SMono.empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,13 +59,12 @@ class ExceptionListenerModule extends Component[DiscordPlugin] with Listener {
|
||||||
|
|
||||||
@EventHandler def onException(e: TBMCExceptionEvent): Unit = {
|
@EventHandler def onException(e: TBMCExceptionEvent): Unit = {
|
||||||
if (DiscordPlugin.SafeMode || !ComponentManager.isEnabled(getClass)) return
|
if (DiscordPlugin.SafeMode || !ComponentManager.isEnabled(getClass)) return
|
||||||
if (lastthrown.stream.anyMatch((ex: Throwable) => util.Arrays.equals(e.getException.getStackTrace, ex.getStackTrace) && (if (e.getException.getMessage == null) ex.getMessage == null
|
if (lastthrown.stream.anyMatch(ex => e.getException.getStackTrace.sameElements(ex.getStackTrace)
|
||||||
else e.getException.getMessage == ex.getMessage)) // e.Exception.Message==ex.Message
|
&& (if (e.getException.getMessage == null) ex.getMessage == null else e.getException.getMessage == ex.getMessage))
|
||||||
&& lastsourcemsg.contains(e.getSourceMessage)) {
|
&& lastsourcemsg.contains(e.getSourceMessage)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ExceptionListenerModule
|
ExceptionListenerModule.SendException(e.getException, e.getSourceMessage)
|
||||||
.SendException(e.getException, e.getSourceMessage)
|
|
||||||
if (lastthrown.size >= 10) lastthrown.remove(0)
|
if (lastthrown.size >= 10) lastthrown.remove(0)
|
||||||
if (lastsourcemsg.size >= 10) lastsourcemsg.remove(0)
|
if (lastsourcemsg.size >= 10) lastsourcemsg.remove(0)
|
||||||
lastthrown.add(e.getException)
|
lastthrown.add(e.getException)
|
||||||
|
@ -86,7 +80,7 @@ class ExceptionListenerModule extends Component[DiscordPlugin] with Listener {
|
||||||
/**
|
/**
|
||||||
* The role to ping if an error occurs. Set to empty ('') to disable.
|
* The role to ping if an error occurs. Set to empty ('') to disable.
|
||||||
*/
|
*/
|
||||||
private def pingRole(guild: Mono[Guild]) = DPUtils.roleData(getConfig, "pingRole", "Coder", guild)
|
private def pingRole(guild: SMono[Guild]) = DPUtils.roleData(getConfig, "pingRole", "Coder", guild)
|
||||||
|
|
||||||
override protected def enable(): Unit = {
|
override protected def enable(): Unit = {
|
||||||
if (DPUtils.disableIfConfigError(this, channel)) return
|
if (DPUtils.disableIfConfigError(this, channel)) return
|
||||||
|
|
|
@ -5,16 +5,15 @@ import buttondevteam.discordplugin.{DPUtils, DiscordPlugin}
|
||||||
import buttondevteam.lib.TBMCCoreAPI
|
import buttondevteam.lib.TBMCCoreAPI
|
||||||
import buttondevteam.lib.architecture.{Component, ConfigData}
|
import buttondevteam.lib.architecture.{Component, ConfigData}
|
||||||
import com.google.common.collect.Lists
|
import com.google.common.collect.Lists
|
||||||
import discord4j.common.util.Snowflake
|
|
||||||
import discord4j.core.`object`.entity.channel.{GuildChannel, MessageChannel}
|
import discord4j.core.`object`.entity.channel.{GuildChannel, MessageChannel}
|
||||||
import discord4j.core.`object`.entity.{Guild, Member, Message, Role}
|
import discord4j.core.`object`.entity.{Guild, Message}
|
||||||
import discord4j.core.`object`.presence.{Presence, Status}
|
import discord4j.core.`object`.presence.Status
|
||||||
import discord4j.core.event.domain.PresenceUpdateEvent
|
import discord4j.core.event.domain.PresenceUpdateEvent
|
||||||
import discord4j.core.spec.{EmbedCreateSpec, MessageCreateSpec}
|
import discord4j.core.spec.{EmbedCreateSpec, MessageCreateSpec}
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.event.player.PlayerJoinEvent
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
import org.bukkit.event.{EventHandler, Listener}
|
import org.bukkit.event.{EventHandler, Listener}
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.scala.publisher.{SFlux, SMono}
|
||||||
|
|
||||||
import java.util
|
import java.util
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
@ -50,40 +49,46 @@ object FunModule {
|
||||||
lastlist = 0
|
lastlist = 0
|
||||||
}
|
}
|
||||||
if (msglowercased == "/list" && Bukkit.getOnlinePlayers.size == lastlistp && {
|
if (msglowercased == "/list" && Bukkit.getOnlinePlayers.size == lastlistp && {
|
||||||
ListC += 1;
|
ListC += 1
|
||||||
ListC - 1
|
ListC - 1
|
||||||
} > 2) { // Lowered already
|
} > 2) { // Lowered already
|
||||||
DPUtils.reply(message, Mono.empty, "stop it. You know the answer.").subscribe
|
DPUtils.reply(message, SMono.empty, "stop it. You know the answer.").subscribe
|
||||||
lastlist = 0
|
lastlist = 0
|
||||||
lastlistp = Bukkit.getOnlinePlayers.size.toShort
|
lastlistp = Bukkit.getOnlinePlayers.size.toShort
|
||||||
return true //Handled
|
return true //Handled
|
||||||
}
|
}
|
||||||
lastlistp = Bukkit.getOnlinePlayers.size.toShort //Didn't handle
|
lastlistp = Bukkit.getOnlinePlayers.size.toShort //Didn't handle
|
||||||
if (!TBMCCoreAPI.IsTestServer && util.Arrays.stream(fm.serverReady).get.anyMatch(msglowercased.contains _)) {
|
if (!TBMCCoreAPI.IsTestServer && fm.serverReady.get.exists(msglowercased.contains)) {
|
||||||
var next = 0
|
var next = 0
|
||||||
if (usableServerReadyStrings.size == 0) fm.createUsableServerReadyStrings()
|
if (usableServerReadyStrings.size == 0) fm.createUsableServerReadyStrings()
|
||||||
next = usableServerReadyStrings.remove(serverReadyRandom.nextInt(usableServerReadyStrings.size))
|
next = usableServerReadyStrings.remove(serverReadyRandom.nextInt(usableServerReadyStrings.size))
|
||||||
DPUtils.reply(message, Mono.empty, fm.serverReadyAnswers.get.get(next)).subscribe
|
DPUtils.reply(message, SMono.empty, fm.serverReadyAnswers.get.get(next)).subscribe
|
||||||
return false //Still process it as a command/mcchat if needed
|
return false //Still process it as a command/mcchat if needed
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
private var lasttime = 0
|
private var lasttime: Long = 0
|
||||||
|
|
||||||
def handleFullHouse(event: PresenceUpdateEvent): Unit = {
|
def handleFullHouse(event: PresenceUpdateEvent): Unit = {
|
||||||
val fm = ComponentManager.getIfEnabled(classOf[FunModule])
|
val fm = ComponentManager.getIfEnabled(classOf[FunModule])
|
||||||
if (fm == null) return
|
if (fm == null) return
|
||||||
if (Calendar.getInstance.get(Calendar.DAY_OF_MONTH) % 5 != 0) return
|
if (Calendar.getInstance.get(Calendar.DAY_OF_MONTH) % 5 != 0) return
|
||||||
|
if (!Option(event.getOld.orElse(null)).exists(_.getStatus == Status.OFFLINE)
|
||||||
|
|| event.getCurrent.getStatus == Status.OFFLINE)
|
||||||
|
return //If it's not an offline -> online change
|
||||||
fm.fullHouseChannel.get.filter((ch: MessageChannel) => ch.isInstanceOf[GuildChannel])
|
fm.fullHouseChannel.get.filter((ch: MessageChannel) => ch.isInstanceOf[GuildChannel])
|
||||||
.flatMap((channel: MessageChannel) => fm.fullHouseDevRole(channel.asInstanceOf[GuildChannel].getGuild).get.filter((role: Role) => event.getOld.map((p: Presence) => p.getStatus == Status.OFFLINE).orElse(false)).filter((role: Role) => !(event.getCurrent.getStatus == Status.OFFLINE)).filterWhen((devrole: Role) => event.getMember.flatMap((m: Member) => m.getRoles.any((r: Role) => r.getId.asLong == devrole.getId.asLong))).filterWhen((devrole: Role) => event.getGuild.flatMapMany((g: Guild) => g.getMembers.filter((m: Member) => m.getRoleIds.stream.anyMatch((s: Snowflake) => s == devrole.getId))).flatMap(Member.getPresence).all((pr: Presence) => !(pr.getStatus == Status.OFFLINE))).filter((devrole: Role) => lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime)).flatMap //This should stay so it checks this last
|
.flatMap(channel => fm.fullHouseDevRole(SMono(channel.asInstanceOf[GuildChannel].getGuild)).get
|
||||||
((devrole: Role) => {
|
.filterWhen(devrole => SMono(event.getMember)
|
||||||
def foo(devrole: Role) = {
|
.flatMap(m => SFlux(m.getRoles).any(_.getId.asLong == devrole.getId.asLong)))
|
||||||
|
.filterWhen(devrole => SMono(event.getGuild)
|
||||||
|
.flatMapMany(g => SFlux(g.getMembers).filter(_.getRoleIds.stream.anyMatch(_ == devrole.getId)))
|
||||||
|
.flatMap(_.getPresence).all(_.getStatus != Status.OFFLINE))
|
||||||
|
.filter(_ => lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime)) //This should stay so it checks this last
|
||||||
|
.flatMap(_ => {
|
||||||
lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime)
|
lasttime = TimeUnit.NANOSECONDS.toHours(System.nanoTime)
|
||||||
channel.createMessage((mcs: MessageCreateSpec) => mcs.setContent("Full house!").setEmbed((ecs: EmbedCreateSpec) => ecs.setImage("https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png")))
|
SMono(channel.createMessage((mcs: MessageCreateSpec) => mcs.setContent("Full house!")
|
||||||
}
|
.setEmbed((ecs: EmbedCreateSpec) => ecs.setImage("https://cdn.discordapp.com/attachments/249295547263877121/249687682618359808/poker-hand-full-house-aces-kings-playing-cards-15553791.png"))))
|
||||||
|
|
||||||
foo(devrole)
|
|
||||||
})).subscribe
|
})).subscribe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,14 +114,18 @@ class FunModule extends Component[DiscordPlugin] with Listener {
|
||||||
|
|
||||||
override protected def enable(): Unit = registerListener(this)
|
override protected def enable(): Unit = registerListener(this)
|
||||||
|
|
||||||
override protected def disable(): Unit = FunModule.lastlist = FunModule.lastlistp = FunModule.ListC = 0
|
override protected def disable(): Unit = {
|
||||||
|
FunModule.lastlist = 0
|
||||||
|
FunModule.lastlistp = 0
|
||||||
|
FunModule.ListC = 0
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler def onPlayerJoin(event: PlayerJoinEvent): Unit = FunModule.ListC = 0
|
@EventHandler def onPlayerJoin(event: PlayerJoinEvent): Unit = FunModule.ListC = 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If all of the people who have this role are online, the bot will post a full house.
|
* If all of the people who have this role are online, the bot will post a full house.
|
||||||
*/
|
*/
|
||||||
private def fullHouseDevRole(guild: Mono[Guild]) = DPUtils.roleData(getConfig, "fullHouseDevRole", "Developer", guild)
|
private def fullHouseDevRole(guild: SMono[Guild]) = DPUtils.roleData(getConfig, "fullHouseDevRole", "Developer", guild)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The channel to post the full house to.
|
* The channel to post the full house to.
|
||||||
|
|
|
@ -12,7 +12,7 @@ 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.scala.publisher.SMono
|
import reactor.core.scala.publisher.{SFlux, SMono}
|
||||||
|
|
||||||
object CommonListeners {
|
object CommonListeners {
|
||||||
val timings = new Timings
|
val timings = new Timings
|
||||||
|
@ -56,25 +56,19 @@ object CommonListeners {
|
||||||
}
|
}
|
||||||
|
|
||||||
foo(event)
|
foo(event)
|
||||||
}).onErrorContinue((err: Throwable, obj: Any) => TBMCCoreAPI.SendException("An error occured while handling a message!", err, DiscordPlugin.plugin)).subscribe
|
}).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) => {
|
||||||
def foo(event: PresenceUpdateEvent) = {
|
if (!DiscordPlugin.SafeMode)
|
||||||
if (DiscordPlugin.SafeMode) return
|
|
||||||
FunModule.handleFullHouse(event)
|
FunModule.handleFullHouse(event)
|
||||||
}
|
|
||||||
|
|
||||||
foo(event)
|
|
||||||
})
|
})
|
||||||
dispatcher.on(classOf[RoleCreateEvent]).subscribe(GameRoleModule.handleRoleEvent _)
|
SFlux(dispatcher.on(classOf[RoleCreateEvent])).subscribe(GameRoleModule.handleRoleEvent _)
|
||||||
dispatcher.on(classOf[RoleDeleteEvent]).subscribe(GameRoleModule.handleRoleEvent _)
|
SFlux(dispatcher.on(classOf[RoleDeleteEvent])).subscribe(GameRoleModule.handleRoleEvent _)
|
||||||
dispatcher.on(classOf[RoleUpdateEvent]).subscribe(GameRoleModule.handleRoleEvent _)
|
SFlux(dispatcher.on(classOf[RoleUpdateEvent])).subscribe(GameRoleModule.handleRoleEvent _)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var debug = false
|
var debug = false
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
def debug(): Unit = debug = !debug
|
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ import java.util.{Objects, Optional}
|
||||||
import javax.annotation.Nullable
|
import javax.annotation.Nullable
|
||||||
|
|
||||||
@SuppressWarnings(Array("SimplifyOptionalCallChains")) //Java 11
|
@SuppressWarnings(Array("SimplifyOptionalCallChains")) //Java 11
|
||||||
@CommandClass(helpText = Array(Array("Channel connect", //
|
@CommandClass(helpText = Array("Channel connect", //
|
||||||
"This command allows you to connect a Minecraft channel to a Discord channel (just like how the global chat is connected to #minecraft-chat).",
|
"This command allows you to connect a Minecraft channel to a Discord channel (just like how the global chat is connected to #minecraft-chat).",
|
||||||
"You need to have access to the MC channel and have manage permissions on the Discord channel.",
|
"You need to have access to the MC channel and have manage permissions on the Discord channel.",
|
||||||
"You also need to have your Minecraft account connected. In #bot use /connect <mcname>.",
|
"You also need to have your Minecraft account connected. In #bot use /connect <mcname>.",
|
||||||
|
@ -30,7 +30,7 @@ import javax.annotation.Nullable
|
||||||
"To remove a connection use @ChromaBot channelcon remove in the channel.",
|
"To remove a connection use @ChromaBot channelcon remove in the channel.",
|
||||||
"Mentioning the bot is needed in this case because the / prefix only works in #bot.",
|
"Mentioning the bot is needed in this case because the / prefix only works in #bot.",
|
||||||
"Invite link: <Unknown>" //
|
"Invite link: <Unknown>" //
|
||||||
)))
|
))
|
||||||
class ChannelconCommand(private val module: MinecraftChatModule) extends ICommand2DC {
|
class ChannelconCommand(private val module: MinecraftChatModule) extends ICommand2DC {
|
||||||
@Command2.Subcommand def remove(sender: Command2DCSender): Boolean = {
|
@Command2.Subcommand def remove(sender: Command2DCSender): Boolean = {
|
||||||
val message = sender.getMessage
|
val message = sender.getMessage
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
package buttondevteam.discordplugin.mcchat
|
package buttondevteam.discordplugin.mcchat
|
||||||
|
|
||||||
import buttondevteam.discordplugin.{DPUtils, DiscordPlayer, DiscordPlugin}
|
|
||||||
import buttondevteam.discordplugin.commands.{Command2DCSender, ICommand2DC}
|
import buttondevteam.discordplugin.commands.{Command2DCSender, ICommand2DC}
|
||||||
|
import buttondevteam.discordplugin.{DPUtils, DiscordPlayer, DiscordPlugin}
|
||||||
import buttondevteam.lib.chat.{Command2, CommandClass}
|
import buttondevteam.lib.chat.{Command2, CommandClass}
|
||||||
import buttondevteam.lib.player.ChromaGamerBase
|
import buttondevteam.lib.player.ChromaGamerBase
|
||||||
import discord4j.core.`object`.entity.channel.PrivateChannel
|
import discord4j.core.`object`.entity.channel.PrivateChannel
|
||||||
|
|
||||||
@CommandClass(helpText = Array(Array(
|
@CommandClass(helpText = Array(
|
||||||
"MC Chat",
|
"MC Chat",
|
||||||
"This command enables or disables the Minecraft chat in private messages.", //
|
"This command enables or disables the Minecraft chat in private messages.", //
|
||||||
"It can be useful if you don't want your messages to be visible, for example when talking in a private channel.",
|
"It can be useful if you don't want your messages to be visible, for example when talking in a private channel.",
|
||||||
"You can also run all of the ingame commands you have access to using this command, if you have your accounts connected." //
|
"You can also run all of the ingame commands you have access to using this command, if you have your accounts connected." //
|
||||||
)))
|
))
|
||||||
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)) {
|
||||||
|
|
|
@ -8,15 +8,14 @@ import discord4j.core.`object`.entity.User
|
||||||
import discord4j.core.`object`.entity.channel.MessageChannel
|
import discord4j.core.`object`.entity.channel.MessageChannel
|
||||||
import lombok.NonNull
|
import lombok.NonNull
|
||||||
|
|
||||||
import java.util
|
|
||||||
import java.util.Collections
|
|
||||||
import javax.annotation.Nullable
|
import javax.annotation.Nullable
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
object MCChatCustom {
|
object MCChatCustom {
|
||||||
/**
|
/**
|
||||||
* Used for town or nation chats or anything else
|
* Used for town or nation chats or anything else
|
||||||
*/
|
*/
|
||||||
private[mcchat] val lastmsgCustom = new util.ArrayList[MCChatCustom.CustomLMD]
|
private[mcchat] val lastmsgCustom = new ListBuffer[MCChatCustom.CustomLMD]
|
||||||
|
|
||||||
def addCustomChat(channel: MessageChannel, groupid: String, mcchannel: Channel, user: User, dcp: DiscordConnectedPlayer, toggles: Int, brtoggles: Set[TBMCSystemChatEvent.BroadcastTarget]): Boolean = {
|
def addCustomChat(channel: MessageChannel, groupid: String, mcchannel: Channel, user: User, dcp: DiscordConnectedPlayer, toggles: Int, brtoggles: Set[TBMCSystemChatEvent.BroadcastTarget]): Boolean = {
|
||||||
lastmsgCustom synchronized {
|
lastmsgCustom synchronized {
|
||||||
|
@ -29,34 +28,32 @@ object MCChatCustom {
|
||||||
gid = groupid
|
gid = groupid
|
||||||
}
|
}
|
||||||
val lmd = new MCChatCustom.CustomLMD(channel, user, gid, mcchannel, dcp, toggles, brtoggles)
|
val lmd = new MCChatCustom.CustomLMD(channel, user, gid, mcchannel, dcp, toggles, brtoggles)
|
||||||
lastmsgCustom.add(lmd)
|
lastmsgCustom += lmd
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
def hasCustomChat(channel: Snowflake): Boolean =
|
def hasCustomChat(channel: Snowflake): Boolean =
|
||||||
lastmsgCustom.stream.anyMatch((lmd: MCChatCustom.CustomLMD) => lmd.channel.getId.asLong == channel.asLong)
|
lastmsgCustom.exists(_.channel.getId.asLong == channel.asLong)
|
||||||
|
|
||||||
@Nullable def getCustomChat(channel: Snowflake): CustomLMD =
|
@Nullable def getCustomChat(channel: Snowflake): CustomLMD =
|
||||||
lastmsgCustom.stream.filter((lmd: MCChatCustom.CustomLMD) => lmd.channel.getId.asLong == channel.asLong).findAny.orElse(null)
|
lastmsgCustom.find(_.channel.getId.asLong == channel.asLong).orNull
|
||||||
|
|
||||||
def removeCustomChat(channel: Snowflake): Boolean = {
|
def removeCustomChat(channel: Snowflake): Unit = {
|
||||||
lastmsgCustom synchronized MCChatUtils.lastmsgfromd.remove(channel.asLong)
|
lastmsgCustom synchronized {
|
||||||
lastmsgCustom.removeIf((lmd: MCChatCustom.CustomLMD) => {
|
MCChatUtils.lastmsgfromd.remove(channel.asLong)
|
||||||
def foo(lmd: MCChatCustom.CustomLMD): Boolean = {
|
lastmsgCustom.filterInPlace(lmd => {
|
||||||
if (lmd.channel.getId.asLong != channel.asLong) return false
|
if (lmd.channel.getId.asLong != channel.asLong) return true
|
||||||
lmd.mcchannel match {
|
lmd.mcchannel match {
|
||||||
case room: ChatRoom => room.leaveRoom(lmd.dcp)
|
case room: ChatRoom => room.leaveRoom(lmd.dcp)
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
true
|
false
|
||||||
}
|
|
||||||
|
|
||||||
foo(lmd)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def getCustomChats: util.List[CustomLMD] = Collections.unmodifiableList(lastmsgCustom)
|
def getCustomChats: List[CustomLMD] = lastmsgCustom.toList
|
||||||
|
|
||||||
class CustomLMD private[mcchat](@NonNull channel: MessageChannel, @NonNull user: User, val groupID: String,
|
class CustomLMD private[mcchat](@NonNull channel: MessageChannel, @NonNull user: User, val groupID: String,
|
||||||
@NonNull mcchannel: Channel, val dcp: DiscordConnectedPlayer, var toggles: Int,
|
@NonNull mcchannel: Channel, val dcp: DiscordConnectedPlayer, var toggles: Int,
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Optional
|
||||||
import java.util.concurrent.{LinkedBlockingQueue, TimeoutException}
|
import java.util.concurrent.{LinkedBlockingQueue, TimeoutException}
|
||||||
import java.util.function.{Consumer, Function, Predicate}
|
import java.util.function.{Consumer, Function, Predicate}
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
|
import scala.jdk.OptionConverters.RichOptional
|
||||||
|
|
||||||
object MCChatListener {
|
object MCChatListener {
|
||||||
|
|
||||||
|
@ -111,9 +112,12 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
||||||
foo(ecs)
|
foo(ecs)
|
||||||
}
|
}
|
||||||
val nanoTime: Long = System.nanoTime
|
val nanoTime: Long = System.nanoTime
|
||||||
val doit: MCChatListener.InterruptibleConsumer[MCChatUtils.LastMsgData] = (lastmsgdata: MCChatUtils.LastMsgData) => {
|
val doit = (lastmsgdata: MCChatUtils.LastMsgData) => {
|
||||||
def foo(lastmsgdata: MCChatUtils.LastMsgData): Unit = {
|
if (lastmsgdata.message == null
|
||||||
if (lastmsgdata.message == null || !(authorPlayer == lastmsgdata.message.getEmbeds.get(0).getAuthor.map(_.getName).orElse(null)) || lastmsgdata.time / 1000000000f < nanoTime / 1000000000f - 120 || !(lastmsgdata.mcchannel.ID == e.getChannel.ID) || lastmsgdata.content.length + e.getMessage.length + 1 > 2048) {
|
|| authorPlayer != lastmsgdata.message.getEmbeds.get(0).getAuthor.toScala.map(_.getName).orNull
|
||||||
|
|| lastmsgdata.time / 1000000000f < nanoTime / 1000000000f - 120
|
||||||
|
|| !(lastmsgdata.mcchannel.ID == e.getChannel.ID)
|
||||||
|
|| lastmsgdata.content.length + e.getMessage.length + 1 > 2048) {
|
||||||
lastmsgdata.message = lastmsgdata.channel.createEmbed(embed).block
|
lastmsgdata.message = lastmsgdata.channel.createEmbed(embed).block
|
||||||
lastmsgdata.time = nanoTime
|
lastmsgdata.time = nanoTime
|
||||||
lastmsgdata.mcchannel = e.getChannel
|
lastmsgdata.mcchannel = e.getChannel
|
||||||
|
@ -124,40 +128,35 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
||||||
lastmsgdata.message.edit((mes: MessageEditSpec) => mes.setEmbed(embed.andThen((ecs: EmbedCreateSpec) => ecs.setDescription(lastmsgdata.content)))).block
|
lastmsgdata.message.edit((mes: MessageEditSpec) => mes.setEmbed(embed.andThen((ecs: EmbedCreateSpec) => ecs.setDescription(lastmsgdata.content)))).block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foo(lastmsgdata)
|
|
||||||
}
|
|
||||||
// Checks if the given channel is different than where the message was sent from
|
// Checks if the given channel is different than where the message was sent from
|
||||||
// Or if it was from MC
|
// Or if it was from MC
|
||||||
val isdifferentchannel: Predicate[Snowflake] = (id: Snowflake) => !((e.getSender.isInstanceOf[DiscordSenderBase])) || (e.getSender.asInstanceOf[DiscordSenderBase]).getChannel.getId.asLong != id.asLong
|
val isdifferentchannel: Predicate[Snowflake] = (id: Snowflake) => !((e.getSender.isInstanceOf[DiscordSenderBase])) || (e.getSender.asInstanceOf[DiscordSenderBase]).getChannel.getId.asLong != id.asLong
|
||||||
if (e.getChannel.isGlobal && (e.isFromCommand || isdifferentchannel.test(module.chatChannel.get))) {
|
if (e.getChannel.isGlobal && (e.isFromCommand || isdifferentchannel.test(module.chatChannel.get))) {
|
||||||
if (MCChatUtils.lastmsgdata == null)
|
if (MCChatUtils.lastmsgdata == null)
|
||||||
MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannelMono.block, null)
|
MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannelMono.block, null)
|
||||||
doit.accept(MCChatUtils.lastmsgdata)
|
doit(MCChatUtils.lastmsgdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (data <- MCChatPrivate.lastmsgPerUser) {
|
for (data <- MCChatPrivate.lastmsgPerUser) {
|
||||||
if ((e.isFromCommand || isdifferentchannel.test(data.channel.getId)) && e.shouldSendTo(MCChatUtils.getSender(data.channel.getId, data.user))) {
|
if ((e.isFromCommand || isdifferentchannel.test(data.channel.getId)) && e.shouldSendTo(MCChatUtils.getSender(data.channel.getId, data.user))) {
|
||||||
doit.accept(data)
|
doit(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MCChatCustom.lastmsgCustom synchronized
|
MCChatCustom.lastmsgCustom synchronized {
|
||||||
val iterator = MCChatCustom.lastmsgCustom.iterator
|
MCChatCustom.lastmsgCustom.filterInPlace(lmd => {
|
||||||
while ( {
|
|
||||||
iterator.hasNext
|
|
||||||
}) {
|
|
||||||
val lmd = iterator.next
|
|
||||||
if ((e.isFromCommand || isdifferentchannel.test(lmd.channel.getId)) //Test if msg is from Discord
|
if ((e.isFromCommand || isdifferentchannel.test(lmd.channel.getId)) //Test if msg is from Discord
|
||||||
&& e.getChannel.ID == lmd.mcchannel.ID //If it's from a command, the command msg has been deleted, so we need to send it
|
&& e.getChannel.ID == lmd.mcchannel.ID //If it's from a command, the command msg has been deleted, so we need to send it
|
||||||
&& e.getGroupID == lmd.groupID) { //Check if this is the group we want to test - #58
|
&& e.getGroupID == lmd.groupID) { //Check if this is the group we want to test - #58
|
||||||
if (e.shouldSendTo(lmd.dcp)) { //Check original user's permissions
|
if (e.shouldSendTo(lmd.dcp)) { //Check original user's permissions
|
||||||
doit.accept(lmd)
|
doit(lmd)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
iterator.remove() //If the user no longer has permission, remove the connection
|
|
||||||
lmd.channel.createMessage("The user no longer has permission to view the channel, connection removed.").subscribe
|
lmd.channel.createMessage("The user no longer has permission to view the channel, connection removed.").subscribe
|
||||||
|
return false //If the user no longer has permission, remove the connection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
case ex: InterruptedException =>
|
case ex: InterruptedException =>
|
||||||
|
|
|
@ -19,17 +19,20 @@ import org.bukkit.event.Event
|
||||||
import org.bukkit.event.player.{AsyncPlayerPreLoginEvent, PlayerJoinEvent, PlayerLoginEvent, PlayerQuitEvent}
|
import org.bukkit.event.player.{AsyncPlayerPreLoginEvent, PlayerJoinEvent, PlayerLoginEvent, PlayerQuitEvent}
|
||||||
import org.bukkit.plugin.AuthorNagException
|
import org.bukkit.plugin.AuthorNagException
|
||||||
import org.reactivestreams.Publisher
|
import org.reactivestreams.Publisher
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.scala.publisher.SMono
|
||||||
|
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.util
|
import java.util
|
||||||
import java.util._
|
import java.util._
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import java.util.function.Supplier
|
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
import java.util.stream.{Collectors, Stream}
|
import java.util.stream.Collectors
|
||||||
import javax.annotation.Nullable
|
import javax.annotation.Nullable
|
||||||
|
import scala.collection.concurrent
|
||||||
|
import scala.collection.convert.ImplicitConversions.`map AsJavaMap`
|
||||||
|
import scala.collection.mutable.ListBuffer
|
||||||
|
import scala.jdk.CollectionConverters.CollectionHasAsScala
|
||||||
import scala.jdk.javaapi.CollectionConverters.asScala
|
import scala.jdk.javaapi.CollectionConverters.asScala
|
||||||
|
|
||||||
object MCChatUtils {
|
object MCChatUtils {
|
||||||
|
@ -43,13 +46,13 @@ object MCChatUtils {
|
||||||
@Nullable private[mcchat] var lastmsgdata: MCChatUtils.LastMsgData = null
|
@Nullable private[mcchat] var lastmsgdata: MCChatUtils.LastMsgData = null
|
||||||
private[mcchat] val lastmsgfromd = new LongObjectHashMap[Message] // Last message sent by a Discord user, used for clearing checkmarks
|
private[mcchat] val lastmsgfromd = new LongObjectHashMap[Message] // Last message sent by a Discord user, used for clearing checkmarks
|
||||||
private var module: MinecraftChatModule = null
|
private var module: MinecraftChatModule = null
|
||||||
private val staticExcludedPlugins = new util.HashMap[Class[_ <: Event], util.HashSet[String]]
|
private val staticExcludedPlugins = Map[Class[_ <: Event], util.HashSet[String]]()
|
||||||
|
|
||||||
def updatePlayerList(): Unit = {
|
def updatePlayerList(): Unit = {
|
||||||
val mod = getModule
|
val mod = getModule
|
||||||
if (mod == null || !mod.showPlayerListOnDC.get) return
|
if (mod == null || !mod.showPlayerListOnDC.get) return
|
||||||
if (lastmsgdata != null) updatePL(lastmsgdata)
|
if (lastmsgdata != null) updatePL(lastmsgdata)
|
||||||
MCChatCustom.lastmsgCustom.forEach(MCChatUtils.updatePL)
|
MCChatCustom.lastmsgCustom.foreach(MCChatUtils.updatePL)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def notEnabled = (module == null || !module.disabling) && getModule == null //Allow using things while disabling the module
|
private def notEnabled = (module == null || !module.disabling) && getModule == null //Allow using things while disabling the module
|
||||||
|
@ -85,7 +88,8 @@ object MCChatUtils {
|
||||||
.filter(_ => C.incrementAndGet > 0) //Always true
|
.filter(_ => C.incrementAndGet > 0) //Always true
|
||||||
.map((p) => DPUtils.sanitizeString(p.getDisplayName)).collect(Collectors.joining(", "))
|
.map((p) => DPUtils.sanitizeString(p.getDisplayName)).collect(Collectors.joining(", "))
|
||||||
s(0) = C + " player" + (if (C.get != 1) "s" else "") + " online"
|
s(0) = C + " player" + (if (C.get != 1) "s" else "") + " online"
|
||||||
lmd.channel.asInstanceOf[TextChannel].edit((tce: TextChannelEditSpec) => tce.setTopic(String.join("\n----\n", s)).setReason("Player list update")).subscribe //Don't wait
|
lmd.channel.asInstanceOf[TextChannel].edit((tce: TextChannelEditSpec) =>
|
||||||
|
tce.setTopic(String.join("\n----\n", s: _*)).setReason("Player list update")).subscribe //Don't wait
|
||||||
}
|
}
|
||||||
|
|
||||||
private[mcchat] def checkEssentials(p: Player): Boolean = {
|
private[mcchat] def checkEssentials(p: Player): Boolean = {
|
||||||
|
@ -94,12 +98,12 @@ object MCChatUtils {
|
||||||
!ess.getUser(p).isHidden
|
!ess.getUser(p).isHidden
|
||||||
}
|
}
|
||||||
|
|
||||||
def addSender[T <: DiscordSenderBase](senders: ConcurrentHashMap[String, ConcurrentHashMap[Snowflake, T]], user: User, sender: T): T =
|
def addSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], user: User, sender: T): T =
|
||||||
addSender(senders, user.getId.asString, sender)
|
addSender(senders, user.getId.asString, sender)
|
||||||
|
|
||||||
def addSender[T <: DiscordSenderBase](senders: ConcurrentHashMap[String, ConcurrentHashMap[Snowflake, T]], did: String, sender: T): T = {
|
def addSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], did: String, sender: T): T = {
|
||||||
var map = senders.get(did)
|
val origMap = senders.get(did)
|
||||||
if (map == null) map = new ConcurrentHashMap[Snowflake, T]
|
val map = if (origMap.isEmpty) new ConcurrentHashMap[Snowflake, T] else origMap.get
|
||||||
map.put(sender.getChannel.getId, sender)
|
map.put(sender.getChannel.getId, sender)
|
||||||
senders.put(did, map)
|
senders.put(did, map)
|
||||||
sender
|
sender
|
||||||
|
@ -117,15 +121,12 @@ object MCChatUtils {
|
||||||
else null.asInstanceOf
|
else null.asInstanceOf
|
||||||
}
|
}
|
||||||
|
|
||||||
def forPublicPrivateChat(action: Mono[MessageChannel] => Mono[_]): Mono[_] = {
|
def forPublicPrivateChat(action: SMono[MessageChannel] => SMono[_]): SMono[_] = {
|
||||||
if (notEnabled) return Mono.empty
|
if (notEnabled) return SMono.empty
|
||||||
val list = new util.ArrayList[Mono[_]]
|
val list = MCChatPrivate.lastmsgPerUser.map(data => action(SMono.just(data.channel)))
|
||||||
list.add(action.apply(module.chatChannelMono))
|
.prepend(action(module.chatChannelMono))
|
||||||
for (data <- MCChatPrivate.lastmsgPerUser) {
|
|
||||||
list.add(action.apply(Mono.just(data.channel)))
|
|
||||||
}
|
|
||||||
// lastmsgCustom.forEach(cc -> action.accept(cc.channel)); - Only send relevant messages to custom chat
|
// lastmsgCustom.forEach(cc -> action.accept(cc.channel)); - Only send relevant messages to custom chat
|
||||||
Mono.whenDelayError(list)
|
SMono.whenDelayError(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -135,14 +136,14 @@ object MCChatUtils {
|
||||||
* @param toggle The toggle to check
|
* @param toggle The toggle to check
|
||||||
* @param hookmsg Whether the message is also sent from the hook
|
* @param hookmsg Whether the message is also sent from the hook
|
||||||
*/
|
*/
|
||||||
def forCustomAndAllMCChat(action: Mono[MessageChannel] => Mono[_], @Nullable toggle: ChannelconBroadcast, hookmsg: Boolean): Mono[_] = {
|
def forCustomAndAllMCChat(action: SMono[MessageChannel] => SMono[_], @Nullable toggle: ChannelconBroadcast, hookmsg: Boolean): SMono[_] = {
|
||||||
if (notEnabled) return Mono.empty
|
if (notEnabled) return SMono.empty
|
||||||
val list = new util.ArrayList[Publisher[_]]
|
val list = new ListBuffer[Publisher[_]]
|
||||||
if (!GeneralEventBroadcasterModule.isHooked || !hookmsg) list.add(forPublicPrivateChat(action))
|
if (!GeneralEventBroadcasterModule.isHooked || !hookmsg) list.append(forPublicPrivateChat(action))
|
||||||
val customLMDFunction = (cc: MCChatCustom.CustomLMD) => action.apply(Mono.just(cc.channel))
|
val customLMDFunction = (cc: MCChatCustom.CustomLMD) => action(SMono.just(cc.channel))
|
||||||
if (toggle == null) MCChatCustom.lastmsgCustom.stream.map(customLMDFunction).forEach(list.add(_))
|
if (toggle == null) MCChatCustom.lastmsgCustom.map(customLMDFunction).foreach(list.append(_))
|
||||||
else MCChatCustom.lastmsgCustom.stream.filter((cc) => (cc.toggles & toggle.flag) ne 0).map(customLMDFunction).forEach(list.add(_))
|
else MCChatCustom.lastmsgCustom.filter((cc) => (cc.toggles & (1 << toggle.id)) ne 0).map(customLMDFunction).foreach(list.append(_))
|
||||||
Mono.whenDelayError(list)
|
SMono.whenDelayError(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -152,18 +153,15 @@ object MCChatUtils {
|
||||||
* @param sender The sender to check perms of or null to send to all that has it toggled
|
* @param sender The sender to check perms of or null to send to all that has it toggled
|
||||||
* @param toggle The toggle to check or null to send to all allowed
|
* @param toggle The toggle to check or null to send to all allowed
|
||||||
*/
|
*/
|
||||||
def forAllowedCustomMCChat(action: Mono[MessageChannel] => Mono[_], @Nullable sender: CommandSender, @Nullable toggle: ChannelconBroadcast): Mono[_] = {
|
def forAllowedCustomMCChat(action: SMono[MessageChannel] => SMono[_], @Nullable sender: CommandSender, @Nullable toggle: ChannelconBroadcast): SMono[_] = {
|
||||||
if (notEnabled) return Mono.empty
|
if (notEnabled) return SMono.empty
|
||||||
val st = MCChatCustom.lastmsgCustom.stream.filter((clmd) => {
|
val st = MCChatCustom.lastmsgCustom.filter(clmd => { //new TBMCChannelConnectFakeEvent(sender, clmd.mcchannel).shouldSendTo(clmd.dcp) - Thought it was this simple hehe - Wait, it *should* be this simple
|
||||||
def foo(clmd: CustomLMD): Boolean = { //new TBMCChannelConnectFakeEvent(sender, clmd.mcchannel).shouldSendTo(clmd.dcp) - Thought it was this simple hehe - Wait, it *should* be this simple
|
if (toggle != null && ((clmd.toggles & (1 << toggle.id)) eq 0)) false //If null then allow
|
||||||
if (toggle != null && ((clmd.toggles & (1 << toggle.id)) eq 0)) return false //If null then allow
|
else if (sender == null) true
|
||||||
if (sender == null) return true
|
else clmd.groupID.equals(clmd.mcchannel.getGroupID(sender))
|
||||||
clmd.groupID.equals(clmd.mcchannel.getGroupID(sender))
|
}).map(cc => action.apply(SMono.just(cc.channel))) //TODO: Send error messages on channel connect
|
||||||
}
|
//Mono.whenDelayError((() => st.iterator).asInstanceOf[java.lang.Iterable[Mono[_]]]) //Can't convert as an iterator or inside the stream, but I can convert it as a stream
|
||||||
|
SMono.whenDelayError(st)
|
||||||
foo(clmd)
|
|
||||||
}).map((cc) => action.apply(Mono.just(cc.channel))) //TODO: Send error messages on channel connect
|
|
||||||
Mono.whenDelayError(st.iterator) //Can't convert as an iterator or inside the stream, but I can convert it as a stream
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,47 +172,45 @@ object MCChatUtils {
|
||||||
* @param toggle The toggle to check or null to send to all allowed
|
* @param toggle The toggle to check or null to send to all allowed
|
||||||
* @param hookmsg Whether the message is also sent from the hook
|
* @param hookmsg Whether the message is also sent from the hook
|
||||||
*/
|
*/
|
||||||
def forAllowedCustomAndAllMCChat(action: Mono[MessageChannel] => Mono[_], @Nullable sender: CommandSender, @Nullable toggle: ChannelconBroadcast, hookmsg: Boolean): Mono[_] = {
|
def forAllowedCustomAndAllMCChat(action: SMono[MessageChannel] => SMono[_], @Nullable sender: CommandSender, @Nullable toggle: ChannelconBroadcast, hookmsg: Boolean): SMono[_] = {
|
||||||
if (notEnabled) return Mono.empty
|
if (notEnabled) return SMono.empty
|
||||||
val cc = forAllowedCustomMCChat(action, sender, toggle)
|
val cc = forAllowedCustomMCChat(action, sender, toggle)
|
||||||
if (!GeneralEventBroadcasterModule.isHooked || !hookmsg) return Mono.whenDelayError(forPublicPrivateChat(action), cc)
|
if (!GeneralEventBroadcasterModule.isHooked || !hookmsg) return SMono.whenDelayError(Array(forPublicPrivateChat(action), cc))
|
||||||
Mono.whenDelayError(cc)
|
SMono.whenDelayError(Array(cc))
|
||||||
}
|
}
|
||||||
|
|
||||||
def send(message: String): Mono[MessageChannel] => Mono[_] = (ch: Mono[MessageChannel]) => ch.flatMap((mc: MessageChannel) => {
|
def send(message: String): SMono[MessageChannel] => SMono[_] = _.flatMap((mc: MessageChannel) => {
|
||||||
def foo(mc: MessageChannel) = {
|
|
||||||
resetLastMessage(mc)
|
resetLastMessage(mc)
|
||||||
mc.createMessage(DPUtils.sanitizeString(message))
|
SMono(mc.createMessage(DPUtils.sanitizeString(message)))
|
||||||
}
|
|
||||||
|
|
||||||
foo(mc)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
def forAllowedMCChat(action: Mono[MessageChannel] => Mono[_], event: TBMCSystemChatEvent): Mono[_] = {
|
def forAllowedMCChat(action: SMono[MessageChannel] => SMono[_], event: TBMCSystemChatEvent): SMono[_] = {
|
||||||
if (notEnabled) return Mono.empty
|
if (notEnabled) return SMono.empty
|
||||||
val list = new util.ArrayList[Mono[_]]
|
val list = new ListBuffer[SMono[_]]
|
||||||
if (event.getChannel.isGlobal) list.add(action.apply(module.chatChannelMono))
|
if (event.getChannel.isGlobal) list.append(action(module.chatChannelMono))
|
||||||
for (data <- MCChatPrivate.lastmsgPerUser)
|
for (data <- MCChatPrivate.lastmsgPerUser)
|
||||||
if (event.shouldSendTo(getSender(data.channel.getId, data.user))) list.add(action.apply(Mono.just(data.channel))) //TODO: Only store ID?}
|
if (event.shouldSendTo(getSender(data.channel.getId, data.user)))
|
||||||
MCChatCustom.lastmsgCustom.stream.filter((clmd) => {
|
list.append(action(SMono.just(data.channel))) //TODO: Only store ID?
|
||||||
def foo(clmd: CustomLMD): Boolean = {
|
MCChatCustom.lastmsgCustom.filter(clmd =>
|
||||||
clmd.brtoggles.contains(event.getTarget) && event.shouldSendTo(clmd.dcp)
|
clmd.brtoggles.contains(event.getTarget) && event.shouldSendTo(clmd.dcp))
|
||||||
}
|
.map(clmd => action(SMono.just(clmd.channel))).forEach(elem => {
|
||||||
|
list.append(elem)
|
||||||
foo(clmd)
|
()
|
||||||
}).map((clmd) => action.apply(Mono.just(clmd.channel))).forEach(list.add(_))
|
})
|
||||||
Mono.whenDelayError(list)
|
SMono.whenDelayError(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will find the best sender to use: if the player is online, use that, if not but connected then use that etc.
|
* This method will find the best sender to use: if the player is online, use that, if not but connected then use that etc.
|
||||||
*/
|
*/
|
||||||
private[mcchat] def getSender(channel: Snowflake, author: User) = { //noinspection OptionalGetWithoutIsPresent
|
private[mcchat] def getSender(channel: Snowflake, author: User): DiscordSenderBase = { //noinspection OptionalGetWithoutIsPresent
|
||||||
Stream.of[Supplier[Optional[DiscordSenderBase]]]( // https://stackoverflow.com/a/28833677/2703239
|
List[() => DiscordSenderBase]( // https://stackoverflow.com/a/28833677/2703239
|
||||||
() => Optional.ofNullable(getSender(OnlineSenders, channel, author)), // Find first non-null
|
() => getSender[DiscordSenderBase](OnlineSenders, channel, author), // Find first non-null
|
||||||
() => Optional.ofNullable(getSender(ConnectedSenders, channel, author)), // This doesn't support the public chat, but it'll always return null for it
|
() => getSender[DiscordSenderBase](ConnectedSenders, channel, author), // This doesn't support the public chat, but it'll always return null for it
|
||||||
() => Optional.ofNullable(getSender(UnconnectedSenders, channel, author)), //
|
() => getSender[DiscordSenderBase](UnconnectedSenders, channel, author), //
|
||||||
() => Optional.of(addSender(UnconnectedSenders, author, new DiscordSender(author, DiscordPlugin.dc.getChannelById(channel).block.asInstanceOf[MessageChannel])))).map(_.get).filter(_.isPresent).map(_.get).findFirst.get
|
() => addSender[DiscordSenderBase](UnconnectedSenders, author,
|
||||||
|
new DiscordSender(author, SMono(DiscordPlugin.dc.getChannelById(channel)).block().asInstanceOf[MessageChannel])))
|
||||||
|
.map(_.apply()).find(sender => sender != null).get
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -226,7 +222,7 @@ object MCChatUtils {
|
||||||
def resetLastMessage(channel: Channel): Unit = {
|
def resetLastMessage(channel: Channel): Unit = {
|
||||||
if (notEnabled) return
|
if (notEnabled) return
|
||||||
if (channel.getId.asLong == module.chatChannel.get.asLong) {
|
if (channel.getId.asLong == module.chatChannel.get.asLong) {
|
||||||
if (lastmsgdata == null) lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannelMono.block, null)
|
if (lastmsgdata == null) lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannelMono.block(), null)
|
||||||
else lastmsgdata.message = null
|
else lastmsgdata.message = null
|
||||||
return
|
return
|
||||||
} // Don't set the whole object to null, the player and channel information should be preserved
|
} // Don't set the whole object to null, the player and channel information should be preserved
|
||||||
|
@ -241,25 +237,23 @@ object MCChatUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
def addStaticExcludedPlugin(event: Class[_ <: Event], plugin: String): util.HashSet[String] =
|
def addStaticExcludedPlugin(event: Class[_ <: Event], plugin: String): util.HashSet[String] =
|
||||||
staticExcludedPlugins.compute(event, (e: Class[_ <: Event], hs: util.HashSet[String]) =>
|
staticExcludedPlugins.compute(event, (_, hs: util.HashSet[String]) =>
|
||||||
if (hs == null) Sets.newHashSet(plugin) else if (hs.add(plugin)) hs else hs)
|
if (hs == null) Sets.newHashSet(plugin) else if (hs.add(plugin)) hs else hs)
|
||||||
|
|
||||||
def callEventExcludingSome(event: Event): Unit = {
|
def callEventExcludingSome(event: Event): Unit = {
|
||||||
if (notEnabled) return
|
if (notEnabled) return
|
||||||
val second = staticExcludedPlugins.get(event.getClass)
|
val second = staticExcludedPlugins.get(event.getClass)
|
||||||
val first = module.excludedPlugins.get
|
val first = module.excludedPlugins.get
|
||||||
val both = if (second == null) first
|
val both = if (second.isEmpty) first
|
||||||
else util.Arrays.copyOf(first, first.length + second.size)
|
else util.Arrays.copyOf(first, first.length + second.size)
|
||||||
var i = first.length
|
var i = first.length
|
||||||
if (second != null) {
|
if (second.nonEmpty) {
|
||||||
for (plugin <- second) {
|
for (plugin <- second.get.asScala) {
|
||||||
both({
|
both(i) = plugin
|
||||||
i += 1;
|
i += 1
|
||||||
i - 1
|
|
||||||
}) = plugin
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
callEventExcluding(event, false, both)
|
callEventExcluding(event, false, both: _*)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,21 +269,18 @@ object MCChatUtils {
|
||||||
if (event.isAsynchronous) {
|
if (event.isAsynchronous) {
|
||||||
if (Thread.holdsLock(Bukkit.getPluginManager)) throw new IllegalStateException(event.getEventName + " cannot be triggered asynchronously from inside synchronized code.")
|
if (Thread.holdsLock(Bukkit.getPluginManager)) throw new IllegalStateException(event.getEventName + " cannot be triggered asynchronously from inside synchronized code.")
|
||||||
if (Bukkit.getServer.isPrimaryThread) throw new IllegalStateException(event.getEventName + " cannot be triggered asynchronously from primary server thread.")
|
if (Bukkit.getServer.isPrimaryThread) throw new IllegalStateException(event.getEventName + " cannot be triggered asynchronously from primary server thread.")
|
||||||
fireEventExcluding(event, only, plugins)
|
fireEventExcluding(event, only, plugins: _*)
|
||||||
}
|
}
|
||||||
else Bukkit.getPluginManager synchronized fireEventExcluding(event, only, plugins)
|
else Bukkit.getPluginManager synchronized fireEventExcluding(event, only, plugins: _*)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def fireEventExcluding(event: Event, only: Boolean, plugins: String*): Unit = {
|
private def fireEventExcluding(event: Event, only: Boolean, plugins: String*): Unit = {
|
||||||
val handlers = event.getHandlers // Code taken from SimplePluginManager in Spigot-API
|
val handlers = event.getHandlers // Code taken from SimplePluginManager in Spigot-API
|
||||||
val listeners = handlers.getRegisteredListeners
|
val listeners = handlers.getRegisteredListeners
|
||||||
val server = Bukkit.getServer
|
val server = Bukkit.getServer
|
||||||
for (registration <- listeners) {
|
for (registration <- listeners) { // Modified to exclude plugins
|
||||||
if (!registration.getPlugin.isEnabled || util.Arrays.stream(plugins).anyMatch((p: String) => only ^ p.equalsIgnoreCase(registration.getPlugin.getName))) {
|
if (registration.getPlugin.isEnabled
|
||||||
continue //todo: continue is not supported
|
&& !plugins.exists(only ^ _.equalsIgnoreCase(registration.getPlugin.getName))) try registration.callEvent(event)
|
||||||
// Modified to exclude plugins
|
|
||||||
}
|
|
||||||
try registration.callEvent(event)
|
|
||||||
catch {
|
catch {
|
||||||
case ex: AuthorNagException =>
|
case ex: AuthorNagException =>
|
||||||
val plugin = registration.getPlugin
|
val plugin = registration.getPlugin
|
||||||
|
@ -308,12 +299,8 @@ object MCChatUtils {
|
||||||
*/
|
*/
|
||||||
def callLoginEvents(dcp: DiscordConnectedPlayer): Unit = {
|
def callLoginEvents(dcp: DiscordConnectedPlayer): Unit = {
|
||||||
val loginFail = (kickMsg: String) => {
|
val loginFail = (kickMsg: String) => {
|
||||||
def foo(kickMsg: String): Unit = {
|
|
||||||
dcp.sendMessage("Minecraft chat disabled, as the login failed: " + kickMsg)
|
dcp.sendMessage("Minecraft chat disabled, as the login failed: " + kickMsg)
|
||||||
MCChatPrivate.privateMCChat(dcp.getChannel, start = false, dcp.getUser, dcp.getChromaUser)
|
MCChatPrivate.privateMCChat(dcp.getChannel, start = false, dcp.getUser, dcp.getChromaUser)
|
||||||
}
|
|
||||||
|
|
||||||
foo(kickMsg)
|
|
||||||
} //Probably also happens if the user is banned or so
|
} //Probably also happens if the user is banned or so
|
||||||
val event = new AsyncPlayerPreLoginEvent(dcp.getName, InetAddress.getLoopbackAddress, dcp.getUniqueId)
|
val event = new AsyncPlayerPreLoginEvent(dcp.getName, InetAddress.getLoopbackAddress, dcp.getUniqueId)
|
||||||
callEventExcludingSome(event)
|
callEventExcludingSome(event)
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
package buttondevteam.discordplugin.mcchat
|
package buttondevteam.discordplugin.mcchat
|
||||||
|
|
||||||
import buttondevteam.core.component.channel.Channel
|
import buttondevteam.core.component.channel.Channel
|
||||||
import buttondevteam.discordplugin.{ChannelconBroadcast, DPUtils, DiscordConnectedPlayer, DiscordPlugin}
|
|
||||||
import buttondevteam.discordplugin.playerfaker.ServerWatcher
|
import buttondevteam.discordplugin.playerfaker.ServerWatcher
|
||||||
import buttondevteam.discordplugin.playerfaker.perm.LPInjector
|
import buttondevteam.discordplugin.playerfaker.perm.LPInjector
|
||||||
import buttondevteam.discordplugin.util.DPState
|
import buttondevteam.discordplugin.util.DPState
|
||||||
import buttondevteam.lib.{TBMCCoreAPI, TBMCSystemChatEvent}
|
import buttondevteam.discordplugin.{ChannelconBroadcast, DPUtils, DiscordConnectedPlayer, DiscordPlugin}
|
||||||
import buttondevteam.lib.architecture.{Component, ConfigData, ReadOnlyConfigData}
|
import buttondevteam.lib.architecture.{Component, ConfigData, ReadOnlyConfigData}
|
||||||
|
import buttondevteam.lib.{TBMCCoreAPI, TBMCSystemChatEvent}
|
||||||
import com.google.common.collect.Lists
|
import com.google.common.collect.Lists
|
||||||
import discord4j.common.util.Snowflake
|
import discord4j.common.util.Snowflake
|
||||||
import discord4j.core.`object`.entity.channel.MessageChannel
|
import discord4j.core.`object`.entity.channel.MessageChannel
|
||||||
import discord4j.rest.util.Color
|
import discord4j.rest.util.Color
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import reactor.core.publisher.Mono
|
import reactor.core.publisher.Mono
|
||||||
|
import reactor.core.scala.publisher.SMono
|
||||||
|
|
||||||
import java.util
|
import java.util
|
||||||
import java.util.{Objects, UUID}
|
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
|
import java.util.{Objects, UUID}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides Minecraft chat connection to Discord. Commands may be used either in a public chat (limited) or in a DM.
|
* Provides Minecraft chat connection to Discord. Commands may be used either in a public chat (limited) or in a DM.
|
||||||
|
@ -45,7 +46,7 @@ class MinecraftChatModule extends Component[DiscordPlugin] {
|
||||||
*/
|
*/
|
||||||
val chatChannel: ReadOnlyConfigData[Snowflake] = DPUtils.snowflakeData(getConfig, "chatChannel", 0L)
|
val chatChannel: ReadOnlyConfigData[Snowflake] = DPUtils.snowflakeData(getConfig, "chatChannel", 0L)
|
||||||
|
|
||||||
def chatChannelMono: Mono[MessageChannel] = DPUtils.getMessageChannel(chatChannel.getPath, chatChannel.get)
|
def chatChannelMono: SMono[MessageChannel] = DPUtils.getMessageChannel(chatChannel.getPath, chatChannel.get)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The channel where the plugin can log when it mutes a player on Discord because of a Minecraft mute
|
* The channel where the plugin can log when it mutes a player on Discord because of a Minecraft mute
|
||||||
|
|
Loading…
Reference in a new issue