pull/32/head
parent
235f12dd40
commit
59b68e45d4
@ -0,0 +1 @@ |
|||||||
|
# web服务 |
@ -0,0 +1,56 @@ |
|||||||
|
package io.legado.app.web.controller |
||||||
|
|
||||||
|
import io.legado.app.App |
||||||
|
import io.legado.app.data.entities.Book |
||||||
|
import io.legado.app.utils.GSON |
||||||
|
import io.legado.app.utils.fromJsonObject |
||||||
|
import io.legado.app.web.utils.ReturnData |
||||||
|
|
||||||
|
class BookshelfController { |
||||||
|
|
||||||
|
val bookshelf: ReturnData |
||||||
|
get() { |
||||||
|
val books = App.db.bookDao().allBooks |
||||||
|
val returnData = ReturnData() |
||||||
|
return if (books.isEmpty()) { |
||||||
|
returnData.setErrorMsg("还没有添加小说") |
||||||
|
} else returnData.setData(books) |
||||||
|
} |
||||||
|
|
||||||
|
fun getChapterList(parameters: Map<String, List<String>>): ReturnData { |
||||||
|
val strings = parameters["url"] |
||||||
|
val returnData = ReturnData() |
||||||
|
if (strings == null) { |
||||||
|
return returnData.setErrorMsg("参数url不能为空,请指定书籍地址") |
||||||
|
} |
||||||
|
val chapterList = App.db.bookChapterDao().getChapterList(strings[0]) |
||||||
|
return returnData.setData(chapterList) |
||||||
|
} |
||||||
|
|
||||||
|
fun getBookContent(parameters: Map<String, List<String>>): ReturnData { |
||||||
|
val strings = parameters["url"] |
||||||
|
val returnData = ReturnData() |
||||||
|
if (strings == null) { |
||||||
|
return returnData.setErrorMsg("参数url不能为空,请指定内容地址") |
||||||
|
} |
||||||
|
val book = App.db.bookDao().getBook(strings[0]) |
||||||
|
val chapter = App.db.bookChapterDao().getChapter(strings[0], strings[1].toInt()) |
||||||
|
if (book == null || chapter == null) { |
||||||
|
returnData.setErrorMsg("未找到") |
||||||
|
} else { |
||||||
|
|
||||||
|
} |
||||||
|
return returnData |
||||||
|
} |
||||||
|
|
||||||
|
fun saveBook(postData: String): ReturnData { |
||||||
|
val book = GSON.fromJsonObject<Book>(postData) |
||||||
|
val returnData = ReturnData() |
||||||
|
if (book != null) { |
||||||
|
App.db.bookDao().insert(book) |
||||||
|
return returnData.setData("") |
||||||
|
} |
||||||
|
return returnData.setErrorMsg("格式不对") |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
package io.legado.app.web.controller |
||||||
|
|
||||||
|
|
||||||
|
import android.text.TextUtils |
||||||
|
import io.legado.app.App |
||||||
|
import io.legado.app.data.entities.BookSource |
||||||
|
import io.legado.app.utils.GSON |
||||||
|
import io.legado.app.utils.fromJsonArray |
||||||
|
import io.legado.app.utils.fromJsonObject |
||||||
|
import io.legado.app.web.utils.ReturnData |
||||||
|
|
||||||
|
class SourceController { |
||||||
|
|
||||||
|
val sources: ReturnData |
||||||
|
get() { |
||||||
|
val bookSources = App.db.bookSourceDao().all |
||||||
|
val returnData = ReturnData() |
||||||
|
return if (bookSources.isEmpty()) { |
||||||
|
returnData.setErrorMsg("设备书源列表为空") |
||||||
|
} else returnData.setData(bookSources) |
||||||
|
} |
||||||
|
|
||||||
|
fun saveSource(postData: String): ReturnData { |
||||||
|
val returnData = ReturnData() |
||||||
|
try { |
||||||
|
val bookSource = GSON.fromJsonObject<BookSource>(postData) |
||||||
|
if (bookSource != null) { |
||||||
|
if (TextUtils.isEmpty(bookSource.bookSourceName) || TextUtils.isEmpty(bookSource.bookSourceUrl)) { |
||||||
|
returnData.setErrorMsg("书源名称和URL不能为空") |
||||||
|
} else { |
||||||
|
App.db.bookSourceDao().insert(bookSource) |
||||||
|
returnData.setData("") |
||||||
|
} |
||||||
|
} else { |
||||||
|
returnData.setErrorMsg("转换书源失败") |
||||||
|
} |
||||||
|
} catch (e: Exception) { |
||||||
|
returnData.setErrorMsg(e.localizedMessage) |
||||||
|
} |
||||||
|
return returnData |
||||||
|
} |
||||||
|
|
||||||
|
fun saveSources(postData: String): ReturnData { |
||||||
|
val okSources = arrayListOf<BookSource>() |
||||||
|
kotlin.runCatching { |
||||||
|
val bookSources = GSON.fromJsonArray<BookSource>(postData) |
||||||
|
if (bookSources != null) { |
||||||
|
for (bookSource in bookSources) { |
||||||
|
if (bookSource.bookSourceName.isBlank() || bookSource.bookSourceUrl.isBlank()) { |
||||||
|
continue |
||||||
|
} |
||||||
|
App.db.bookSourceDao().insert(bookSource) |
||||||
|
okSources.add(bookSource) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return ReturnData().setData(okSources) |
||||||
|
} |
||||||
|
|
||||||
|
fun getSource(parameters: Map<String, List<String>>): ReturnData { |
||||||
|
val strings = parameters["url"] |
||||||
|
val returnData = ReturnData() |
||||||
|
if (strings == null) { |
||||||
|
return returnData.setErrorMsg("参数url不能为空,请指定书源地址") |
||||||
|
} |
||||||
|
val bookSource = App.db.bookSourceDao().getBookSource(strings[0]) |
||||||
|
?: return returnData.setErrorMsg("未找到书源,请检查书源地址") |
||||||
|
return returnData.setData(bookSource) |
||||||
|
} |
||||||
|
|
||||||
|
fun deleteSources(postData: String): ReturnData { |
||||||
|
kotlin.runCatching { |
||||||
|
GSON.fromJsonArray<BookSource>(postData)?.let { |
||||||
|
App.db.bookSourceDao().delete(*it.toTypedArray()) |
||||||
|
} |
||||||
|
} |
||||||
|
return ReturnData().setData("已执行"/*okSources*/) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
package io.legado.app.web.controller |
||||||
|
|
||||||
|
|
||||||
|
import fi.iki.elonen.NanoHTTPD |
||||||
|
import fi.iki.elonen.NanoWSD |
||||||
|
import io.legado.app.App |
||||||
|
import io.legado.app.R |
||||||
|
import io.legado.app.model.WebBook |
||||||
|
import io.legado.app.model.webbook.SourceDebug |
||||||
|
import io.legado.app.utils.GSON |
||||||
|
import io.legado.app.utils.fromJsonObject |
||||||
|
import io.legado.app.utils.isJson |
||||||
|
import kotlinx.coroutines.* |
||||||
|
import kotlinx.coroutines.Dispatchers.IO |
||||||
|
import java.io.IOException |
||||||
|
|
||||||
|
|
||||||
|
class SourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) : |
||||||
|
NanoWSD.WebSocket(handshakeRequest), |
||||||
|
CoroutineScope by MainScope(), |
||||||
|
SourceDebug.Callback { |
||||||
|
|
||||||
|
|
||||||
|
override fun onOpen() { |
||||||
|
launch(IO) { |
||||||
|
do { |
||||||
|
delay(30000) |
||||||
|
runCatching { |
||||||
|
ping(byteArrayOf("ping".toByte())) |
||||||
|
} |
||||||
|
} while (isOpen) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onClose( |
||||||
|
code: NanoWSD.WebSocketFrame.CloseCode, |
||||||
|
reason: String, |
||||||
|
initiatedByRemote: Boolean |
||||||
|
) { |
||||||
|
cancel() |
||||||
|
SourceDebug.cancelDebug(true) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onMessage(message: NanoWSD.WebSocketFrame) { |
||||||
|
if (!message.textPayload.isJson()) return |
||||||
|
kotlin.runCatching { |
||||||
|
val debugBean = GSON.fromJsonObject<Map<String, String>>(message.textPayload) |
||||||
|
if (debugBean != null) { |
||||||
|
val tag = debugBean["tag"] |
||||||
|
val key = debugBean["key"] |
||||||
|
if (tag.isNullOrBlank() || key.isNullOrBlank()) { |
||||||
|
kotlin.runCatching { |
||||||
|
send(App.INSTANCE.getString(R.string.cannot_empty)) |
||||||
|
close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
App.db.bookSourceDao().getBookSource(tag)?.let { |
||||||
|
SourceDebug(WebBook(it), this).startDebug(key) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onPong(pong: NanoWSD.WebSocketFrame) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
override fun onException(exception: IOException) { |
||||||
|
SourceDebug.cancelDebug(true) |
||||||
|
} |
||||||
|
|
||||||
|
override fun printLog(state: Int, msg: String) { |
||||||
|
kotlin.runCatching { |
||||||
|
send(msg) |
||||||
|
if (state == -1 || state == 1000) { |
||||||
|
SourceDebug.cancelDebug(true) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
package io.legado.app.web.utils |
||||||
|
|
||||||
|
import android.content.res.AssetManager |
||||||
|
import android.text.TextUtils |
||||||
|
import fi.iki.elonen.NanoHTTPD |
||||||
|
import io.legado.app.App |
||||||
|
import java.io.File |
||||||
|
import java.io.IOException |
||||||
|
|
||||||
|
|
||||||
|
class AssetsWeb(rootPath: String) { |
||||||
|
private val assetManager: AssetManager = App.INSTANCE.assets |
||||||
|
private var rootPath = "web" |
||||||
|
|
||||||
|
init { |
||||||
|
if (!TextUtils.isEmpty(rootPath)) { |
||||||
|
this.rootPath = rootPath |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Throws(IOException::class) |
||||||
|
fun getResponse(path: String): NanoHTTPD.Response { |
||||||
|
var path1 = path |
||||||
|
path1 = (rootPath + path1).replace("/+".toRegex(), File.separator) |
||||||
|
val inputStream = assetManager.open(path1) |
||||||
|
return NanoHTTPD.newChunkedResponse( |
||||||
|
NanoHTTPD.Response.Status.OK, |
||||||
|
getMimeType(path1), |
||||||
|
inputStream |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
private fun getMimeType(path: String): String { |
||||||
|
val suffix = path.substring(path.lastIndexOf(".")) |
||||||
|
return when { |
||||||
|
suffix.equals(".html", ignoreCase = true) |
||||||
|
|| suffix.equals(".htm", ignoreCase = true) -> "text/html" |
||||||
|
suffix.equals(".js", ignoreCase = true) -> "text/javascript" |
||||||
|
suffix.equals(".css", ignoreCase = true) -> "text/css" |
||||||
|
suffix.equals(".ico", ignoreCase = true) -> "image/x-icon" |
||||||
|
else -> "text/html" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
package io.legado.app.web.utils |
||||||
|
|
||||||
|
|
||||||
|
class ReturnData { |
||||||
|
|
||||||
|
var isSuccess: Boolean = false |
||||||
|
|
||||||
|
var errorCode: Int = 0 |
||||||
|
|
||||||
|
private var errorMsg: String? = null |
||||||
|
|
||||||
|
private var data: Any? = null |
||||||
|
|
||||||
|
init { |
||||||
|
this.isSuccess = false |
||||||
|
this.errorMsg = "未知错误,请联系开发者!" |
||||||
|
} |
||||||
|
|
||||||
|
fun getErrorMsg(): String? { |
||||||
|
return errorMsg |
||||||
|
} |
||||||
|
|
||||||
|
fun setErrorMsg(errorMsg: String): ReturnData { |
||||||
|
this.isSuccess = false |
||||||
|
this.errorMsg = errorMsg |
||||||
|
return this |
||||||
|
} |
||||||
|
|
||||||
|
fun getData(): Any? { |
||||||
|
return data |
||||||
|
} |
||||||
|
|
||||||
|
fun setData(data: Any): ReturnData { |
||||||
|
this.isSuccess = true |
||||||
|
this.errorMsg = "" |
||||||
|
this.data = data |
||||||
|
return this |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue