pull/32/head
parent
d7fb601d33
commit
079088d6e5
@ -1,8 +0,0 @@ |
|||||||
package io.legado.app.data.entities.rule |
|
||||||
|
|
||||||
data class BaseRule( |
|
||||||
var selector: String = "", |
|
||||||
var template: String? = null, |
|
||||||
var attr: String? = null, |
|
||||||
var type: RuleType |
|
||||||
) |
|
@ -1,11 +1,14 @@ |
|||||||
package io.legado.app.data.entities.rule |
package io.legado.app.data.entities.rule |
||||||
|
|
||||||
data class BookInfoRule( |
data class BookInfoRule( |
||||||
var name: Rule, |
var urlPattern: String? = null, |
||||||
var author: Rule, |
var init: String? = null, |
||||||
var desc: Rule, |
var name: String? = null, |
||||||
var meta: Rule, |
var author: String? = null, |
||||||
var updateTime: Rule, |
var desc: String? = null, |
||||||
var tocUrl: Rule, |
var meta: String? = null, |
||||||
var store: List<PutRule> |
var lastChapter: String? = null, |
||||||
|
var updateTime: String? = null, |
||||||
|
var coverUrl: String? = null, |
||||||
|
var tocUrl: String? = null |
||||||
) |
) |
@ -1,10 +0,0 @@ |
|||||||
package io.legado.app.data.entities.rule |
|
||||||
|
|
||||||
data class ChapterRule( |
|
||||||
var chapterList: Rule, |
|
||||||
var isReversed: Boolean = false, |
|
||||||
var title: Rule, |
|
||||||
var contentUrl: Rule, |
|
||||||
var resourceUrl: Rule, |
|
||||||
var nextUrl: Rule |
|
||||||
) |
|
@ -1,7 +1,6 @@ |
|||||||
package io.legado.app.data.entities.rule |
package io.legado.app.data.entities.rule |
||||||
|
|
||||||
data class ContentRule( |
data class ContentRule( |
||||||
var fulltext: Rule, |
var content: String? = null, |
||||||
var resourceUrl: Rule, |
var nextUrl: String? = null |
||||||
var nextUrl: Rule |
|
||||||
) |
) |
@ -1,11 +1,14 @@ |
|||||||
package io.legado.app.data.entities.rule |
package io.legado.app.data.entities.rule |
||||||
|
|
||||||
data class ExploreRule( |
data class ExploreRule( |
||||||
var bookList: Rule, |
var exploreUrl: String? = null, |
||||||
var name: Rule, |
var bookList: String? = null, |
||||||
var author: Rule, |
var name: String? = null, |
||||||
var desc: Rule, |
var author: String? = null, |
||||||
var meta: Rule, |
var desc: String? = null, |
||||||
var bookUrl: Rule, |
var meta: String? = null, |
||||||
var store: PutRule |
var lastChapter: String? = null, |
||||||
|
var updateTime: String? = null, |
||||||
|
var bookUrl: String? = null, |
||||||
|
var coverUrl: String? = null |
||||||
) |
) |
@ -1,6 +0,0 @@ |
|||||||
package io.legado.app.data.entities.rule |
|
||||||
|
|
||||||
data class PutRule( |
|
||||||
var selector: Rule, |
|
||||||
var key: String |
|
||||||
) |
|
@ -1,120 +0,0 @@ |
|||||||
package io.legado.app.data.entities.rule |
|
||||||
|
|
||||||
import io.legado.app.utils.safeTrim |
|
||||||
import io.legado.app.utils.splitNotBlank |
|
||||||
|
|
||||||
data class Rule( |
|
||||||
var selectors: List<BaseRule>, |
|
||||||
var regex: String?, |
|
||||||
var replacement: String?, |
|
||||||
var javascript: String?, |
|
||||||
var extra: String? |
|
||||||
) { |
|
||||||
companion object { |
|
||||||
val JS_PATTERN = Regex("""\{\{([^}]+?)}}""") |
|
||||||
val CONST_PATTERN = Regex("""\{(\$\.[^}]+?)}""") |
|
||||||
|
|
||||||
fun parse(input: String) = when { |
|
||||||
input.startsWith("$.") -> parseJSON(input) |
|
||||||
input.startsWith("//") -> parseXPATH(input) |
|
||||||
input.startsWith("RE:") -> parseREGEX(input) |
|
||||||
isJsRule(input) -> parseJS(input) |
|
||||||
isConstRule(input) -> parseCONST(input) |
|
||||||
else -> parseCSS(input) |
|
||||||
} |
|
||||||
|
|
||||||
private fun isJsRule(input: String): Boolean { |
|
||||||
val open = input.indexOf("{{") |
|
||||||
if (open < 0) return false |
|
||||||
val close = input.indexOf("}}", open) |
|
||||||
return close > 0 |
|
||||||
} |
|
||||||
|
|
||||||
private fun isConstRule(input: String): Boolean { |
|
||||||
val open = input.indexOf("{") |
|
||||||
if (open < 0) return false |
|
||||||
val close = input.indexOf("}", open) |
|
||||||
return close > 0 |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private fun parseCSS(rawRule: String): List<BaseRule> { |
|
||||||
val rules = mutableListOf<BaseRule>() |
|
||||||
for (line in rawRule.splitNotBlank("\n")) { |
|
||||||
val baseRule = BaseRule(type = RuleType.CSS) |
|
||||||
if (line.contains("@@")) { |
|
||||||
val temp = line.split("@@") |
|
||||||
baseRule.selector = temp[0].trim() |
|
||||||
baseRule.attr = temp[1].safeTrim() ?: "text" // 写了 @@ 但是后面空白的也默认为 text |
|
||||||
} else { |
|
||||||
baseRule.selector = line |
|
||||||
baseRule.attr = "text" |
|
||||||
} |
|
||||||
rules.add(baseRule) |
|
||||||
} |
|
||||||
return rules |
|
||||||
} |
|
||||||
|
|
||||||
private fun parseJSON(rawRule: String): List<BaseRule> { |
|
||||||
val rules = mutableListOf<BaseRule>() |
|
||||||
for (line in rawRule.splitNotBlank("\n")) { |
|
||||||
val baseRule = BaseRule(type = RuleType.JSON) |
|
||||||
baseRule.selector = line |
|
||||||
rules.add(baseRule) |
|
||||||
} |
|
||||||
return rules |
|
||||||
} |
|
||||||
|
|
||||||
private fun parseXPATH(rawRule: String): List<BaseRule> { |
|
||||||
val rules = mutableListOf<BaseRule>() |
|
||||||
for (line in rawRule.splitNotBlank("\n")) { |
|
||||||
val baseRule = BaseRule(type = RuleType.XPATH) |
|
||||||
baseRule.selector = line |
|
||||||
rules.add(baseRule) |
|
||||||
} |
|
||||||
return rules |
|
||||||
} |
|
||||||
|
|
||||||
private fun parseCONST(rawRule: String): List<BaseRule> { |
|
||||||
val rules = mutableListOf<BaseRule>() |
|
||||||
val subRule = mutableListOf<String>() |
|
||||||
for (line in rawRule.splitNotBlank("\n")) { |
|
||||||
subRule.clear() |
|
||||||
val baseRule = BaseRule(type = RuleType.JSON) |
|
||||||
// 保留 URL 中的 % 字符 |
|
||||||
baseRule.template = CONST_PATTERN.replace(line.replace("%", "%%")) { match -> |
|
||||||
subRule.add(match.groupValues[1]) |
|
||||||
"%s" |
|
||||||
} |
|
||||||
baseRule.selector = subRule.joinToString("\n") |
|
||||||
rules.add(baseRule) |
|
||||||
} |
|
||||||
return rules |
|
||||||
} |
|
||||||
|
|
||||||
private fun parseJS(rawRule: String): List<BaseRule> { |
|
||||||
TODO() |
|
||||||
} |
|
||||||
|
|
||||||
private fun parseREGEX(rawRule: String): List<BaseRule> { |
|
||||||
TODO() |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* |
|
||||||
* CSS 规则说明 |
|
||||||
* 使用 JSOUP 的"选择规则",后面加上需要获取的属性名或者方法,如 href, data-url, text 等,如果不加默认为 text |
|
||||||
* CSS "选择规则" 和 "属性方法" 之间用 @@ 隔开 |
|
||||||
* |
|
||||||
* CONST 规则说明: |
|
||||||
* {$.xxx} 表示要获取 JSON 变量 $.xxx,最先解析 |
|
||||||
* {@.yyy} 表示要获取之前存储的变量 yyy |
|
||||||
* {#.zzz} 表示直接输出 zzz,可以留空,{#.} 什么也不输出 |
|
||||||
* |
|
||||||
* */ |
|
||||||
enum class RuleType { |
|
||||||
CSS, XPATH, JSON, REGEX, CONST, JS, HYBRID |
|
||||||
} |
|
@ -1,11 +1,14 @@ |
|||||||
package io.legado.app.data.entities.rule |
package io.legado.app.data.entities.rule |
||||||
|
|
||||||
data class SearchRule( |
data class SearchRule( |
||||||
var bookList: Rule, |
var searchUrl: String? = null, |
||||||
var name: Rule, |
var bookList: String? = null, |
||||||
var author: Rule, |
var name: String? = null, |
||||||
var desc: Rule, |
var author: String? = null, |
||||||
var meta: Rule, |
var desc: String? = null, |
||||||
var bookUrl: Rule, |
var meta: String? = null, |
||||||
var store: List<PutRule> |
var lastChapter: String? = null, |
||||||
|
var updateTime: String? = null, |
||||||
|
var bookUrl: String? = null, |
||||||
|
var coverUrl: String? = null |
||||||
) |
) |
@ -0,0 +1,8 @@ |
|||||||
|
package io.legado.app.data.entities.rule |
||||||
|
|
||||||
|
data class TocRule( |
||||||
|
var chapterList: String? = null, |
||||||
|
var chapterName: String? = null, |
||||||
|
var chapterUrl: String? = null, |
||||||
|
var nextUrl: String? = null |
||||||
|
) |
Loading…
Reference in new issue