97 lines
3.2 KiB
Kotlin
97 lines
3.2 KiB
Kotlin
package dev.solsynth.snConnect.services
|
|
|
|
import dev.solsynth.snConnect.models.WebSocketPacket
|
|
import kotlinx.coroutines.GlobalScope
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.flow.Flow
|
|
import kotlinx.coroutines.flow.channelFlow
|
|
import kotlinx.coroutines.launch
|
|
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, 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"
|
|
}
|
|
|
|
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> = channelFlow {
|
|
val url = "${getWsBaseUrl()}/ws"
|
|
val request = Request.Builder()
|
|
.url(url)
|
|
.apply {
|
|
botApiKey?.let { header("Authorization", "Bearer $it") }
|
|
}
|
|
.build()
|
|
|
|
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, 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}")
|
|
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()
|
|
|
|
awaitClose {
|
|
websocket?.close(1000, "Shutting down")
|
|
websocket = null
|
|
}
|
|
}
|
|
|
|
fun disconnect() {
|
|
websocket?.close(1000, "Disconnecting")
|
|
websocket = null
|
|
}
|
|
}
|