Remove jsoup usage and clean up
This commit is contained in:
1 parent
5dc02c0bd5
commit
95631ef468
17 files changed
+46
-57
No files matched your search
@@ -98,7 +98,6 @@ Here is the libraries
|
|||||||
- [Coil](https://coil-kt.github.io/coil/)
|
- [Coil](https://coil-kt.github.io/coil/)
|
||||||
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
||||||
- [libarchive](https://www.libarchive.org/)
|
- [libarchive](https://www.libarchive.org/)
|
||||||
- [jsoup](https://jsoup.org/)
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
|||||||
@@ -240,7 +240,6 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.kotlinx.coroutines.android)
|
implementation(libs.kotlinx.coroutines.android)
|
||||||
implementation(libs.kotlinx.datetime)
|
implementation(libs.kotlinx.datetime)
|
||||||
implementation(libs.jsoup)
|
|
||||||
|
|
||||||
coreLibraryDesugaring(libs.desugar)
|
coreLibraryDesugaring(libs.desugar)
|
||||||
|
|
||||||
|
|||||||
@@ -178,7 +178,8 @@ object EhEngine {
|
|||||||
location.takeIf { "bounce_login" !in it } ?: throw NotLoggedInException()
|
location.takeIf { "bounce_login" !in it } ?: throw NotLoggedInException()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getTorrentList(url: String, gid: Long, token: String): TorrentResult {
|
suspend fun getTorrentList(gid: Long, token: String): TorrentResult {
|
||||||
|
val url = EhUrl.getTorrentUrl(gid, token)
|
||||||
val referer = EhUrl.getGalleryDetailUrl(gid, token)
|
val referer = EhUrl.getGalleryDetailUrl(gid, token)
|
||||||
return ehRequest(url, referer).fetchUsingAsByteBuffer(TorrentParser::parse)
|
return ehRequest(url, referer).fetchUsingAsByteBuffer(TorrentParser::parse)
|
||||||
}
|
}
|
||||||
@@ -188,7 +189,8 @@ object EhEngine {
|
|||||||
"${id}x$key"
|
"${id}x$key"
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getArchiveList(url: String, gid: Long, token: String): ArchiveParser.Result {
|
suspend fun getArchiveList(gid: Long, token: String): ArchiveParser.Result {
|
||||||
|
val url = EhUrl.getArchiveUrl(gid, token)
|
||||||
val funds = if (EhUtils.isExHentai) getFunds() else null
|
val funds = if (EhUtils.isExHentai) getFunds() else null
|
||||||
return ehRequest(url, EhUrl.getGalleryDetailUrl(gid, token))
|
return ehRequest(url, EhUrl.getGalleryDetailUrl(gid, token))
|
||||||
.fetchUsingAsByteBuffer(ArchiveParser::parse.partially2(funds))
|
.fetchUsingAsByteBuffer(ArchiveParser::parse.partially2(funds))
|
||||||
@@ -304,7 +306,7 @@ object EhEngine {
|
|||||||
.fetchUsingAsText(FavoritesParser::parseNote)
|
.fetchUsingAsText(FavoritesParser::parseNote)
|
||||||
|
|
||||||
suspend fun downloadArchive(gid: Long, token: String, res: String, isHath: Boolean): String? {
|
suspend fun downloadArchive(gid: Long, token: String, res: String, isHath: Boolean): String? {
|
||||||
val url = EhUrl.getDownloadArchive(gid, token)
|
val url = EhUrl.getArchiveUrl(gid, token)
|
||||||
val referer = EhUrl.getGalleryDetailUrl(gid, token)
|
val referer = EhUrl.getGalleryDetailUrl(gid, token)
|
||||||
val request = ehRequest(url, referer, EhUrl.origin) {
|
val request = ehRequest(url, referer, EhUrl.origin) {
|
||||||
formBody {
|
formBody {
|
||||||
|
|||||||
@@ -125,7 +125,12 @@ object EhUrl {
|
|||||||
addQueryParameter("act", "addfav")
|
addQueryParameter("act", "addfav")
|
||||||
}.buildString()
|
}.buildString()
|
||||||
|
|
||||||
fun getDownloadArchive(gid: Long, token: String) = ehUrl("archiver.php") {
|
fun getArchiveUrl(gid: Long, token: String) = ehUrl("archiver.php") {
|
||||||
|
addQueryParameter("gid", "$gid")
|
||||||
|
addQueryParameter("token", token)
|
||||||
|
}.buildString()
|
||||||
|
|
||||||
|
fun getTorrentUrl(gid: Long, token: String) = ehUrl("gallerytorrents.php") {
|
||||||
addQueryParameter("gid", "$gid")
|
addQueryParameter("gid", "$gid")
|
||||||
addQueryParameter("token", token)
|
addQueryParameter("token", token)
|
||||||
}.buildString()
|
}.buildString()
|
||||||
|
|||||||
@@ -44,8 +44,6 @@ data class GalleryDetail(
|
|||||||
var apiUid: Long = -1L,
|
var apiUid: Long = -1L,
|
||||||
var apiKey: String? = null,
|
var apiKey: String? = null,
|
||||||
var torrentCount: Int = 0,
|
var torrentCount: Int = 0,
|
||||||
var torrentUrl: String? = null,
|
|
||||||
var archiveUrl: String? = null,
|
|
||||||
var parent: String? = null,
|
var parent: String? = null,
|
||||||
var newerVersions: List<BaseGalleryInfo> = emptyList(),
|
var newerVersions: List<BaseGalleryInfo> = emptyList(),
|
||||||
var visible: String? = null,
|
var visible: String? = null,
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ object HomeParser {
|
|||||||
?: throw ParseException("Parse torrent key error")
|
?: throw ParseException("Parse torrent key error")
|
||||||
|
|
||||||
fun parseFunds(body: String): Funds {
|
fun parseFunds(body: String): Funds {
|
||||||
FundsRegex.find(body)?.groupValues?.run {
|
FundsRegex.find(body)?.run {
|
||||||
val fundsC = ParserUtils.parseInt(get(1), 0)
|
val fundsC = ParserUtils.parseInt(groupValues[1], 0)
|
||||||
val fundsGP = ParserUtils.parseInt(get(2), 0)
|
val fundsGP = ParserUtils.parseInt(groupValues[2], 0)
|
||||||
return Funds(fundsGP, fundsC)
|
return Funds(fundsGP, fundsC)
|
||||||
}
|
}
|
||||||
throw ParseException("Parse funds error")
|
throw ParseException("Parse funds error")
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ package com.hippo.ehviewer.client.parser
|
|||||||
import com.hippo.ehviewer.util.toEpochMillis
|
import com.hippo.ehviewer.util.toEpochMillis
|
||||||
import com.hippo.ehviewer.util.toIntOrDefault
|
import com.hippo.ehviewer.util.toIntOrDefault
|
||||||
import com.hippo.ehviewer.util.toLocalDateTime
|
import com.hippo.ehviewer.util.toLocalDateTime
|
||||||
import com.hippo.ehviewer.util.toLongOrDefault
|
|
||||||
import com.hippo.ehviewer.util.unescapeXml
|
|
||||||
import kotlinx.datetime.LocalDateTime
|
import kotlinx.datetime.LocalDateTime
|
||||||
import kotlinx.datetime.format.char
|
import kotlinx.datetime.format.char
|
||||||
|
|
||||||
@@ -41,9 +39,5 @@ object ParserUtils {
|
|||||||
|
|
||||||
fun parseDate(str: String): Long = formatter.parse(str).toEpochMillis()
|
fun parseDate(str: String): Long = formatter.parse(str).toEpochMillis()
|
||||||
|
|
||||||
fun trim(str: String?): String = str?.unescapeXml()?.trim().orEmpty()
|
fun parseInt(str: String, defValue: Int): Int = str.replace(",", "").toIntOrDefault(defValue)
|
||||||
|
|
||||||
fun parseInt(str: String?, defValue: Int): Int = trim(str).replace(",", "").toIntOrDefault(defValue)
|
|
||||||
|
|
||||||
fun parseLong(str: String?, defValue: Long): Long = trim(str).replace(",", "").toLongOrDefault(defValue)
|
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ private fun GalleryDetail.content() = arrayOf(
|
|||||||
R.string.key_rating_count to ratingCount.toString(),
|
R.string.key_rating_count to ratingCount.toString(),
|
||||||
R.string.key_rating to rating.toString(),
|
R.string.key_rating to rating.toString(),
|
||||||
R.string.key_torrents to torrentCount.toString(),
|
R.string.key_torrents to torrentCount.toString(),
|
||||||
R.string.key_torrent_url to torrentUrl,
|
R.string.key_torrent_url to EhUrl.getTorrentUrl(gid, token),
|
||||||
R.string.favorite_name to favoriteName,
|
R.string.favorite_name to favoriteName,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ fun BelowHeader(galleryDetail: GalleryDetail, voteTag: VoteTag) {
|
|||||||
val archiveResult = remember(galleryDetail) {
|
val archiveResult = remember(galleryDetail) {
|
||||||
async(Dispatchers.IO + Job(), CoroutineStart.LAZY) {
|
async(Dispatchers.IO + Job(), CoroutineStart.LAZY) {
|
||||||
with(galleryDetail) {
|
with(galleryDetail) {
|
||||||
EhEngine.getArchiveList(archiveUrl!!, gid, token)
|
EhEngine.getArchiveList(gid, token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,7 +598,7 @@ fun BelowHeader(galleryDetail: GalleryDetail, voteTag: VoteTag) {
|
|||||||
val torrentResult = remember(galleryDetail) {
|
val torrentResult = remember(galleryDetail) {
|
||||||
async(Dispatchers.IO + Job(), CoroutineStart.LAZY) {
|
async(Dispatchers.IO + Job(), CoroutineStart.LAZY) {
|
||||||
parZip(
|
parZip(
|
||||||
{ EhEngine.getTorrentList(galleryDetail.torrentUrl!!, galleryDetail.gid, galleryDetail.token) },
|
{ EhEngine.getTorrentList(galleryDetail.gid, galleryDetail.token) },
|
||||||
{ EhEngine.getTorrentKey() },
|
{ EhEngine.getTorrentKey() },
|
||||||
{ list, key -> list to key },
|
{ list, key -> list to key },
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package com.hippo.ehviewer.util
|
package com.hippo.ehviewer.util
|
||||||
|
|
||||||
import org.jsoup.parser.Parser
|
private val EntityRegex = "&(?:amp|lt|gt|quot|#039);".toRegex()
|
||||||
|
private val EntityMap = mapOf(
|
||||||
|
"&" to "&",
|
||||||
|
"<" to "<",
|
||||||
|
">" to ">",
|
||||||
|
""" to "\"",
|
||||||
|
"'" to "'", // HTML uses ' instead of '
|
||||||
|
)
|
||||||
|
|
||||||
fun String.unescapeXml(): String = Parser.unescapeEntities(this, true)
|
fun String.unescapeXml() = replace(EntityRegex) { EntityMap[it.value]!! }
|
||||||
|
|
||||||
inline infix fun <T> CharSequence.trimAnd(block: CharSequence.() -> T): T = block(trim())
|
|
||||||
|
|
||||||
fun String.toIntOrDefault(defaultValue: Int): Int = toIntOrNull() ?: defaultValue
|
fun String.toIntOrDefault(defaultValue: Int): Int = toIntOrNull() ?: defaultValue
|
||||||
|
|
||||||
fun String.toLongOrDefault(defaultValue: Long): Long = toLongOrNull() ?: defaultValue
|
|
||||||
|
|
||||||
fun String.toFloatOrDefault(defaultValue: Float): Float = toFloatOrNull() ?: defaultValue
|
|
||||||
|
|
||||||
fun String?.containsIgnoreCase(other: String) = this?.contains(other, true) == true
|
fun String?.containsIgnoreCase(other: String) = this?.contains(other, true) == true
|
||||||
@@ -14,8 +14,6 @@ pub struct GalleryDetail {
|
|||||||
pub apiUid: i64,
|
pub apiUid: i64,
|
||||||
pub apiKey: Option<String>,
|
pub apiKey: Option<String>,
|
||||||
pub torrentCount: i32,
|
pub torrentCount: i32,
|
||||||
pub torrentUrl: Option<String>,
|
|
||||||
pub archiveUrl: Option<String>,
|
|
||||||
pub parent: Option<String>,
|
pub parent: Option<String>,
|
||||||
pub newerVersions: Vec<BaseGalleryInfo>,
|
pub newerVersions: Vec<BaseGalleryInfo>,
|
||||||
pub visible: Option<String>,
|
pub visible: Option<String>,
|
||||||
@@ -148,22 +146,16 @@ fn parse_detail(gd: &mut GalleryDetail, dom: &VDom, parser: &Parser, body: &str)
|
|||||||
gd.apiKey = Some(caps[4].to_string());
|
gd.apiKey = Some(caps[4].to_string());
|
||||||
gd.galleryInfo.rating = caps[5].parse().ok()?;
|
gd.galleryInfo.rating = caps[5].parse().ok()?;
|
||||||
|
|
||||||
let torrent_regex = regex!(
|
let regex = regex!(r#"[^(]+\(([^)]+)"#);
|
||||||
r#"<a[^<>]*onclick="return popUp\('([^']+)'[^)]+\)">Torrent Download \((\d+)\)</a>"#
|
let gd5 = dom.get_element_by_id("gd5")?.get(parser)?.as_tag()?;
|
||||||
);
|
let node = gd5.query_selector(parser, "a[onclick]")?.nth(1)?;
|
||||||
let caps = torrent_regex.captures(body)?;
|
let text = node.get(parser)?.inner_text(parser);
|
||||||
gd.torrentUrl = unescape(&caps[1]).ok().map(|s| s.to_string());
|
let caps = regex.captures(&text)?;
|
||||||
gd.torrentCount = caps[2].parse().ok()?;
|
gd.torrentCount = caps[1].parse().ok()?;
|
||||||
|
|
||||||
let archive_regex =
|
|
||||||
regex!(r#"<a[^<>]*onclick="return popUp\('([^']+)'[^)]+\)">Archive Download</a>"#);
|
|
||||||
let caps = archive_regex.captures(body)?;
|
|
||||||
gd.archiveUrl = unescape(&caps[1]).ok().map(|s| s.to_string());
|
|
||||||
|
|
||||||
let gd1 = dom.get_element_by_id("gd1")?.get(parser)?.as_tag()?;
|
let gd1 = dom.get_element_by_id("gd1")?.get(parser)?.as_tag()?;
|
||||||
let style = get_tag_attr(get_first_child(gd1, parser)?, "style")?;
|
let style = get_tag_attr(get_first_child(gd1, parser)?, "style")?;
|
||||||
let cover_regex = regex!(r#"[^(]+\(([^)]+)"#);
|
let caps = regex.captures(style)?;
|
||||||
let caps = cover_regex.captures(style)?;
|
|
||||||
gd.galleryInfo.thumbKey = get_thumb_key(&caps[1]);
|
gd.galleryInfo.thumbKey = get_thumb_key(&caps[1]);
|
||||||
|
|
||||||
let title = dom.get_element_by_id("gn")?.get(parser)?.inner_text(parser);
|
let title = dom.get_element_by_id("gn")?.get(parser)?.inner_text(parser);
|
||||||
|
|||||||
@@ -96,11 +96,8 @@ fn parse_uploader_and_pages(str: &str) -> (Option<String>, bool, i32) {
|
|||||||
regex!(r#"<a href="https://e[x-]hentai.org/uploader/.*?">(.*?)</a>|(\(Disowned\))"#)
|
regex!(r#"<a href="https://e[x-]hentai.org/uploader/.*?">(.*?)</a>|(\(Disowned\))"#)
|
||||||
.captures(str)
|
.captures(str)
|
||||||
.map(|grp| {
|
.map(|grp| {
|
||||||
grp.get(1)
|
let str = grp.get(1).or_else(|| grp.get(2)).unwrap().as_str();
|
||||||
.or_else(|| grp.get(2))
|
unescape(str).as_deref().unwrap_or(str).to_string()
|
||||||
.unwrap()
|
|
||||||
.as_str()
|
|
||||||
.to_string()
|
|
||||||
});
|
});
|
||||||
let pages = match regex!(r"<div>(\d+) pages</div>").captures(str) {
|
let pages = match regex!(r"<div>(\d+) pages</div>").captures(str) {
|
||||||
None => 0,
|
None => 0,
|
||||||
@@ -155,7 +152,8 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option<BaseGalleryInfo> {
|
|||||||
None => ("".to_string(), None),
|
None => ("".to_string(), None),
|
||||||
Some(node) => (
|
Some(node) => (
|
||||||
node.inner_text(parser).trim().to_string(),
|
node.inner_text(parser).trim().to_string(),
|
||||||
get_node_attr(node, "title").map(str::to_string),
|
get_node_attr(node, "title")
|
||||||
|
.map(|s| unescape(s).as_deref().unwrap_or(s).to_string()),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let ir = get_first_element_by_class_name(node, parser, "ir")?
|
let ir = get_first_element_by_class_name(node, parser, "ir")?
|
||||||
@@ -168,8 +166,11 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option<BaseGalleryInfo> {
|
|||||||
None => (None, false, 0),
|
None => (None, false, 0),
|
||||||
Some(node) => parse_uploader_and_pages(&node.get(parser)?.inner_html(parser)),
|
Some(node) => parse_uploader_and_pages(&node.get(parser)?.inner_html(parser)),
|
||||||
};
|
};
|
||||||
let favorite_note = get_element_by_id(node, parser, format!("favnote_{gid}").as_str())
|
let favorite_note =
|
||||||
.map(|e| e.inner_text(parser).to_string());
|
get_element_by_id(node, parser, format!("favnote_{gid}").as_str()).map(|e| {
|
||||||
|
let str = e.inner_text(parser);
|
||||||
|
unescape(&str).as_deref().unwrap_or(&str).to_string()
|
||||||
|
});
|
||||||
Some(BaseGalleryInfo {
|
Some(BaseGalleryInfo {
|
||||||
gid,
|
gid,
|
||||||
token,
|
token,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::{EhError, get_node_handle_attr, get_tag_attr, select_first};
|
use crate::{EhError, get_node_handle_attr, get_tag_attr, select_first};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
use quick_xml::escape::unescape;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tl::{Parser, VDom};
|
use tl::{Parser, VDom};
|
||||||
|
|
||||||
@@ -26,7 +27,8 @@ pub fn parse_profile(dom: &VDom, parser: &Parser) -> Result<Profile> {
|
|||||||
.next()
|
.next()
|
||||||
.and_then(|n| {
|
.and_then(|n| {
|
||||||
let mut iter = n.get(parser)?.as_tag()?.query_selector(parser, "div")?;
|
let mut iter = n.get(parser)?.as_tag()?.query_selector(parser, "div")?;
|
||||||
let display_name = iter.next()?.get(parser)?.inner_text(parser).to_string();
|
let str = iter.next()?.get(parser)?.inner_text(parser);
|
||||||
|
let display_name = unescape(&str).as_deref().unwrap_or(&str).to_string();
|
||||||
let avatar = iter.next().and_then(|n| {
|
let avatar = iter.next().and_then(|n| {
|
||||||
let img = select_first(n.get(parser)?.as_tag()?, parser, "img")?;
|
let img = select_first(n.get(parser)?.as_tag()?, parser, "img")?;
|
||||||
get_tag_attr(img, "src").map(|src| {
|
get_tag_attr(img, "src").map(|src| {
|
||||||
|
|||||||
@@ -98,7 +98,6 @@
|
|||||||
- [Coil](https://coil-kt.github.io/coil/)
|
- [Coil](https://coil-kt.github.io/coil/)
|
||||||
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
||||||
- [libarchive](https://www.libarchive.org/)
|
- [libarchive](https://www.libarchive.org/)
|
||||||
- [jsoup](https://jsoup.org/)
|
|
||||||
|
|
||||||
# ライセンス
|
# ライセンス
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,6 @@
|
|||||||
- [Coil](https://coil-kt.github.io/coil/)
|
- [Coil](https://coil-kt.github.io/coil/)
|
||||||
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
||||||
- [libarchive](https://www.libarchive.org/)
|
- [libarchive](https://www.libarchive.org/)
|
||||||
- [jsoup](https://jsoup.org/)
|
|
||||||
|
|
||||||
# 许可证
|
# 许可证
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,6 @@
|
|||||||
- [Coil](https://coil-kt.github.io/coil/)
|
- [Coil](https://coil-kt.github.io/coil/)
|
||||||
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
||||||
- [libarchive](https://www.libarchive.org/)
|
- [libarchive](https://www.libarchive.org/)
|
||||||
- [jsoup](https://jsoup.org/)
|
|
||||||
|
|
||||||
# 許可證書
|
# 許可證書
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ material-kolor = "com.materialkolor:material-kolor:2.1.1"
|
|||||||
desugar = "com.android.tools:desugar_jdk_libs:2.1.5"
|
desugar = "com.android.tools:desugar_jdk_libs:2.1.5"
|
||||||
|
|
||||||
diff = "io.github.petertrr:kotlin-multiplatform-diff:1.1.0"
|
diff = "io.github.petertrr:kotlin-multiplatform-diff:1.1.0"
|
||||||
jsoup = "org.jsoup:jsoup:1.20.1"
|
|
||||||
|
|
||||||
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
|
||||||
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
|
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
|
||||||
|
|||||||
Reference in new issue
Block a user