Implicit classes for conversion, more fixing
Added 'extension methods' to convert to Scala-friendly formats easily
This commit is contained in:
parent
7296ebd2f8
commit
a0a7f756c4
17 changed files with 286 additions and 260 deletions
|
@ -4,7 +4,7 @@ import buttondevteam.discordplugin.ChannelconBroadcast.ChannelconBroadcast
|
|||
import buttondevteam.discordplugin.mcchat.MCChatUtils
|
||||
import discord4j.core.`object`.entity.Message
|
||||
import discord4j.core.`object`.entity.channel.MessageChannel
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.core.scala.publisher.SMono
|
||||
|
||||
import javax.annotation.Nullable
|
||||
|
||||
|
@ -20,8 +20,8 @@ object ChromaBot {
|
|||
*
|
||||
* @param message The message to send, duh (use {@link MessageChannel# createMessage ( String )})
|
||||
*/
|
||||
def sendMessage(message: java.util.function.Function[Mono[MessageChannel], Mono[Message]]): Unit =
|
||||
MCChatUtils.forPublicPrivateChat(message.apply(_)).subscribe
|
||||
def sendMessage(message: SMono[MessageChannel] => SMono[Message]): Unit =
|
||||
MCChatUtils.forPublicPrivateChat(message).subscribe
|
||||
|
||||
/**
|
||||
* Send a message to the chat channels, private chats and custom chats.
|
||||
|
@ -29,8 +29,8 @@ object ChromaBot {
|
|||
* @param message The message to send, duh
|
||||
* @param toggle The toggle type for channelcon
|
||||
*/
|
||||
def sendMessageCustomAsWell(message: Function[Mono[MessageChannel], Mono[Message]], @Nullable toggle: ChannelconBroadcast): Unit =
|
||||
MCChatUtils.forCustomAndAllMCChat(message.apply, toggle, false).subscribe
|
||||
def sendMessageCustomAsWell(message: SMono[MessageChannel] => SMono[Message], @Nullable toggle: ChannelconBroadcast): Unit =
|
||||
MCChatUtils.forCustomAndAllMCChat(message.apply, toggle, hookmsg = false).subscribe
|
||||
|
||||
def updatePlayerList(): Unit =
|
||||
MCChatUtils.updatePlayerList()
|
||||
|
|
|
@ -5,8 +5,9 @@ import buttondevteam.lib.architecture.{Component, ConfigData, IHaveConfig, ReadO
|
|||
import discord4j.common.util.Snowflake
|
||||
import discord4j.core.`object`.entity.channel.MessageChannel
|
||||
import discord4j.core.`object`.entity.{Guild, Message, Role}
|
||||
import discord4j.core.spec.EmbedCreateSpec
|
||||
import reactor.core.scala.publisher.SMono
|
||||
import discord4j.core.spec.{EmbedCreateSpec, Spec}
|
||||
import reactor.core.publisher.{Flux, Mono}
|
||||
import reactor.core.scala.publisher.{SFlux, SMono}
|
||||
|
||||
import java.util
|
||||
import java.util.Comparator
|
||||
|
@ -206,4 +207,17 @@ object DPUtils {
|
|||
getMessageChannel(config.getPath, config.get)
|
||||
|
||||
def ignoreError[T](mono: SMono[T]): SMono[T] = mono.onErrorResume((_: Throwable) => SMono.empty)
|
||||
|
||||
implicit class MonoExtensions[T](mono: Mono[T]) {
|
||||
def ^^(): SMono[T] = SMono(mono)
|
||||
}
|
||||
|
||||
implicit class FluxExtensions[T](flux: Flux[T]) {
|
||||
def ^^(): SFlux[T] = SFlux(flux)
|
||||
}
|
||||
|
||||
implicit class SpecExtensions[T <: Spec[_]](spec: T) {
|
||||
def ^^(): Unit = ()
|
||||
}
|
||||
|
||||
}
|
|
@ -89,7 +89,7 @@ import scala.annotation.tailrec
|
|||
|
||||
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 != lastanntime) lastAnnouncementTime.set(lastanntime) // If sending succeeded
|
||||
} catch {
|
||||
case e: Exception =>
|
||||
e.printStackTrace()
|
||||
|
|
|
@ -17,7 +17,9 @@ import org.bukkit.entity.Player
|
|||
var WaitingToConnect: HashBiMap[String, String] = HashBiMap.create
|
||||
}
|
||||
|
||||
@CommandClass(helpText = Array(Array("Connect command", "This command lets you connect your account with a Minecraft account. This allows using the private Minecraft chat and other things."))) class ConnectCommand extends ICommand2DC {
|
||||
@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.")) class ConnectCommand extends ICommand2DC {
|
||||
@Command2.Subcommand def `def`(sender: Command2DCSender, Minecraftname: String): Boolean = {
|
||||
val message = sender.getMessage
|
||||
val channel = message.getChannel.block
|
||||
|
|
|
@ -16,7 +16,7 @@ class DebugCommand extends ICommand2DC {
|
|||
.map((u: User) => SMono(u.asMember(DiscordPlugin.mainServer.getId))).getOrElse(SMono.empty))
|
||||
.flatMap((m: Member) => DiscordPlugin.plugin.modRole.get
|
||||
.map(mr => m.getRoleIds.stream.anyMatch((r: Snowflake) => r == mr.getId))
|
||||
.switchIfEmpty(SMono.fromCallable(() => DiscordPlugin.mainServer.getOwnerId.asLong eq m.getId.asLong)))
|
||||
.switchIfEmpty(SMono.fromCallable(() => DiscordPlugin.mainServer.getOwnerId.asLong == m.getId.asLong)))
|
||||
.onErrorResume(_ => SMono.just(false)) //Role not found
|
||||
.subscribe(success => {
|
||||
if (success) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import buttondevteam.discordplugin.DiscordPlugin
|
|||
import buttondevteam.lib.TBMCDebugMessageEvent
|
||||
import discord4j.core.`object`.entity.channel.MessageChannel
|
||||
import org.bukkit.event.{EventHandler, Listener}
|
||||
import reactor.core.scala.publisher.SMono
|
||||
|
||||
object DebugMessageListener {
|
||||
private def SendMessage(message: String): Unit = {
|
||||
|
@ -16,7 +17,7 @@ object DebugMessageListener {
|
|||
sb.append("```").append("\n")
|
||||
sb.append(if (message.length > 2000) message.substring(0, 2000) else message).append("\n")
|
||||
sb.append("```")
|
||||
mc.flatMap((ch: MessageChannel) => ch.createMessage(sb.toString)).subscribe
|
||||
mc.flatMap((ch: MessageChannel) => SMono(ch.createMessage(sb.toString))).subscribe
|
||||
} catch {
|
||||
case ex: Exception =>
|
||||
ex.printStackTrace()
|
||||
|
|
|
@ -107,7 +107,7 @@ class FunModule extends Component[DiscordPlugin] with Listener {
|
|||
* Answers for a recognized question. Selected randomly.
|
||||
*/
|
||||
final private val serverReadyAnswers: ConfigData[util.ArrayList[String]] =
|
||||
getConfig.getData("serverReadyAnswers", () => Lists.newArrayList(FunModule.serverReadyStrings))
|
||||
getConfig.getData("serverReadyAnswers", () => Lists.newArrayList(FunModule.serverReadyStrings): _*)
|
||||
|
||||
private def createUsableServerReadyStrings(): Unit =
|
||||
IntStream.range(0, serverReadyAnswers.get.size).forEach((i: Int) => FunModule.usableServerReadyStrings.add(i.toShort))
|
||||
|
|
|
@ -39,9 +39,10 @@ object MCChatCustom {
|
|||
@Nullable def getCustomChat(channel: Snowflake): CustomLMD =
|
||||
lastmsgCustom.find(_.channel.getId.asLong == channel.asLong).orNull
|
||||
|
||||
def removeCustomChat(channel: Snowflake): Unit = {
|
||||
def removeCustomChat(channel: Snowflake): Boolean = {
|
||||
lastmsgCustom synchronized {
|
||||
MCChatUtils.lastmsgfromd.remove(channel.asLong)
|
||||
val count = lastmsgCustom.size
|
||||
lastmsgCustom.filterInPlace(lmd => {
|
||||
if (lmd.channel.getId.asLong != channel.asLong) return true
|
||||
lmd.mcchannel match {
|
||||
|
@ -50,6 +51,7 @@ object MCChatCustom {
|
|||
}
|
||||
false
|
||||
})
|
||||
lastmsgCustom.size < count
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package buttondevteam.discordplugin.mcchat
|
||||
|
||||
import buttondevteam.core.ComponentManager
|
||||
import buttondevteam.core.component.channel.Channel
|
||||
import buttondevteam.discordplugin._
|
||||
import buttondevteam.discordplugin.listeners.CommandListener
|
||||
import buttondevteam.discordplugin.playerfaker.{VanillaCommandListener, VanillaCommandListener14, VanillaCommandListener15}
|
||||
|
@ -24,10 +23,10 @@ import reactor.core.scala.publisher.{SFlux, SMono}
|
|||
|
||||
import java.time.Instant
|
||||
import java.util
|
||||
import java.util.Optional
|
||||
import java.util.concurrent.{LinkedBlockingQueue, TimeoutException}
|
||||
import java.util.function.{Consumer, Function, Predicate}
|
||||
import java.util.function.{Consumer, Predicate}
|
||||
import java.util.stream.Collectors
|
||||
import scala.jdk.CollectionConverters.SetHasAsScala
|
||||
import scala.jdk.OptionConverters.RichOptional
|
||||
|
||||
object MCChatListener {
|
||||
|
@ -133,7 +132,7 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
|||
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 (MCChatUtils.lastmsgdata == null)
|
||||
MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannelMono.block, null)
|
||||
MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannelMono.block(), null)
|
||||
doit(MCChatUtils.lastmsgdata)
|
||||
}
|
||||
|
||||
|
@ -146,7 +145,7 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
|||
MCChatCustom.lastmsgCustom.filterInPlace(lmd => {
|
||||
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.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
|
||||
doit(lmd)
|
||||
}
|
||||
|
@ -254,9 +253,7 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
|||
.filter(channel => {
|
||||
MCChatUtils.resetLastMessage(channel)
|
||||
recevents.add(ev)
|
||||
if (rectask != null) {
|
||||
return true
|
||||
}
|
||||
if (rectask == null) {
|
||||
recrun = () => {
|
||||
recthread = Thread.currentThread
|
||||
processDiscordToMC()
|
||||
|
@ -265,7 +262,8 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
|||
}
|
||||
}
|
||||
rectask = Bukkit.getScheduler.runTaskAsynchronously(DiscordPlugin.plugin, recrun) //Start message processing
|
||||
return true
|
||||
}
|
||||
true
|
||||
}).map(_ => false).defaultIfEmpty(true)
|
||||
}
|
||||
|
||||
|
@ -299,47 +297,44 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
|||
val dsender: DiscordSenderBase = MCChatUtils.getSender(event.getMessage.getChannelId, sender)
|
||||
val user: DiscordPlayer = dsender.getChromaUser
|
||||
|
||||
def replaceUserMentions(): Unit = {
|
||||
for (u <- SFlux(event.getMessage.getUserMentions).toIterable()) { //TODO: Role mentions
|
||||
dmessage = dmessage.replace(u.getMention, "@" + u.getUsername) // TODO: IG Formatting
|
||||
val m: Optional[Member] = u.asMember(DiscordPlugin.mainServer.getId).onErrorResume((t: Throwable) => Mono.empty).blockOptional
|
||||
val m = u.asMember(DiscordPlugin.mainServer.getId).onErrorResume(_ => Mono.empty).blockOptional
|
||||
if (m.isPresent) {
|
||||
val mm: Member = m.get
|
||||
val nick: String = mm.getDisplayName
|
||||
dmessage = dmessage.replace(mm.getNicknameMention, "@" + nick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
replaceUserMentions()
|
||||
|
||||
def replaceChannelMentions(): Unit = {
|
||||
for (ch <- SFlux(event.getGuild.flux).flatMap(_.getChannels).toIterable()) {
|
||||
dmessage = dmessage.replace(ch.getMention, "#" + ch.getName)
|
||||
}
|
||||
}
|
||||
|
||||
replaceChannelMentions()
|
||||
|
||||
def replaceEmojis(): Unit = {
|
||||
dmessage = EmojiParser.parseToAliases(dmessage, EmojiParser.FitzpatrickAction.PARSE) //Converts emoji to text- TODO: Add option to disable (resource pack?)
|
||||
dmessage = dmessage.replaceAll(":(\\S+)\\|type_(?:(\\d)|(1)_2):", ":$1::skin-tone-$2:") //Convert to Discord's format so it still shows up
|
||||
dmessage = dmessage.replaceAll("<a?:(\\S+):(\\d+)>", ":$1:") //We don't need info about the custom emojis, just display their text
|
||||
val getChatMessage: Function[String, String] = (msg: String) => //
|
||||
msg + (if (event.getMessage.getAttachments.size > 0) {
|
||||
"\n" + event.getMessage.getAttachments.stream.map(_.getUrl).collect(Collectors.joining("\n"))
|
||||
}
|
||||
else {
|
||||
""
|
||||
})
|
||||
val clmd: MCChatCustom.CustomLMD = MCChatCustom.getCustomChat(event.getMessage.getChannelId)
|
||||
var react: Boolean = false
|
||||
val sendChannel: MessageChannel = event.getMessage.getChannel.block
|
||||
val isPrivate: Boolean = sendChannel.isInstanceOf[PrivateChannel]
|
||||
if (dmessage.startsWith("/")) { // Ingame command
|
||||
if (handleIngameCommand(event, dmessage, dsender, user, clmd, isPrivate)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
else { // Not a command
|
||||
react = handleIngameMessage(event, dmessage, dsender, user, getChatMessage, clmd, isPrivate)
|
||||
}
|
||||
if (react) {
|
||||
|
||||
replaceEmojis()
|
||||
val clmd = MCChatCustom.getCustomChat(event.getMessage.getChannelId)
|
||||
val sendChannel = event.getMessage.getChannel.block
|
||||
val isPrivate = sendChannel.isInstanceOf[PrivateChannel]
|
||||
|
||||
def addCheckmark() = {
|
||||
try {
|
||||
val lmfd: Message = MCChatUtils.lastmsgfromd.get(event.getMessage.getChannelId.asLong)
|
||||
if (lmfd != null) {
|
||||
val lmfd = MCChatUtils.lastmsgfromd.get(event.getMessage.getChannelId.asLong)
|
||||
if (lmfd != null)
|
||||
lmfd.removeSelfReaction(DiscordPlugin.DELIVERED_REACTION).subscribe // Remove it no matter what, we know it's there 99.99% of the time
|
||||
}
|
||||
} catch {
|
||||
case e: Exception =>
|
||||
TBMCCoreAPI.SendException("An error occured while removing reactions from chat!", e, module)
|
||||
|
@ -347,103 +342,111 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
|||
MCChatUtils.lastmsgfromd.put(event.getMessage.getChannelId.asLong, event.getMessage)
|
||||
event.getMessage.addReaction(DiscordPlugin.DELIVERED_REACTION).subscribe
|
||||
}
|
||||
|
||||
if (dmessage.startsWith("/")) // Ingame command
|
||||
handleIngameCommand(event, dmessage, dsender, user, clmd, isPrivate)
|
||||
else if (handleIngameMessage(event, dmessage, dsender, user, clmd, isPrivate)) // Not a command
|
||||
addCheckmark()
|
||||
} catch {
|
||||
case e: Exception =>
|
||||
TBMCCoreAPI.SendException("An error occured while handling message \"" + dmessage + "\"!", e, module)
|
||||
}
|
||||
}
|
||||
|
||||
private def handleIngameMessage(event: MessageCreateEvent, dmessage: String, dsender: DiscordSenderBase, user: DiscordPlayer, getChatMessage: Function[String, String], clmd: MCChatCustom.CustomLMD, isPrivate: Boolean): Boolean = {
|
||||
var react: Boolean = false
|
||||
if (dmessage.isEmpty && event.getMessage.getAttachments.size == 0 && !(isPrivate) && (event.getMessage.getType eq Message.Type.CHANNEL_PINNED_MESSAGE)) {
|
||||
val rtr: Channel.RecipientTestResult = if (clmd != null) {
|
||||
clmd.mcchannel.getRTR(clmd.dcp)
|
||||
}
|
||||
else {
|
||||
dsender.getChromaUser.channel.get.getRTR(dsender)
|
||||
}
|
||||
TBMCChatAPI.SendSystemMessage(if (clmd != null) clmd.mcchannel else dsender.getChromaUser.channel.get, rtr,
|
||||
(dsender match {
|
||||
case player: Player =>
|
||||
player.getDisplayName
|
||||
case _ =>
|
||||
dsender.getName
|
||||
}) + " pinned a message on Discord.", TBMCSystemChatEvent.BroadcastTarget.ALL)
|
||||
}
|
||||
else {
|
||||
val cmb: ChatMessage.ChatMessageBuilder = ChatMessage.builder(dsender, user, getChatMessage.apply(dmessage)).fromCommand(false)
|
||||
if (clmd != null) {
|
||||
TBMCChatAPI.SendChatMessage(cmb.permCheck(clmd.dcp).build, clmd.mcchannel)
|
||||
}
|
||||
else {
|
||||
TBMCChatAPI.SendChatMessage(cmb.build)
|
||||
}
|
||||
react = true
|
||||
}
|
||||
react
|
||||
/**
|
||||
* Handles a message coming from Discord to Minecraft.
|
||||
*
|
||||
* @param event The Discord event
|
||||
* @param dmessage The message itself
|
||||
* @param dsender The sender who sent it
|
||||
* @param user The Chroma user of the sender
|
||||
* @param clmd Custom chat last message data (if in a custom chat)
|
||||
* @param isPrivate Whether the chat is private
|
||||
* @return Whether the bot should react with a checkmark
|
||||
*/
|
||||
private def handleIngameMessage(event: MessageCreateEvent, dmessage: String, dsender: DiscordSenderBase, user: DiscordPlayer,
|
||||
clmd: MCChatCustom.CustomLMD, isPrivate: Boolean): Boolean = {
|
||||
def getAttachmentText = {
|
||||
val att = event.getMessage.getAttachments.asScala
|
||||
if (att.nonEmpty) att map (_.getUrl) mkString "\n"
|
||||
else ""
|
||||
}
|
||||
|
||||
private def handleIngameCommand(event: MessageCreateEvent, dmessage: String, dsender: DiscordSenderBase, user: DiscordPlayer, clmd: MCChatCustom.CustomLMD, isPrivate: Boolean): Boolean = {
|
||||
if (!(isPrivate)) {
|
||||
event.getMessage.delete.subscribe
|
||||
}
|
||||
val cmd: String = dmessage.substring(1)
|
||||
val cmdlowercased: String = cmd.toLowerCase
|
||||
if (dsender.isInstanceOf[DiscordSender] && module.whitelistedCommands.get.stream.noneMatch((s: String) => cmdlowercased == s || cmdlowercased.startsWith(s + " "))) { // Command not whitelisted
|
||||
dsender.sendMessage("Sorry, you can only access these commands from here:\n" + module.whitelistedCommands.get.stream.map((uc: String) => "/" + uc).collect(Collectors.joining(", ")) + (if (user.getConnectedID(classOf[TBMCPlayer]) == null) {
|
||||
"\nTo access your commands, first please connect your accounts, using /connect in " + DPUtils.botmention + "\nThen y"
|
||||
if (event.getMessage.getType eq Message.Type.CHANNEL_PINNED_MESSAGE) {
|
||||
val mcchannel = if (clmd != null) clmd.mcchannel else dsender.getChromaUser.channel.get
|
||||
val rtr = mcchannel getRTR (if (clmd != null) clmd.dcp else dsender)
|
||||
TBMCChatAPI.SendSystemMessage(mcchannel, rtr, (dsender match {
|
||||
case player: Player => player.getDisplayName
|
||||
case _ => dsender.getName
|
||||
}) + " pinned a message on Discord.", TBMCSystemChatEvent.BroadcastTarget.ALL)
|
||||
false
|
||||
}
|
||||
else {
|
||||
"\nY"
|
||||
}) + "ou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!")
|
||||
return true
|
||||
val cmb = ChatMessage.builder(dsender, user, dmessage + getAttachmentText()).fromCommand(false)
|
||||
if (clmd != null)
|
||||
TBMCChatAPI.SendChatMessage(cmb.permCheck(clmd.dcp).build, clmd.mcchannel)
|
||||
else
|
||||
TBMCChatAPI.SendChatMessage(cmb.build)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a Minecraft command coming from Discord.
|
||||
*
|
||||
* @param event The Discord event
|
||||
* @param dmessage The Discord mewsage, starting with a slash
|
||||
* @param dsender The sender who sent it
|
||||
* @param user The Chroma user of the sender
|
||||
* @param clmd The custom last message data (if in a custom chat)
|
||||
* @param isPrivate Whether the chat is private
|
||||
* @return
|
||||
*/
|
||||
private def handleIngameCommand(event: MessageCreateEvent, dmessage: String, dsender: DiscordSenderBase, user: DiscordPlayer,
|
||||
clmd: MCChatCustom.CustomLMD, isPrivate: Boolean): Unit = {
|
||||
def notWhitelisted(cmd: String) = module.whitelistedCommands.get.stream
|
||||
.noneMatch(s => cmd == s || cmd.startsWith(s + " "))
|
||||
|
||||
def whitelistedCommands = module.whitelistedCommands.get.stream
|
||||
.map("/" + _).collect(Collectors.joining(", "))
|
||||
|
||||
if (!isPrivate)
|
||||
event.getMessage.delete.subscribe
|
||||
val cmd = dmessage.substring(1)
|
||||
val cmdlowercased = cmd.toLowerCase
|
||||
if (dsender.isInstanceOf[DiscordSender] && notWhitelisted(cmdlowercased)) { // Command not whitelisted
|
||||
dsender.sendMessage("Sorry, you can only access these commands from here:\n" + whitelistedCommands() +
|
||||
(if (user.getConnectedID(classOf[TBMCPlayer]) == null)
|
||||
"\nTo access your commands, first please connect your accounts, using /connect in " + DPUtils.botmention
|
||||
+ "\nThen y" else "\nY") + "ou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!")
|
||||
return
|
||||
}
|
||||
module.log(dsender.getName + " ran from DC: /" + cmd)
|
||||
if (dsender.isInstanceOf[DiscordSender] && runCustomCommand(dsender, cmdlowercased)) {
|
||||
return true
|
||||
}
|
||||
val channel: Channel = if (clmd == null) {
|
||||
user.channel.get
|
||||
}
|
||||
else {
|
||||
clmd.mcchannel
|
||||
}
|
||||
val ev: TBMCCommandPreprocessEvent = new TBMCCommandPreprocessEvent(dsender, channel, dmessage, if (clmd == null) {
|
||||
dsender
|
||||
}
|
||||
else {
|
||||
clmd.dcp
|
||||
})
|
||||
Bukkit.getScheduler.runTask(DiscordPlugin.plugin, //Commands need to be run sync
|
||||
() => {
|
||||
def foo(): Unit = {
|
||||
Bukkit.getPluginManager.callEvent(ev)
|
||||
if (ev.isCancelled) {
|
||||
return
|
||||
}
|
||||
val channel = if (clmd == null) user.channel.get else clmd.mcchannel
|
||||
val ev = new TBMCCommandPreprocessEvent(dsender, channel, dmessage, if (clmd == null) dsender else clmd.dcp)
|
||||
Bukkit.getScheduler.runTask(DiscordPlugin.plugin, () => { //Commands need to be run sync
|
||||
Bukkit.getPluginManager.callEvent(ev)
|
||||
if (!ev.isCancelled)
|
||||
runMCCommand(dsender, cmd)
|
||||
})
|
||||
}
|
||||
|
||||
private def runMCCommand(dsender: DiscordSenderBase, cmd: String): Unit = {
|
||||
try {
|
||||
val mcpackage: String = Bukkit.getServer.getClass.getPackage.getName
|
||||
if (!(module.enableVanillaCommands.get)) {
|
||||
val mcpackage = Bukkit.getServer.getClass.getPackage.getName
|
||||
if (!module.enableVanillaCommands.get)
|
||||
Bukkit.dispatchCommand(dsender, cmd)
|
||||
}
|
||||
else {
|
||||
if (mcpackage.contains("1_12")) {
|
||||
else if (mcpackage.contains("1_12"))
|
||||
VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd)
|
||||
}
|
||||
else {
|
||||
if (mcpackage.contains("1_14")) {
|
||||
else if (mcpackage.contains("1_14"))
|
||||
VanillaCommandListener14.runBukkitOrVanillaCommand(dsender, cmd)
|
||||
}
|
||||
else {
|
||||
if (mcpackage.contains("1_15") || mcpackage.contains("1_16")) {
|
||||
else if (mcpackage.contains("1_15") || mcpackage.contains("1_16"))
|
||||
VanillaCommandListener15.runBukkitOrVanillaCommand(dsender, cmd)
|
||||
}
|
||||
else {
|
||||
else
|
||||
Bukkit.dispatchCommand(dsender, cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
case e: NoClassDefFoundError =>
|
||||
TBMCCoreAPI.SendException("A class is not found when trying to run command " + cmd + "!", e, module)
|
||||
|
@ -452,18 +455,20 @@ class MCChatListener(val module: MinecraftChatModule) extends Listener {
|
|||
}
|
||||
}
|
||||
|
||||
foo()
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles custom public commands. Used to hide sensitive information in public chats.
|
||||
*
|
||||
* @param dsender The Discord sender
|
||||
* @param cmdlowercased The command, lowercased
|
||||
* @return Whether the command was a custom command
|
||||
*/
|
||||
private def runCustomCommand(dsender: DiscordSenderBase, cmdlowercased: String): Boolean = {
|
||||
if (cmdlowercased.startsWith("list")) {
|
||||
val players: util.Collection[_ <: Player] = Bukkit.getOnlinePlayers
|
||||
val players = Bukkit.getOnlinePlayers
|
||||
dsender.sendMessage("There are " + players.stream.filter(MCChatUtils.checkEssentials).count + " out of " + Bukkit.getMaxPlayers + " players online.")
|
||||
dsender.sendMessage("Players: " + players.stream.filter(MCChatUtils.checkEssentials).map(Player.getDisplayName).collect(Collectors.joining(", ")))
|
||||
return true
|
||||
dsender.sendMessage("Players: " + players.stream.filter(MCChatUtils.checkEssentials).map(_.getDisplayName).collect(Collectors.joining(", ")))
|
||||
true
|
||||
}
|
||||
return false
|
||||
else false
|
||||
}
|
||||
}
|
|
@ -4,12 +4,12 @@ import buttondevteam.core.ComponentManager
|
|||
import buttondevteam.discordplugin.mcchat.MCChatUtils.LastMsgData
|
||||
import buttondevteam.discordplugin.{DiscordConnectedPlayer, DiscordPlayer, DiscordPlugin, DiscordSenderBase}
|
||||
import buttondevteam.lib.player.TBMCPlayer
|
||||
import discord4j.common.util.Snowflake
|
||||
import discord4j.core.`object`.entity.User
|
||||
import discord4j.core.`object`.entity.channel.{MessageChannel, PrivateChannel}
|
||||
import org.bukkit.Bukkit
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.jdk.javaapi.CollectionConverters.asScala
|
||||
|
||||
object MCChatPrivate {
|
||||
/**
|
||||
|
@ -39,7 +39,7 @@ object MCChatPrivate {
|
|||
def foo(): Unit = {
|
||||
if ((p == null || p.isInstanceOf[DiscordSenderBase]) // Player is offline - If the player is online, that takes precedence
|
||||
&& sender.isLoggedIn) { //Don't call the quit event if login failed
|
||||
MCChatUtils.callLogoutEvent(sender, false) //The next line has to run *after* this one, so can't use the needsSync parameter
|
||||
MCChatUtils.callLogoutEvent(sender, needsSync = false) //The next line has to run *after* this one, so can't use the needsSync parameter
|
||||
}
|
||||
|
||||
MCChatUtils.LoggedInPlayers.remove(sender.getUniqueId)
|
||||
|
@ -61,14 +61,13 @@ object MCChatPrivate {
|
|||
def isMinecraftChatEnabled(dp: DiscordPlayer): Boolean = isMinecraftChatEnabled(dp.getDiscordID)
|
||||
|
||||
def isMinecraftChatEnabled(did: String): Boolean = { // Don't load the player data just for this
|
||||
lastmsgPerUser.stream.anyMatch((lmd: MCChatUtils.LastMsgData) =>
|
||||
lmd.channel.asInstanceOf[PrivateChannel].getRecipientIds.stream.anyMatch((u: Snowflake) => u.asString == did))
|
||||
lastmsgPerUser.exists(_.channel.asInstanceOf[PrivateChannel].getRecipientIds.stream.anyMatch(u => u.asString == did))
|
||||
}
|
||||
|
||||
def logoutAll(): Unit = {
|
||||
MCChatUtils.ConnectedSenders synchronized {
|
||||
for (entry <- asScala(MCChatUtils.ConnectedSenders.entrySet)) {
|
||||
for (valueEntry <- entry.getValue.entrySet) {
|
||||
for ((_, userMap) <- MCChatUtils.ConnectedSenders) {
|
||||
for (valueEntry <- asScala(userMap.entrySet)) {
|
||||
if (MCChatUtils.getSender(MCChatUtils.OnlineSenders, valueEntry.getKey, valueEntry.getValue.getUser) == null) { //If the player is online then the fake player was already logged out
|
||||
MCChatUtils.callLogoutEvent(valueEntry.getValue, !Bukkit.isPrimaryThread)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.bukkit.entity.Player
|
|||
import org.bukkit.event.Event
|
||||
import org.bukkit.event.player.{AsyncPlayerPreLoginEvent, PlayerJoinEvent, PlayerLoginEvent, PlayerQuitEvent}
|
||||
import org.bukkit.plugin.AuthorNagException
|
||||
import org.reactivestreams.Publisher
|
||||
import reactor.core.scala.publisher.SMono
|
||||
|
||||
import java.net.InetAddress
|
||||
|
@ -46,7 +45,7 @@ object MCChatUtils {
|
|||
@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 var module: MinecraftChatModule = null
|
||||
private val staticExcludedPlugins = Map[Class[_ <: Event], util.HashSet[String]]()
|
||||
private val staticExcludedPlugins: concurrent.Map[Class[_ <: Event], util.HashSet[String]] = concurrent.TrieMap()
|
||||
|
||||
def updatePlayerList(): Unit = {
|
||||
val mod = getModule
|
||||
|
@ -102,22 +101,22 @@ object MCChatUtils {
|
|||
addSender(senders, user.getId.asString, sender)
|
||||
|
||||
def addSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], did: String, sender: T): T = {
|
||||
val origMap = senders.get(did)
|
||||
val map = if (origMap.isEmpty) new ConcurrentHashMap[Snowflake, T] else origMap.get
|
||||
val mapOpt = senders.get(did)
|
||||
val map = if (mapOpt.isEmpty) new ConcurrentHashMap[Snowflake, T] else mapOpt.get
|
||||
map.put(sender.getChannel.getId, sender)
|
||||
senders.put(did, map)
|
||||
sender
|
||||
}
|
||||
|
||||
def getSender[T <: DiscordSenderBase](senders: ConcurrentHashMap[String, ConcurrentHashMap[Snowflake, T]], channel: Snowflake, user: User): T = {
|
||||
val map = senders.get(user.getId.asString)
|
||||
if (map != null) map.get(channel)
|
||||
def getSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], channel: Snowflake, user: User): T = {
|
||||
val mapOpt = senders.get(user.getId.asString)
|
||||
if (mapOpt.nonEmpty) mapOpt.get.get(channel)
|
||||
else null.asInstanceOf
|
||||
}
|
||||
|
||||
def removeSender[T <: DiscordSenderBase](senders: ConcurrentHashMap[String, ConcurrentHashMap[Snowflake, T]], channel: Snowflake, user: User): T = {
|
||||
val map = senders.get(user.getId.asString)
|
||||
if (map != null) map.remove(channel)
|
||||
def removeSender[T <: DiscordSenderBase](senders: concurrent.Map[String, ConcurrentHashMap[Snowflake, T]], channel: Snowflake, user: User): T = {
|
||||
val mapOpt = senders.get(user.getId.asString)
|
||||
if (mapOpt.nonEmpty) mapOpt.get.remove(channel)
|
||||
else null.asInstanceOf
|
||||
}
|
||||
|
||||
|
@ -138,11 +137,12 @@ object MCChatUtils {
|
|||
*/
|
||||
def forCustomAndAllMCChat(action: SMono[MessageChannel] => SMono[_], @Nullable toggle: ChannelconBroadcast, hookmsg: Boolean): SMono[_] = {
|
||||
if (notEnabled) return SMono.empty
|
||||
val list = new ListBuffer[Publisher[_]]
|
||||
if (!GeneralEventBroadcasterModule.isHooked || !hookmsg) list.append(forPublicPrivateChat(action))
|
||||
val customLMDFunction = (cc: MCChatCustom.CustomLMD) => action(SMono.just(cc.channel))
|
||||
if (toggle == null) MCChatCustom.lastmsgCustom.map(customLMDFunction).foreach(list.append(_))
|
||||
else MCChatCustom.lastmsgCustom.filter((cc) => (cc.toggles & (1 << toggle.id)) ne 0).map(customLMDFunction).foreach(list.append(_))
|
||||
val list =
|
||||
List(if (!GeneralEventBroadcasterModule.isHooked || !hookmsg)
|
||||
forPublicPrivateChat(action) else SMono.empty) ++
|
||||
(if (toggle == null) MCChatCustom.lastmsgCustom
|
||||
else MCChatCustom.lastmsgCustom.filter(cc => (cc.toggles & (1 << toggle.id)) != 0))
|
||||
.map(_.channel).map(SMono.just).map(action)
|
||||
SMono.whenDelayError(list)
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ object MCChatUtils {
|
|||
def forAllowedCustomMCChat(action: SMono[MessageChannel] => SMono[_], @Nullable sender: CommandSender, @Nullable toggle: ChannelconBroadcast): SMono[_] = {
|
||||
if (notEnabled) return SMono.empty
|
||||
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
|
||||
if (toggle != null && ((clmd.toggles & (1 << toggle.id)) eq 0)) false //If null then allow
|
||||
if (toggle != null && ((clmd.toggles & (1 << toggle.id)) == 0)) false //If null then allow
|
||||
else if (sender == null) true
|
||||
else clmd.groupID.equals(clmd.mcchannel.getGroupID(sender))
|
||||
}).map(cc => action.apply(SMono.just(cc.channel))) //TODO: Send error messages on channel connect
|
||||
|
@ -204,13 +204,12 @@ object MCChatUtils {
|
|||
* 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): DiscordSenderBase = { //noinspection OptionalGetWithoutIsPresent
|
||||
List[() => DiscordSenderBase]( // https://stackoverflow.com/a/28833677/2703239
|
||||
() => getSender[DiscordSenderBase](OnlineSenders, channel, author), // Find first non-null
|
||||
() => getSender[DiscordSenderBase](ConnectedSenders, channel, author), // This doesn't support the public chat, but it'll always return null for it
|
||||
() => getSender[DiscordSenderBase](UnconnectedSenders, channel, author), //
|
||||
() => addSender[DiscordSenderBase](UnconnectedSenders, author,
|
||||
new DiscordSender(author, SMono(DiscordPlugin.dc.getChannelById(channel)).block().asInstanceOf[MessageChannel])))
|
||||
.map(_.apply()).find(sender => sender != null).get
|
||||
Option(getSender(OnlineSenders, channel, author)) // Find first non-null
|
||||
.orElse(Option(getSender(ConnectedSenders, channel, author))) // This doesn't support the public chat, but it'll always return null for it
|
||||
.orElse(Option(getSender(UnconnectedSenders, channel, author))) //
|
||||
.orElse(Option(addSender(UnconnectedSenders, author,
|
||||
new DiscordSender(author, SMono(DiscordPlugin.dc.getChannelById(channel)).block().asInstanceOf[MessageChannel]))))
|
||||
.get
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
package buttondevteam.discordplugin.mcchat
|
||||
|
||||
import buttondevteam.discordplugin.DPUtils.FluxExtensions
|
||||
import buttondevteam.discordplugin._
|
||||
import buttondevteam.lib.TBMCSystemChatEvent
|
||||
import buttondevteam.lib.player.{TBMCPlayer, TBMCPlayerBase, TBMCYEEHAWEvent}
|
||||
import discord4j.common.util.Snowflake
|
||||
import discord4j.core.`object`.entity.Role
|
||||
import discord4j.core.`object`.entity.channel.MessageChannel
|
||||
import discord4j.core.`object`.entity.{Member, Role, User}
|
||||
import net.ess3.api.events.{AfkStatusChangeEvent, MuteStatusChangeEvent, NickChangeEvent, VanishStatusChangeEvent}
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.{EventHandler, EventPriority, Listener}
|
||||
import org.bukkit.event.entity.PlayerDeathEvent
|
||||
import org.bukkit.event.player.PlayerLoginEvent.Result
|
||||
import org.bukkit.event.player._
|
||||
import org.bukkit.event.server.{BroadcastMessageEvent, TabCompleteEvent}
|
||||
import reactor.core.publisher.{Flux, Mono}
|
||||
|
||||
import java.util.Optional
|
||||
import org.bukkit.event.{EventHandler, EventPriority, Listener}
|
||||
import reactor.core.publisher.Flux
|
||||
import reactor.core.scala.publisher.SMono
|
||||
|
||||
class MCListener(val module: MinecraftChatModule) extends Listener {
|
||||
final private val muteRole = DPUtils.roleData(module.getConfig, "muteRole", "Muted")
|
||||
|
@ -25,7 +25,7 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
|
|||
if (e.getResult ne Result.ALLOWED) return
|
||||
if (e.getPlayer.isInstanceOf[DiscordConnectedPlayer]) return
|
||||
val dcp = MCChatUtils.LoggedInPlayers.get(e.getPlayer.getUniqueId)
|
||||
if (dcp != null) MCChatUtils.callLogoutEvent(dcp, needsSync = false)
|
||||
if (dcp.nonEmpty) MCChatUtils.callLogoutEvent(dcp.get, needsSync = false)
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR) def onPlayerJoin(e: PlayerJoinEvent): Unit = {
|
||||
|
@ -34,14 +34,12 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
|
|||
def foo(): Unit = {
|
||||
val p = e.getPlayer
|
||||
val dp = TBMCPlayerBase.getPlayer(p.getUniqueId, classOf[TBMCPlayer]).getAs(classOf[DiscordPlayer])
|
||||
if (dp != null) DiscordPlugin.dc.getUserById(Snowflake.of(dp.getDiscordID)).flatMap((user) => user.getPrivateChannel.flatMap((chan) => module.chatChannelMono.flatMap((cc: MessageChannel) => {
|
||||
def foo(cc: MessageChannel) = {
|
||||
if (dp != null)
|
||||
DiscordPlugin.dc.getUserById(Snowflake.of(dp.getDiscordID)).flatMap(user =>
|
||||
user.getPrivateChannel.flatMap(chan => module.chatChannelMono.flatMap(cc => {
|
||||
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID, DiscordPlayerSender.create(user, chan, p, module))
|
||||
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID, DiscordPlayerSender.create(user, cc, p, module)) //Stored per-channel
|
||||
Mono.empty
|
||||
}
|
||||
|
||||
foo(cc)
|
||||
SMono.empty
|
||||
}))).subscribe
|
||||
val message = e.getJoinMessage
|
||||
sendJoinLeaveMessage(message, e.getPlayer)
|
||||
|
@ -58,8 +56,8 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.MONITOR) def onPlayerLeave(e: PlayerQuitEvent): Unit = {
|
||||
if (e.getPlayer.isInstanceOf[DiscordConnectedPlayer]) return // Only care about real users
|
||||
MCChatUtils.OnlineSenders.entrySet.removeIf((entry) => entry.getValue.entrySet.stream.anyMatch((p) => p.getValue.getUniqueId.equals(e.getPlayer.getUniqueId)))
|
||||
Bukkit.getScheduler.runTaskAsynchronously(DiscordPlugin.plugin, () => Optional.ofNullable(MCChatUtils.LoggedInPlayers.get(e.getPlayer.getUniqueId)).ifPresent(MCChatUtils.callLoginEvents))
|
||||
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.runTaskLaterAsynchronously(DiscordPlugin.plugin, () => ChromaBot.updatePlayerList(), 5)
|
||||
val message = e.getQuitMessage
|
||||
sendJoinLeaveMessage(message, e.getPlayer)
|
||||
|
@ -89,16 +87,18 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
|
|||
if (!source.isPlayer) return
|
||||
val p = TBMCPlayerBase.getPlayer(source.getPlayer.getUniqueId, classOf[TBMCPlayer]).getAs(classOf[DiscordPlayer])
|
||||
if (p == null) return
|
||||
DPUtils.ignoreError(DiscordPlugin.dc.getUserById(Snowflake.of(p.getDiscordID)).flatMap((user: User) => user.asMember(DiscordPlugin.mainServer.getId)).flatMap((user: Member) => role.flatMap((r: Role) => {
|
||||
def foo(r: Role): Mono[_] = {
|
||||
DPUtils.ignoreError(SMono(DiscordPlugin.dc.getUserById(Snowflake.of(p.getDiscordID)))
|
||||
.flatMap(user => SMono(user.asMember(DiscordPlugin.mainServer.getId)))
|
||||
.flatMap(user => role.flatMap((r: Role) => {
|
||||
def foo(r: Role): SMono[_] = {
|
||||
if (e.getValue) user.addRole(r.getId)
|
||||
else user.removeRole(r.getId)
|
||||
val modlog = module.modlogChannel.get
|
||||
val msg = (if (e.getValue) "M"
|
||||
else "Unm") + "uted user: " + user.getUsername + "#" + user.getDiscriminator
|
||||
module.log(msg)
|
||||
if (modlog != null) return modlog.flatMap((ch: MessageChannel) => ch.createMessage(msg))
|
||||
Mono.empty
|
||||
if (modlog != null) return modlog.flatMap((ch: MessageChannel) => SMono(ch.createMessage(msg)))
|
||||
SMono.empty
|
||||
}
|
||||
|
||||
foo(r)
|
||||
|
@ -117,10 +117,10 @@ class MCListener(val module: MinecraftChatModule) extends Listener {
|
|||
case _ => event.getSender.getName
|
||||
}
|
||||
//Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO
|
||||
DiscordPlugin.mainServer.getEmojis.filter(e => "YEEHAW" == e.getName).take(1).singleOrEmpty
|
||||
.map(Optional.of(_)).defaultIfEmpty(Optional.empty)
|
||||
.flatMap((yeehaw) => MCChatUtils.forPublicPrivateChat(MCChatUtils.send(name +
|
||||
yeehaw.map((guildEmoji) => " <:YEEHAW:" + guildEmoji.getId.asString + ">s").orElse(" YEEHAWs")))).subscribe
|
||||
DiscordPlugin.mainServer.getEmojis.^^().filter(e => "YEEHAW" == e.getName).take(1).singleOrEmpty
|
||||
.map(Option.apply).defaultIfEmpty(Option.empty)
|
||||
.flatMap(yeehaw => MCChatUtils.forPublicPrivateChat(MCChatUtils.send(name +
|
||||
yeehaw.map(guildEmoji => " <:YEEHAW:" + guildEmoji.getId.asString + ">s").getOrElse(" YEEHAWs")))).subscribe
|
||||
}
|
||||
|
||||
@EventHandler def onNickChange(event: NickChangeEvent): Unit = MCChatUtils.updatePlayerList()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package buttondevteam.discordplugin.mcchat
|
||||
|
||||
import buttondevteam.core.component.channel.Channel
|
||||
import buttondevteam.discordplugin.DPUtils.{MonoExtensions, SpecExtensions}
|
||||
import buttondevteam.discordplugin.playerfaker.ServerWatcher
|
||||
import buttondevteam.discordplugin.playerfaker.perm.LPInjector
|
||||
import buttondevteam.discordplugin.util.DPState
|
||||
|
@ -12,12 +13,12 @@ import discord4j.common.util.Snowflake
|
|||
import discord4j.core.`object`.entity.channel.MessageChannel
|
||||
import discord4j.rest.util.Color
|
||||
import org.bukkit.Bukkit
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.core.scala.publisher.SMono
|
||||
|
||||
import java.util
|
||||
import java.util.stream.Collectors
|
||||
import java.util.{Objects, UUID}
|
||||
import scala.jdk.CollectionConverters.IterableHasAsScala
|
||||
|
||||
/**
|
||||
* Provides Minecraft chat connection to Discord. Commands may be used either in a public chat (limited) or in a DM.
|
||||
|
@ -51,7 +52,7 @@ class MinecraftChatModule extends Component[DiscordPlugin] {
|
|||
/**
|
||||
* The channel where the plugin can log when it mutes a player on Discord because of a Minecraft mute
|
||||
*/
|
||||
val modlogChannel: ReadOnlyConfigData[Mono[MessageChannel]] = DPUtils.channelData(getConfig, "modlogChannel")
|
||||
val modlogChannel: ReadOnlyConfigData[SMono[MessageChannel]] = DPUtils.channelData(getConfig, "modlogChannel")
|
||||
/**
|
||||
* The plugins to exclude from fake player events used for the 'mcchat' command - some plugins may crash, add them here
|
||||
*/
|
||||
|
@ -113,7 +114,7 @@ class MinecraftChatModule extends Component[DiscordPlugin] {
|
|||
}
|
||||
if (chcons != null) {
|
||||
val chconkeys = chcons.getKeys(false)
|
||||
for (chconkey <- chconkeys) {
|
||||
for (chconkey <- chconkeys.asScala) {
|
||||
val chcon = chcons.getConfigurationSection(chconkey)
|
||||
val mcch = Channel.getChannels.filter((ch: Channel) => ch.ID == chcon.getString("mcchid")).findAny
|
||||
val ch = DiscordPlugin.dc.getChannelById(Snowflake.of(chcon.getLong("chid"))).block
|
||||
|
@ -122,17 +123,16 @@ class MinecraftChatModule extends Component[DiscordPlugin] {
|
|||
val groupid = chcon.getString("groupid")
|
||||
val toggles = chcon.getInt("toggles")
|
||||
val brtoggles = chcon.getStringList("brtoggles")
|
||||
if (!mcch.isPresent || ch == null || user == null || groupid == null) continue //todo: continue is not supported
|
||||
Bukkit.getScheduler.runTask(getPlugin, () => {
|
||||
def foo() = { //<-- Needed because of occasional ConcurrentModificationExceptions when creating the player (PermissibleBase)
|
||||
val dcp = DiscordConnectedPlayer.create(user, ch.asInstanceOf[MessageChannel], UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname"), this)
|
||||
MCChatCustom.addCustomChat(ch.asInstanceOf[MessageChannel], groupid, mcch.get, user, dcp, toggles, brtoggles.stream.map(TBMCSystemChatEvent.BroadcastTarget.get).filter(Objects.nonNull).collect(Collectors.toSet))
|
||||
}
|
||||
|
||||
foo()
|
||||
if (mcch.isPresent && ch != null && user != null && groupid != null) {
|
||||
Bukkit.getScheduler.runTask(getPlugin, () => { //<-- Needed because of occasional ConcurrentModificationExceptions when creating the player (PermissibleBase)
|
||||
val dcp = DiscordConnectedPlayer.create(user, ch.asInstanceOf[MessageChannel],
|
||||
UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname"), this)
|
||||
MCChatCustom.addCustomChat(ch.asInstanceOf[MessageChannel], groupid, mcch.get, user, dcp, toggles,
|
||||
brtoggles.asScala.map(TBMCSystemChatEvent.BroadcastTarget.get).filter(Objects.nonNull).toSet)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
try if (lpInjector == null) lpInjector = new LPInjector(DiscordPlugin.plugin)
|
||||
catch {
|
||||
case e: Exception =>
|
||||
|
@ -205,7 +205,7 @@ class MinecraftChatModule extends Component[DiscordPlugin] {
|
|||
chconc.set("mcname", chcon.dcp.getName)
|
||||
chconc.set("groupid", chcon.groupID)
|
||||
chconc.set("toggles", chcon.toggles)
|
||||
chconc.set("brtoggles", chcon.brtoggles.stream.map(_.getName).collect(Collectors.toList))
|
||||
chconc.set("brtoggles", chcon.brtoggles.map(_.getName).toList)
|
||||
}
|
||||
if (listener != null) { //Can be null if disabled because of a config error
|
||||
listener.stop(true)
|
||||
|
@ -219,10 +219,10 @@ class MinecraftChatModule extends Component[DiscordPlugin] {
|
|||
* It will block to make sure all messages are sent
|
||||
*/
|
||||
private def sendStateMessage(color: Color, message: String) =
|
||||
MCChatUtils.forCustomAndAllMCChat(_.flatMap(_.createEmbed(_.setColor(color).setTitle(message))),
|
||||
ChannelconBroadcast.RESTART, hookmsg = false).block
|
||||
MCChatUtils.forCustomAndAllMCChat(_.flatMap(_.createEmbed(spec => spec.setColor(color).setTitle(message)).^^()),
|
||||
ChannelconBroadcast.RESTART, hookmsg = false).block()
|
||||
|
||||
private def sendStateMessage(color: Color, message: String, extra: String) =
|
||||
MCChatUtils.forCustomAndAllMCChat(_.flatMap(_.createEmbed(_.setColor(color).setTitle(message).setDescription(extra))
|
||||
.onErrorResume((_: Throwable) => Mono.empty)), ChannelconBroadcast.RESTART, hookmsg = false).block
|
||||
MCChatUtils.forCustomAndAllMCChat(_.flatMap(_.createEmbed(_.setColor(color).setTitle(message).setDescription(extra).^^()).^^()
|
||||
.onErrorResume(_ => SMono.empty)), ChannelconBroadcast.RESTART, hookmsg = false).block()
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package buttondevteam.discordplugin.mccommands
|
||||
|
||||
import buttondevteam.discordplugin.{DPUtils, DiscordPlayer, DiscordPlugin, DiscordSenderBase}
|
||||
import buttondevteam.discordplugin.commands.{ConnectCommand, VersionCommand}
|
||||
import buttondevteam.discordplugin.mcchat.{MCChatUtils, MinecraftChatModule}
|
||||
import buttondevteam.discordplugin.util.DPState
|
||||
import buttondevteam.discordplugin.{DPUtils, DiscordPlayer, DiscordPlugin, DiscordSenderBase}
|
||||
import buttondevteam.lib.chat.{Command2, CommandClass, ICommand2MC}
|
||||
import buttondevteam.lib.player.{ChromaGamerBase, TBMCPlayer, TBMCPlayerBase}
|
||||
import discord4j.core.`object`.ExtendedInvite
|
||||
|
@ -14,10 +14,10 @@ import reactor.core.publisher.Mono
|
|||
|
||||
import java.lang.reflect.Method
|
||||
|
||||
@CommandClass(path = "discord", helpText = Array(Array(
|
||||
@CommandClass(path = "discord", helpText = Array(
|
||||
"Discord",
|
||||
"This command allows performing Discord-related actions."
|
||||
))) class DiscordMCCommand extends ICommand2MC {
|
||||
)) class DiscordMCCommand extends ICommand2MC {
|
||||
@Command2.Subcommand def accept(player: Player): Boolean = {
|
||||
if (checkSafeMode(player)) return true
|
||||
val did = ConnectCommand.WaitingToConnect.get(player.getName)
|
||||
|
@ -45,17 +45,17 @@ import java.lang.reflect.Method
|
|||
true
|
||||
}
|
||||
|
||||
@Command2.Subcommand(permGroup = Command2.Subcommand.MOD_GROUP, helpText = Array(Array(
|
||||
@Command2.Subcommand(permGroup = Command2.Subcommand.MOD_GROUP, helpText = Array(
|
||||
"Reload Discord plugin",
|
||||
"Reloads the config. To apply some changes, you may need to also run /discord restart."
|
||||
))) def reload(sender: CommandSender): Unit =
|
||||
)) def reload(sender: CommandSender): Unit =
|
||||
if (DiscordPlugin.plugin.tryReloadConfig) sender.sendMessage("§bConfig reloaded.")
|
||||
else sender.sendMessage("§cFailed to reload config.")
|
||||
|
||||
@Command2.Subcommand(permGroup = Command2.Subcommand.MOD_GROUP, helpText = Array(Array(
|
||||
@Command2.Subcommand(permGroup = Command2.Subcommand.MOD_GROUP, helpText = Array(
|
||||
"Restart the plugin", //
|
||||
"This command disables and then enables the plugin." //
|
||||
))) def restart(sender: CommandSender): Unit = {
|
||||
)) def restart(sender: CommandSender): Unit = {
|
||||
val task: Runnable = () => {
|
||||
def foo(): Unit = {
|
||||
if (!DiscordPlugin.plugin.tryReloadConfig) {
|
||||
|
@ -84,16 +84,16 @@ import java.lang.reflect.Method
|
|||
}
|
||||
}
|
||||
|
||||
@Command2.Subcommand(helpText = Array(Array(
|
||||
@Command2.Subcommand(helpText = Array(
|
||||
"Version command",
|
||||
"Prints the plugin version"))) def version(sender: CommandSender): Unit = {
|
||||
"Prints the plugin version")) def version(sender: CommandSender): Unit = {
|
||||
sender.sendMessage(VersionCommand.getVersion)
|
||||
}
|
||||
|
||||
@Command2.Subcommand(helpText = Array(Array(
|
||||
@Command2.Subcommand(helpText = Array(
|
||||
"Invite",
|
||||
"Shows an invite link to the server"
|
||||
))) def invite(sender: CommandSender): Unit = {
|
||||
)) def invite(sender: CommandSender): Unit = {
|
||||
if (checkSafeMode(sender)) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -36,8 +36,10 @@ class DelegatingMockMaker() extends MockMaker {
|
|||
override def createStaticMock[T](`type`: Class[T], settings: MockCreationSettings[T], handler: MockHandler[_]): MockMaker.StaticMockControl[T] =
|
||||
this.mockMaker.createStaticMock(`type`, settings, handler)
|
||||
|
||||
override def createConstructionMock[T](`type`: Class[T], settingsFactory: Function[MockedConstruction.Context, MockCreationSettings[T]], handlerFactory: Function[MockedConstruction.Context, MockHandler[T]], mockInitializer: MockedConstruction.MockInitializer[T]): MockMaker.ConstructionMockControl[T] =
|
||||
this.mockMaker.createConstructionMock[T](`type`, settingsFactory: Function[MockedConstruction.Context, MockCreationSettings[T]], handlerFactory, mockInitializer)
|
||||
override def createConstructionMock[T](`type`: Class[T], settingsFactory: java.util.function.Function[MockedConstruction.Context,
|
||||
MockCreationSettings[T]], handlerFactory: java.util.function.Function[MockedConstruction.Context,
|
||||
MockHandler[T]], mockInitializer: MockedConstruction.MockInitializer[T]): MockMaker.ConstructionMockControl[T] =
|
||||
this.mockMaker.createConstructionMock[T](`type`, settingsFactory, handlerFactory, mockInitializer)
|
||||
|
||||
def setMockMaker(mockMaker: MockMaker): Unit = {
|
||||
this.mockMaker = mockMaker
|
||||
|
|
|
@ -4,8 +4,8 @@ import buttondevteam.discordplugin.DiscordConnectedPlayer
|
|||
import buttondevteam.discordplugin.mcchat.MCChatUtils
|
||||
import com.destroystokyo.paper.profile.CraftPlayerProfile
|
||||
import net.bytebuddy.implementation.bind.annotation.IgnoreForBinding
|
||||
import org.bukkit.{Bukkit, Server}
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.{Bukkit, Server}
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker
|
||||
import org.mockito.invocation.InvocationOnMock
|
||||
|
@ -46,14 +46,15 @@ class ServerWatcher {
|
|||
def foo(invocation: InvocationOnMock): AnyRef = {
|
||||
val method = invocation.getMethod
|
||||
val pc = method.getParameterCount
|
||||
var player: DiscordConnectedPlayer = null
|
||||
var player = Option.empty[DiscordConnectedPlayer]
|
||||
method.getName match {
|
||||
case "getPlayer" =>
|
||||
if (pc == 1 && (method.getParameterTypes()(0) eq classOf[UUID])) player = MCChatUtils.LoggedInPlayers.get(invocation.getArgument[UUID](0))
|
||||
if (pc == 1 && (method.getParameterTypes()(0) == classOf[UUID]))
|
||||
player = MCChatUtils.LoggedInPlayers.get(invocation.getArgument[UUID](0))
|
||||
case "getPlayerExact" =>
|
||||
if (pc == 1) {
|
||||
val argument = invocation.getArgument(0)
|
||||
player = MCChatUtils.LoggedInPlayers.values.stream.filter((dcp) => dcp.getName.equalsIgnoreCase(argument)).findAny.orElse(null)
|
||||
player = MCChatUtils.LoggedInPlayers.values.find(_.getName.equalsIgnoreCase(argument))
|
||||
}
|
||||
|
||||
/*case "getOnlinePlayers":
|
||||
|
@ -65,13 +66,14 @@ class ServerWatcher {
|
|||
if (pc == 2) {
|
||||
val uuid = invocation.getArgument(0)
|
||||
val name = invocation.getArgument(1)
|
||||
player = if (uuid != null) MCChatUtils.LoggedInPlayers.get(uuid)
|
||||
else null
|
||||
if (player == null && name != null) player = MCChatUtils.LoggedInPlayers.values.stream.filter((dcp) => dcp.getName.equalsIgnoreCase(name)).findAny.orElse(null)
|
||||
if (player != null) return new CraftPlayerProfile(player.getUniqueId, player.getName)
|
||||
player = if (uuid != null) MCChatUtils.LoggedInPlayers.get(uuid) else Option.empty
|
||||
if (player.isEmpty && name != null)
|
||||
player = MCChatUtils.LoggedInPlayers.values.find(_.getName.equalsIgnoreCase(name))
|
||||
if (player.nonEmpty)
|
||||
return new CraftPlayerProfile(player.get.getUniqueId, player.get.getName)
|
||||
}
|
||||
}
|
||||
if (player != null) return player
|
||||
if (player.nonEmpty) return player.get
|
||||
method.invoke(origServer, invocation.getArguments)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@ import discord4j.core.`object`.entity.Role
|
|||
import reactor.core.publisher.Mono
|
||||
|
||||
@CommandClass class RoleCommand private[role](var grm: GameRoleModule) extends ICommand2DC {
|
||||
@Command2.Subcommand(helpText = Array(Array(
|
||||
@Command2.Subcommand(helpText = Array(
|
||||
"Add role",
|
||||
"This command adds a role to your account."
|
||||
))) def add(sender: Command2DCSender, @Command2.TextArg rolename: String): Boolean = {
|
||||
)) def add(sender: Command2DCSender, @Command2.TextArg rolename: String): Boolean = {
|
||||
val role = checkAndGetRole(sender, rolename)
|
||||
if (role == null) return true
|
||||
try sender.getMessage.getAuthorAsMember.flatMap(m => m.addRole(role.getId).switchIfEmpty(Mono.fromRunnable(() => sender.sendMessage("added role.")))).subscribe
|
||||
|
@ -23,10 +23,10 @@ import reactor.core.publisher.Mono
|
|||
true
|
||||
}
|
||||
|
||||
@Command2.Subcommand(helpText = Array(Array(
|
||||
@Command2.Subcommand(helpText = Array(
|
||||
"Remove role",
|
||||
"This command removes a role from your account."
|
||||
))) def remove(sender: Command2DCSender, @Command2.TextArg rolename: String): Boolean = {
|
||||
)) def remove(sender: Command2DCSender, @Command2.TextArg rolename: String): Boolean = {
|
||||
val role = checkAndGetRole(sender, rolename)
|
||||
if (role == null) return true
|
||||
try sender.getMessage.getAuthorAsMember.flatMap(m => m.removeRole(role.getId).switchIfEmpty(Mono.fromRunnable(() => sender.sendMessage("removed role.")))).subscribe
|
||||
|
|
Loading…
Reference in a new issue