✨ Sync message to SN
This commit is contained in:
		@@ -2,12 +2,14 @@ package dev.solsynth.snConnect
 | 
			
		||||
 | 
			
		||||
import dev.solsynth.snConnect.commands.SnCommand
 | 
			
		||||
import dev.solsynth.snConnect.commands.SnCommandCompleter
 | 
			
		||||
import dev.solsynth.snConnect.models.*
 | 
			
		||||
import dev.solsynth.snConnect.listeners.SnChatListener
 | 
			
		||||
import dev.solsynth.snConnect.models.SnChatMessage
 | 
			
		||||
import dev.solsynth.snConnect.models.WebSocketPacket
 | 
			
		||||
import dev.solsynth.snConnect.services.SnMessageService
 | 
			
		||||
import dev.solsynth.snConnect.services.SnService
 | 
			
		||||
import kotlinx.coroutines.GlobalScope
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
import net.md_5.bungee.api.ChatColor
 | 
			
		||||
import net.md_5.bungee.api.chat.BaseComponent
 | 
			
		||||
import net.md_5.bungee.api.chat.ClickEvent
 | 
			
		||||
import net.md_5.bungee.api.chat.ComponentBuilder
 | 
			
		||||
import net.md_5.bungee.api.chat.HoverEvent
 | 
			
		||||
@@ -15,22 +17,26 @@ import net.md_5.bungee.api.chat.TextComponent
 | 
			
		||||
import net.milkbowl.vault.economy.Economy
 | 
			
		||||
import org.bukkit.Bukkit
 | 
			
		||||
import org.bukkit.Bukkit.getOnlinePlayers
 | 
			
		||||
import org.bukkit.Color
 | 
			
		||||
