diff --git a/api.md b/api.md index a6eea3ca3..fd92ca2fb 100644 --- a/api.md +++ b/api.md @@ -59,6 +59,16 @@ URL = http://127.0.0.1:1234/deleteRssSources Method = POST ``` +#### 调试源 + +key为书源搜索关键词,tag为源链接 + +``` +URL = ws://127.0.0.1:1235/bookSourceDebug +URL = ws://127.0.0.1:1235/rssSourceDebug +Message = { key: [String], tag: [String] } +``` + #### 获取替换规则 ``` @@ -99,9 +109,8 @@ Body = { rule: [ReplaceRule], text: [String] } #### 搜索在线书籍 ``` -URL = http://127.0.0.1:1234/searchBook -Method = POST -Body = { key: [String], page: [Number] } +URL = ws://127.0.0.1:1235/searchBook +Message = { key: [String] } ``` #### 插入书籍 diff --git a/app/src/main/java/io/legado/app/api/controller/BookController.kt b/app/src/main/java/io/legado/app/api/controller/BookController.kt index a1244208e..38bcd35ed 100644 --- a/app/src/main/java/io/legado/app/api/controller/BookController.kt +++ b/app/src/main/java/io/legado/app/api/controller/BookController.kt @@ -200,7 +200,7 @@ object BookController { fun saveBook(postData: String?): ReturnData { val returnData = ReturnData() GSON.fromJsonObject(postData).getOrNull()?.let { book -> - appDb.bookDao.update(book) + appDb.bookDao.insert(book) AppWebDav.uploadBookProgress(book) return returnData.setData("") } diff --git a/app/src/main/java/io/legado/app/web/HttpServer.kt b/app/src/main/java/io/legado/app/web/HttpServer.kt index 71b915410..b5f4183c4 100644 --- a/app/src/main/java/io/legado/app/web/HttpServer.kt +++ b/app/src/main/java/io/legado/app/web/HttpServer.kt @@ -1,7 +1,6 @@ package io.legado.app.web import android.graphics.Bitmap -import com.google.gson.Gson import fi.iki.elonen.NanoHTTPD import io.legado.app.api.ReturnData import io.legado.app.api.controller.BookController @@ -9,13 +8,11 @@ import io.legado.app.api.controller.BookSourceController import io.legado.app.api.controller.ReplaceRuleController import io.legado.app.api.controller.RssSourceController import io.legado.app.service.WebService -import io.legado.app.utils.FileUtils -import io.legado.app.utils.externalFiles +import io.legado.app.utils.* import io.legado.app.web.utils.AssetsWeb import splitties.init.appCtx import java.io.* - class HttpServer(port: Int) : NanoHTTPD(port) { private val assetsWeb = AssetsWeb("web") @@ -100,7 +97,7 @@ class HttpServer(port: Int) : NanoHTTPD(port) { ) } else { try { - newFixedLengthResponse(Gson().toJson(returnData)) + newFixedLengthResponse(GSON.toJson(returnData)) } catch (e: OutOfMemoryError) { val path = FileUtils.getPath( appCtx.externalFiles, @@ -109,7 +106,7 @@ class HttpServer(port: Int) : NanoHTTPD(port) { ) val file = FileUtils.createFileIfNotExist(path) BufferedWriter(FileWriter(file)).use { - Gson().toJson(returnData, it) + GSON.toJson(returnData, it) } val fis = FileInputStream(file) newFixedLengthResponse( diff --git a/app/src/main/java/io/legado/app/web/WebSocketServer.kt b/app/src/main/java/io/legado/app/web/WebSocketServer.kt index 3e95c2101..f2c7c27a0 100644 --- a/app/src/main/java/io/legado/app/web/WebSocketServer.kt +++ b/app/src/main/java/io/legado/app/web/WebSocketServer.kt @@ -2,8 +2,7 @@ package io.legado.app.web import fi.iki.elonen.NanoWSD import io.legado.app.service.WebService -import io.legado.app.web.socket.BookSourceDebugWebSocket -import io.legado.app.web.socket.RssSourceDebugWebSocket +import io.legado.app.web.socket.* class WebSocketServer(port: Int) : NanoWSD(port) { @@ -16,6 +15,9 @@ class WebSocketServer(port: Int) : NanoWSD(port) { "/rssSourceDebug" -> { RssSourceDebugWebSocket(handshake) } + "/searchBook" -> { + BookSearchWebSocket(handshake) + } else -> null } } diff --git a/app/src/main/java/io/legado/app/web/socket/BookSearchWebSocket.kt b/app/src/main/java/io/legado/app/web/socket/BookSearchWebSocket.kt new file mode 100644 index 000000000..abb83af7f --- /dev/null +++ b/app/src/main/java/io/legado/app/web/socket/BookSearchWebSocket.kt @@ -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>(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) { + 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) + +}