Przeglądaj źródła

Merge pull request #1874 from Xwite/master

refactor:在线书籍文件导入
kunfei 4 lat temu
rodzic
commit
64c93032c0

+ 1 - 1
app/src/main/assets/web/bookSource/index.html

@@ -25,7 +25,7 @@
             <div>
                 <div>源类型 :</div>
                 <textarea rows="1" id="bookSourceType" class="base" title="bookSourceType"
-                          placeholder="&lt;必填&gt;0:文本 1:音频 2:图片"></textarea>
+                          placeholder="&lt;必填&gt;0:文本 1:音频 2:图片 3:文件(只提供下载的网站)"></textarea>
             </div>
             <div>
                 <div>源名称 :</div>

+ 1 - 43
app/src/main/java/io/legado/app/api/controller/BookController.kt

@@ -1,9 +1,7 @@
 package io.legado.app.api.controller
 
 import android.net.Uri
-import android.util.Base64
 import androidx.core.graphics.drawable.toBitmap
-import androidx.documentfile.provider.DocumentFile
 import io.legado.app.api.ReturnData
 import io.legado.app.constant.PreferKey
 import io.legado.app.data.appDb
@@ -12,7 +10,6 @@ import io.legado.app.data.entities.BookSource
 import io.legado.app.help.BookHelp
 import io.legado.app.help.CacheManager
 import io.legado.app.help.ContentProcessor
-import io.legado.app.help.config.AppConfig
 import io.legado.app.help.glide.ImageLoader
 import io.legado.app.help.storage.AppWebDav
 import io.legado.app.model.BookCover
@@ -27,7 +24,6 @@ import kotlinx.coroutines.delay
 import kotlinx.coroutines.runBlocking
 import splitties.init.appCtx
 import java.io.File