import org.bukkit.plugin.java.JavaPlugin
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SolarNetworkConnect : JavaPlugin() {
 | 
			
		||||
    private var economy: Economy? = null
 | 
			
		||||
    private var sn: SnService? = null
 | 
			
		||||
    private var messageService: SnMessageService? = null
 | 
			
		||||
    private var syncChatRooms: List<String> = emptyList()
 | 
			
		||||
    private var destinationChatId: String? = null
 | 
			
		||||
 | 
			
		||||
    private fun handleWebSocketPacket(packet: WebSocketPacket) {
 | 
			
		||||
        logger.info("Received WebSocket packet: type=${packet.type}")
 | 
			
		||||
        // logger.info("Received WebSocket packet: type=${packet.type}")
 | 
			
		||||
        if (packet.type.startsWith("messages") && packet.data != null) {
 | 
			
		||||
            try {
 | 
			
		||||
                when (packet.type) {
 | 
			
		||||
                    "messages.new" -> {
 | 
			
		||||
                        val message = SnChatMessage.fromJson(packet.data)
 | 
			
		||||
                        // Ignore automated accounts
 | 
			
		||||
                        if (message.sender.account.automatedId.isNullOrBlank()) return;
 | 
			
		||||
                        // Only some rooms got synced
 | 
			
		||||
                        if (syncChatRooms.isEmpty() || syncChatRooms.contains(message.chatRoomId)) {
 | 
			
		||||
                            val roomName = message.chatRoom.name ?: "DM"
 | 
			
		||||
                            val senderName = message.sender.account.nick
 | 
			
		||||
@@ -82,6 +88,10 @@ class SolarNetworkConnect : JavaPlugin() {
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (messageService != null && destinationChatId != null) {
 | 
			
		||||
            server.pluginManager.registerEvents(SnChatListener(messageService!!, destinationChatId!!), this)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Bukkit.getPluginCommand("solar")!!.setExecutor(SnCommand(this.sn!!, this.economy))
 | 
			
		||||
        Bukkit.getPluginCommand("solar")!!.tabCompleter = SnCommandCompleter()
 | 
			
		||||
 | 
			
		||||
@@ -102,9 +112,12 @@ class SolarNetworkConnect : JavaPlugin() {
 | 
			
		||||
        val clientId = config.getString("sn.client_id") ?: return false;
 | 
			
		||||
        val clientSecret = config.getString("sn.client_secret") ?: return false;
 | 
			
		||||
        val botApiKey = config.getString("sn.bot_secret");
 | 
			
		||||
        val syncRooms = config.getStringList("chat.sync_chat_rooms")
 | 
			
		||||
        val destination = config.getString("chat.outgoing_room") ?: return false;
 | 
			
		||||
        val syncRooms = config.getStringList("chat.sync_rooms")
 | 
			
		||||
        syncChatRooms = syncRooms
 | 
			
		||||
        destinationChatId = destination
 | 
			
		||||
        sn = SnService(baseUrl, clientId, clientSecret, botApiKey);
 | 
			
		||||
        messageService = SnMessageService(sn!!)
 | 
			
		||||
        GlobalScope.launch {
 | 
			
		||||
            sn!!.connectWebSocketAsFlow().collect { packet ->
 | 
			
		||||
                handleWebSocketPacket(packet)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,39 +0,0 @@
 | 
			
		||||
package dev.solsynth.snConnect
 | 
			
		||||
 | 
			
		||||
import dev.solsynth.snConnect.services.SnService
 | 
			
		||||
import kotlinx.coroutines.runBlocking
 | 
			
		||||
import kotlinx.coroutines.withTimeoutOrNull
 | 
			
		||||
 | 
			
		||||
class WebSocketTester {
 | 
			
		||||
    companion object {
 | 
			
		||||
        @JvmStatic
 | 
			
		||||
        fun main(args: Array<String>) {
 | 
			
		||||
            if (args.size < 4) {
 | 
			
		||||
                println("Usage: WebSocketTester <baseUrl> <clientId> <clientSecret> <botApiKey>")
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val baseUrl = args[0]
 | 
			
		||||
            val clientId = args[1]
 | 
			
		||||
            val clientSecret = args[2]
 | 
			
		||||
            val botApiKey = if (args[3] == "null") null else args[3]
 | 
			
		||||
 | 
			
		||||
            runBlocking {
 | 
			
		||||
                val service = SnService(baseUrl, clientId, clientSecret, botApiKey)
 | 
			
		||||
                println("Starting WebSocket test for $baseUrl")
 | 
			
		||||
 | 
			
		||||
                val result = withTimeoutOrNull(30000L) { // 30 seconds timeout
 | 
			
		||||
                    service.connectWebSocketAsFlow().collect { packet ->
 | 
			
		||||
                        println("Received packet: type=${packet.type}, endpoint=${packet.endpoint}, data=${packet.data}")
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (result == null) {
 | 
			
		||||
                    println("WebSocket test timed out")
 | 
			
		||||
                } else {
 | 
			
		||||
                    println("WebSocket test completed")
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
package dev.solsynth.snConnect.listeners
 | 
			
		||||
 | 
			
		||||
import dev.solsynth.snConnect.services.SnMessageService
 | 
			
		||||
import org.bukkit.event.EventHandler
 | 
			
		||||
import org.bukkit.event.Listener
 | 
			
		||||
import org.bukkit.event.player.AsyncPlayerChatEvent
 | 
			
		||||
import org.bukkit.event.player.PlayerJoinEvent
 | 
			
		||||
import org.bukkit.event.player.PlayerQuitEvent
 | 
			
		||||
 | 
			
		||||
class SnChatListener(private val messageService: SnMessageService, private val destinationChatId: String) : Listener {
 | 
			
		||||
 | 
			
		||||
    @EventHandler
 | 
			
		||||
    fun onPlayerChat(event: AsyncPlayerChatEvent) {
 | 
			
		||||
        val message = "${event.player.name}: ${event.message}"
 | 
			
		||||
        messageService.sendMessage(destinationChatId, message)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @EventHandler
 | 
			
		||||
    fun onPlayerJoin(event: PlayerJoinEvent) {
 | 
			
		||||
        val message = "${event.player.name} joined the game."
 | 
			
		||||
        messageService.sendMessage(destinationChatId, message)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @EventHandler
 | 
			
		||||
    fun onPlayerQuit(event: PlayerQuitEvent) {
 | 
			
		||||
        val message = "${event.player.name} left the game."
 | 
			
		||||
        messageService.sendMessage(destinationChatId, message)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,40 @@
 | 
			
		||||
package dev.solsynth.snConnect.services
 | 
			
		||||
 | 
			
		||||
import kotlinx.serialization.SerialName
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import kotlinx.serialization.json.Json
 | 
			
		||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
 | 
			
		||||
import okhttp3.Request
 | 
			
		||||
import okhttp3.RequestBody.Companion.toRequestBody
 | 
			
		||||
import java.io.IOException
 | 
			
		||||
import java.util.UUID
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
data class SnMessageRequest(
 | 
			
		||||
    val content: String,
 | 
			
		||||
    val nonce: String
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
class SnMessageService(private val sn: SnService) {
 | 
			
		||||
    private val json = Json {
 | 
			
		||||
        ignoreUnknownKeys = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun sendMessage(chatRoomId: String, content: String) {
 | 
			
		||||
        val body = SnMessageRequest(content, UUID.randomUUID().toString())
 | 
			
		||||
        val request = Request.Builder()
 | 
			
		||||
            .url(sn.getUrl("sphere", "/chat/$chatRoomId/messages"))
 | 
			
		||||
            .post(json.encodeToString(body).toRequestBody("application/json".toMediaTypeOrNull()))
 | 
			
		||||
            .apply {
 | 
			
		||||
                sn.botApiKey?.let { header("Authorization", "Bearer $it") }
 | 
			
		||||
            }
 | 
			
		||||
            .build()
 | 
			
		||||
 | 
			
		||||
        sn.client.newCall(request).execute().use { response ->
 | 
			
		||||
            if (!response.isSuccessful) {
 | 
			
		||||
                val responseBody = response.body?.string() ?: "No body"
 | 
			
		||||
                throw IOException("Unexpected code $response: $responseBody")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -12,7 +12,7 @@ import okhttp3.Response
 | 
			
		||||
import okio.ByteString
 | 
			
		||||
import java.util.logging.Logger
 | 
			
		||||
 | 
			
		||||
class SnService(private val baseUrl: String, val clientId: String, val clientSecret: String, private val botApiKey: String?) {
 | 
			
		||||
class SnService(private val baseUrl: String, val clientId: String, val clientSecret: String, val botApiKey: String?) {
 | 
			
		||||
    val client = OkHttpClient.Builder().build();
 | 
			
		||||
    private val logger = Logger.getLogger(SnService::class.java.name)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,9 @@
 | 
			
		||||
sn:
 | 
			
		||||
  endpoint: https://api.sn.solsynth.dev
 | 
			
		||||
  client_id: highland-mc
 | 
			
		||||
  client_secret: 12345678
 | 
			
		||||
  endpoint: https://api.solian.app
 | 
			
		||||
  client_id: goatcraft
 | 
			
		||||
  client_secret: 12345678
 | 
			
		||||
  bot_secret: 114.514.19198
 | 
			
		||||
  destination_chat_id: some_chat_id
 | 
			
		||||
chat:
 | 
			
		||||
  sync_rooms: []
 | 
			
		||||
  outgoing_room: 00000000-0000-0000-0000-00000000008b
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user