🚀 Finishing up the Chat Sync

This commit is contained in:
2025-10-05 03:14:20 +08:00
parent 6303d44ab4
commit 8ef05de8ad
4 changed files with 90 additions and 33 deletions

View File

@@ -1,9 +1,11 @@
package dev.solsynth.snConnect.services
import dev.solsynth.snConnect.models.WebSocketPacket
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.WebSocket
@@ -15,6 +17,7 @@ import java.util.logging.Logger
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)
private var websocket: WebSocket? = null
fun getUrl(service: String, segment: String): String {
return "$baseUrl/$service$segment"
@@ -34,40 +37,60 @@ class SnService(private val baseUrl: String, val clientId: String, val clientSec
return client.newWebSocket(request, listener)
}
fun connectWebSocketAsFlow(): Flow<WebSocketPacket> = callbackFlow {
val url = "${getWsBaseUrl()}/ws";
fun connectWebSocketAsFlow(): Flow<WebSocketPacket> = channelFlow {
val url = "${getWsBaseUrl()}/ws"
val request = Request.Builder()
.url(url)
.apply {
botApiKey?.let { header("Authorization", "Bearer $it") }
}
.build()
val websocket = client.newWebSocket(request, object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
logger.info("WebSocket connection opened to $url")
}
override fun onMessage(webSocket: WebSocket, text: String) {
WebSocketPacket.fromJson(text)?.let { trySend(it) }
}
fun connect() {
websocket = client.newWebSocket(request, object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
logger.info("WebSocket connection opened to $url")
}
override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
val text = bytes.string(Charsets.UTF_8)
WebSocketPacket.fromJson(text)?.let { trySend(it) }
}
override fun onMessage(webSocket: WebSocket, text: String) {
WebSocketPacket.fromJson(text)?.let { trySend(it) }
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
logger.severe("WebSocket connection failed: ${t.message}, response: ${response?.code}")
close(t)
}
override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
val text = bytes.string(Charsets.UTF_8)
WebSocketPacket.fromJson(text)?.let { trySend(it) }
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
logger.severe("WebSocket connection failed: ${t.message}, response: ${response?.code}")
websocket = null
GlobalScope.launch {
delay(1000)
connect()
}
}
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
logger.info("WebSocket connection closed: code=$code, reason=$reason")
websocket = null
GlobalScope.launch {
delay(1000)
connect()
}
}
})
}
connect()
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
logger.info("WebSocket connection closed: code=$code, reason=$reason")
close()
}
})
awaitClose {
websocket.close(1000, "Flow closed")
websocket?.close(1000, "Shutting down")
websocket = null
}
}
fun disconnect() {
websocket?.close(1000, "Disconnecting")
websocket = null
}
}