Sync chat from SN

This commit is contained in:
2025-10-05 02:42:21 +08:00
parent affe9a40f5
commit e77841fc09
16 changed files with 580 additions and 17 deletions

View File

@@ -1,11 +1,73 @@
package dev.solsynth.snConnect.services
import dev.solsynth.snConnect.models.WebSocketPacket
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import okhttp3.Response
import okio.ByteString
import java.util.logging.Logger
class SnService(private val baseUrl: String, val clientId: String, val clientSecret: String) {
class SnService(private val baseUrl: String, val clientId: String, val clientSecret: String, private val botApiKey: String?) {
val client = OkHttpClient.Builder().build();
private val logger = Logger.getLogger(SnService::class.java.name)
fun getUrl(service: String, segment: String): String {
return "$baseUrl/cgi/$service$segment"
return "$baseUrl/$service$segment"
}
}
fun getWsBaseUrl(): String {
return baseUrl.replaceFirst("http", "ws")
}
fun connectWebSocket(listener: WebSocketListener): WebSocket {
val request = Request.Builder()
.url("${getWsBaseUrl()}/ws")
.apply {
botApiKey?.let { header("Authorization", "Bearer $it") }
}
.build()
return client.newWebSocket(request, listener)
}
fun connectWebSocketAsFlow(): Flow<WebSocketPacket> = callbackFlow {
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) }
}
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}")
close(t)
}
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")
}
}
}