-import java.io.FileOutputStream
 
 object BookController {
 
@@ -248,45 +244,7 @@ object BookController {
         val fileData = parameters["fileData"]?.firstOrNull()
             ?: return returnData.setErrorMsg("fileData 不能为空")
         kotlin.runCatching {
-            val defaultBookTreeUri = AppConfig.defaultBookTreeUri
-            if (defaultBookTreeUri.isNullOrBlank()) return returnData.setErrorMsg("没有设置书籍保存位置!")
-            val treeUri = Uri.parse(defaultBookTreeUri)
-            val fileBytes =
-                Base64.decode(fileData.substringAfter("base64,"), Base64.DEFAULT)
-            val uri = if (treeUri.isContentScheme()) {
-                val treeDoc = DocumentFile.fromTreeUri(appCtx, treeUri)
-                var doc = treeDoc!!.findFile(fileName)
-                if (doc == null) {
-                    doc = treeDoc.createFile(FileUtils.getMimeType(fileName), fileName)
-                        ?: throw SecurityException("Permission Denial")
-                }
-                appCtx.contentResolver.openOutputStream(doc.uri)!!.use { oStream ->
-                    oStream.write(fileBytes)
-                }
-                doc.uri
-            } else {
-                val treeFile = File(treeUri.path!!)
-                val file = treeFile.getFile(fileName)
-                FileOutputStream(file).use { oStream ->
-                    oStream.write(fileBytes)
-                }
-                Uri.fromFile(file)
-            }
-            val nameAuthor = LocalBook.analyzeNameAuthor(fileName)
-            val book = Book(
-                bookUrl = uri.toString(),
-                name = nameAuthor.first,
-                author = nameAuthor.second,
-                originName = fileName,
-                coverUrl = FileUtils.getPath(
-                    appCtx.externalFiles,
-                    "covers",
-                    "${MD5Utils.md5Encode16(uri.toString())}.jpg"
-                )
-            )
-            if (book.isEpub()) EpubFile.upBookInfo(book)
-            if (book.isUmd()) UmdFile.upBookInfo(book)
-            appDb.bookDao.insert(book)
+           LocalBook.importFile(fileData, fileName)
         }.onFailure {
             return when (it) {
                 is SecurityException -> returnData.setErrorMsg("需重新设置书籍保存位置!")

+ 2 - 1
app/src/main/java/io/legado/app/constant/BookType.kt

@@ -5,7 +5,8 @@ import androidx.annotation.IntDef
 object BookType {
     const val default = 0           // 0 文本
     const val audio = 1             // 1 音频
-    const val image = 2             //图片
+    const val image = 2            // 2 图片
+    const val file = 3               // 3 只提供下载服务的网站
     const val local = "loc_book"
 
     @Target(AnnotationTarget.VALUE_PARAMETER)

+ 1 - 1
app/src/main/java/io/legado/app/data/entities/BookSource.kt

@@ -27,7 +27,7 @@ data class BookSource(
     var bookSourceName: String = "",
     // 分组
     var bookSourceGroup: String? = null,
-    // 类型,0 文本,1 音频, 2 图片
+    // 类型,0 文本,1 音频, 2 图片, 3 文件(指的是类似知轩藏书只提供下载的网站)
     @BookType.Type
     var bookSourceType: Int = 0,
     // 详情页url正则

+ 5 - 9
app/src/main/java/io/legado/app/help/JsExtensions.kt

@@ -197,12 +197,10 @@ interface JsExtensions {
      *js实现读取cookie
      */
     fun getCookie(tag: String, key: String? = null): String {
-        val cookie = CookieStore.getCookie(tag)
-        val cookieMap = CookieStore.cookieToMap(cookie)
         return if (key != null) {
-            cookieMap[key] ?: ""
+            CookieStore.getKey(tag, key)
         } else {
-            cookie
+            CookieStore.getCookie(tag)
         }
     }
 
@@ -470,10 +468,8 @@ interface JsExtensions {
      * @return zip指定文件的数据
      */
     fun getZipByteArrayContent(url: String, path: String): ByteArray? {
-        val bytes = if (url.startsWith("http://") || url.startsWith("https://")) {
-            runBlocking {
-                return@runBlocking okHttpClient.newCallResponseBody { url(url) }.bytes()
-            }
+        val bytes = if (url.isAbsUrl()) {
+            AnalyzeUrl(url, source = getSource()).getByteArray()
         } else {
             StringUtils.hexStringToByte(url)
         }
@@ -517,7 +513,7 @@ interface JsExtensions {
                 str.isAbsUrl() -> runBlocking {
                     var x = CacheManager.getByteArray(key)
                     if (x == null) {
-                        x = okHttpClient.newCallResponseBody { url(str) }.bytes()
+                        x = AnalyzeUrl(str, source = getSource()).getByteArray()
                         x.let {
                             CacheManager.put(key, it)
                         }

+ 60 - 1
app/src/main/java/io/legado/app/model/localBook/LocalBook.kt

@@ -1,6 +1,7 @@
 package io.legado.app.model.localBook
 
 import android.net.Uri
+import android.util.Base64
 import androidx.documentfile.provider.DocumentFile
 import com.script.SimpleBindings
 import io.legado.app.R
@@ -8,13 +9,17 @@ import io.legado.app.constant.AppConst
 import io.legado.app.data.appDb
 import io.legado.app.data.entities.Book
 import io.legado.app.data.entities.BookChapter
+import io.legado.app.data.entities.BaseSource
 import io.legado.app.exception.TocEmptyException
+import io.legado.app.exception.NoStackTraceException
 import io.legado.app.help.BookHelp
 import io.legado.app.help.config.AppConfig
+import io.legado.app.model.analyzeRule.AnalyzeUrl
 import io.legado.app.utils.*
 import splitties.init.appCtx
 import java.io.File
 import java.io.FileInputStream
+import java.io.FileOutputStream
 import java.io.FileNotFoundException
 import java.io.InputStream
 import java.util.regex.Pattern
@@ -79,6 +84,32 @@ object LocalBook {
         }
     }
 
+    //导入在线的文件
+    fun importFile(
+        str: String,
+        fileName: String,
+        source: BaseSource? = null
+    ): Book {
+        val bytes = when {
+            str.isAbsUrl() -> AnalyzeUrl(str, source = source).getByteArray()
+            str.isDataUrl() -> Base64.decode(str.substringAfter("base64,"), Base64.DEFAULT)
+            else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL")
+        }
+        //从文件头识别文件格式
+        
+        return importFile(bytes, fileName)
+    }
+
+    fun importFile(
+        bytes: ByteArray,
+        fileName: String
+    ): Book {
+        return saveBookFile(bytes, fileName).let {
+            importFile(it)
+        }
+    }
+
+    //导入本地文件
     fun importFile(uri: Uri): Book {
         val bookUrl: String
         val updateTime: Long
@@ -119,7 +150,7 @@ object LocalBook {
         return book
     }
 
-    fun analyzeNameAuthor(fileName: String): Pair<String, String> {
+    private fun analyzeNameAuthor(fileName: String): Pair<String, String> {
         val tempFileName = fileName.substringBeforeLast(".")
         var name: String
         var author: String
@@ -171,4 +202,32 @@ object LocalBook {
             }
         }
     }
+
+    private fun saveBookFile(
+        bytes: ByteArray,
+        fileName: String
+    ): Uri {
+        val defaultBookTreeUri = AppConfig.defaultBookTreeUri
+        if (defaultBookTreeUri.isNullOrBlank()) throw NoStackTraceException("没有设置书籍保存位置!")
+        val treeUri = Uri.parse(defaultBookTreeUri)
+        return if (treeUri.isContentScheme()) {
+            val treeDoc = DocumentFile.fromTreeUri(appCtx, treeUri)
+            var doc = treeDoc!!.findFile(fileName)
+            if (doc == null) {
+                doc = treeDoc.createFile(FileUtils.getMimeType(fileName), fileName)
+                    ?: throw SecurityException("Permission Denial")
+            }
+            appCtx.contentResolver.openOutputStream(doc.uri)!!.use { oStream ->
+                oStream.write(bytes)
+            }
+            doc.uri
+        } else {
+            val treeFile = File(treeUri.path!!)
+            val file = treeFile.getFile(fileName)
+            FileOutputStream(file).use { oStream ->
+                oStream.write(bytes)
+            }
+            Uri.fromFile(file)
+        }
+    }
 }

+ 2 - 0
app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt

@@ -192,6 +192,7 @@ class BookSourceEditActivity :
             binding.cbIsEnableFind.isChecked = it.enabledExplore
             binding.spType.setSelection(
                 when (it.bookSourceType) {
+                    BookType.file -> 3
                     BookType.image -> 2
                     BookType.audio -> 1
                     else -> 0
@@ -296,6 +297,7 @@ class BookSourceEditActivity :
         source.enabled = binding.cbIsEnable.isChecked
         source.enabledExplore = binding.cbIsEnableFind.isChecked
         source.bookSourceType = when (binding.spType.selectedItemPosition) {
+            3 -> BookType.file
             2 -> BookType.image
             1 -> BookType.audio
             else -> BookType.default

+ 1 - 0
app/src/main/res/values-es-rES/arrays.xml

@@ -4,6 +4,7 @@
 		<item>Texto</item>
 		<item>Audio</item>
 		<item>Image</item>
+		<item>File</item>
 	</string-array>
 
 	<string-array name="group_style">

+ 1 - 0
app/src/main/res/values-pt-rBR/arrays.xml

@@ -4,6 +4,7 @@
 		<item>Texto</item>
 		<item>Áudio</item>
 		<item>Image</item>
+		<item>File</item>
 	</string-array>
 
 	<string-array name="group_style">

+ 1 - 0
app/src/main/res/values-zh-rHK/arrays.xml

@@ -5,6 +5,7 @@
         <item>文本</item>
         <item>音頻</item>
         <item>图片</item>
+        <item>文件</item>
     </string-array>
 
     <string-array name="group_style">

+ 1 - 0
app/src/main/res/values-zh-rTW/arrays.xml

@@ -4,6 +4,7 @@
         <item>文字</item>
         <item>音訊</item>
         <item>图片</item>
+        <item>文件</item>
     </string-array>
 
     <string-array name="group_style">

+ 1 - 0
app/src/main/res/values-zh/arrays.xml

@@ -4,6 +4,7 @@
         <item>文本</item>
         <item>音频</item>
         <item>图片</item>
+        <item>文件</item>
     </string-array>
 
     <string-array name="group_style">

+ 1 - 0
app/src/main/res/values/arrays.xml

@@ -4,6 +4,7 @@
 		<item>Text</item>
 		<item>Audio</item>
 		<item>Image</item>
+		<item>File</item>
 	</string-array>
 
 	<string-array name="group_style">