|
|
@@ -0,0 +1,92 @@
|
|
|
+package io.legado.app.web.socket
|
|
|
+
|
|
|
+import fi.iki.elonen.NanoHTTPD
|
|
|
+import fi.iki.elonen.NanoWSD
|
|
|
+import io.legado.app.R
|
|
|
+import io.legado.app.data.entities.SearchBook
|
|
|
+import io.legado.app.help.config.AppConfig
|
|
|
+import io.legado.app.model.webBook.SearchModel
|
|
|
+import io.legado.app.ui.book.search.SearchScope
|
|
|
+import io.legado.app.utils.*
|
|
|
+import kotlinx.coroutines.*
|
|
|
+import kotlinx.coroutines.Dispatchers.IO
|
|
|
+import splitties.init.appCtx
|
|
|
+
|
|
|
+import java.io.IOException
|
|
|
+
|
|
|
+class BookSearchWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) :
|
|
|
+ NanoWSD.WebSocket(handshakeRequest),
|
|
|
+ CoroutineScope by MainScope(),
|
|
|
+ SearchModel.CallBack {
|
|
|
+
|
|
|
+ private val normalClosure = NanoWSD.WebSocketFrame.CloseCode.NormalClosure
|
|
|
+ private val searchModel = SearchModel(this, this)
|
|
|
+
|
|
|
+ private val SEARCH_FINISH = "Search finish"
|
|
|
+
|
|
|
+ override fun onOpen() {
|
|
|
+ launch(IO) {
|
|
|
+ kotlin.runCatching {
|
|
|
+ while (isOpen) {
|
|
|
+ ping("ping".toByteArray())
|
|
|
+ delay(30000)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onClose(
|
|
|
+ code: NanoWSD.WebSocketFrame.CloseCode,
|
|
|
+ reason: String,
|
|
|
+ initiatedByRemote: Boolean
|
|
|
+ ) {
|
|
|
+ cancel()
|
|
|
+ searchModel.close()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onMessage(message: NanoWSD.WebSocketFrame) {
|
|
|
+ launch(IO) {
|
|
|
+ kotlin.runCatching {
|
|
|
+ if (!message.textPayload.isJson()) {
|
|
|
+ send("数据必须为Json格式")
|
|
|
+ close(normalClosure, SEARCH_FINISH, false)
|
|
|
+ return@launch
|
|
|
+ }
|
|
|
+ val searchMap =
|
|
|
+ GSON.fromJsonObject<Map<String, String>>(message.textPayload).getOrNull()
|
|
|
+ if (searchMap != null) {
|
|
|
+ val key = searchMap["key"]
|
|
|
+ if (key.isNullOrBlank()) {
|
|
|
+ send(appCtx.getString(R.string.cannot_empty))
|
|
|
+ close(normalClosure, SEARCH_FINISH, false)
|
|
|
+ return@launch
|
|
|
+ }
|
|
|
+ searchModel.search(System.currentTimeMillis(), key)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onPong(pong: NanoWSD.WebSocketFrame) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onException(exception: IOException) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun getSearchScope(): SearchScope = SearchScope(AppConfig.searchScope)
|
|
|
+
|
|
|
+ override fun onSearchStart() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onSearchSuccess(searchBooks: ArrayList<SearchBook>) {
|
|
|
+ send(GSON.toJson(searchBooks))
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onSearchFinish(isEmpty: Boolean) = close(normalClosure, SEARCH_FINISH, false)
|
|
|
+
|
|
|
+ override fun onSearchCancel(exception: Exception?) = close(normalClosure, exception?.toString() ?: SEARCH_FINISH, false)
|
|
|
+
|
|
|
+}
|