Remove jsoup usage and clean up

This commit is contained in:
FooIbar committed 2025-06-14 19:21:35 +08:00
1 parent 5dc02c0bd5
commit 95631ef468
17 files changed
+46 -57

No files matched your search

-1
View File
@@ -98,7 +98,6 @@ Here is the libraries
- [Coil](https://coil-kt.github.io/coil/)
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
- [libarchive](https://www.libarchive.org/)
- [jsoup](https://jsoup.org/)
# License
-1
View File
@@ -240,7 +240,6 @@ dependencies {
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.datetime)
implementation(libs.jsoup)
coreLibraryDesugaring(libs.desugar)
@@ -178,7 +178,8 @@ object EhEngine {
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)
return ehRequest(url, referer).fetchUsingAsByteBuffer(TorrentParser::parse)
}
@@ -188,7 +189,8 @@ object EhEngine {
"${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
return ehRequest(url, EhUrl.getGalleryDetailUrl(gid, token))
.fetchUsingAsByteBuffer(ArchiveParser::parse.partially2(funds))
@@ -304,7 +306,7 @@ object EhEngine {
.fetchUsingAsText(FavoritesParser::parseNote)
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 request = ehRequest(url, referer, EhUrl.origin) {
formBody {
@@ -125,7 +125,12 @@ object EhUrl {
addQueryParameter("act", "addfav")
}.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("token", token)
}.buildString()
@@ -44,8 +44,6 @@ data class GalleryDetail(
var apiUid: Long = -1L,
var apiKey: String? = null,
var torrentCount: Int = 0,
var torrentUrl: String? = null,
var archiveUrl: String? = null,
var parent: String? = null,
var newerVersions: List<BaseGalleryInfo> = emptyList(),
var visible: String? = null,
@@ -25,9 +25,9 @@ object HomeParser {
?: throw ParseException("Parse torrent key error")
fun parseFunds(body: String): Funds {
FundsRegex.find(body)?.groupValues?.run {
val fundsC = ParserUtils.parseInt(get(1), 0)
val fundsGP = ParserUtils.parseInt(get(2), 0)
FundsRegex.find(body)?.run {
val fundsC = ParserUtils.parseInt(groupValues[1], 0)
val fundsGP = ParserUtils.parseInt(groupValues[2], 0)
return Funds(fundsGP, fundsC)
}
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.toIntOrDefault
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.format.char
@@ -41,9 +39,5 @@ object ParserUtils {
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 = trim(str).replace(",", "").toIntOrDefault(defValue)
fun parseLong(str: String?, defValue: Long): Long = trim(str).replace(",", "").toLongOrDefault(defValue)
fun parseInt(str: String, defValue: Int): Int = str.replace(",", "").toIntOrDefault(defValue)
}
@@ -58,7 +58,7 @@ private fun GalleryDetail.content() = arrayOf(
R.string.key_rating_count to ratingCount.toString(),
R.string.key_rating to rating.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,
)
@@ -551,7 +551,7 @@ fun BelowHeader(galleryDetail: GalleryDetail, voteTag: VoteTag) {
val archiveResult = remember(galleryDetail) {
async(Dispatchers.IO + Job(), CoroutineStart.LAZY) {
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) {
async(Dispatchers.IO + Job(), CoroutineStart.LAZY) {
parZip(
{ EhEngine.getTorrentList(galleryDetail.torrentUrl!!, galleryDetail.gid, galleryDetail.token) },
{ EhEngine.getTorrentList(galleryDetail.gid, galleryDetail.token) },
{ EhEngine.getTorrentKey() },
{ list, key -> list to key },
)
@@ -1,15 +1,16 @@
package com.hippo.ehviewer.util
import org.jsoup.parser.Parser
private val EntityRegex = "&(?:amp|lt|gt|quot|#039);".toRegex()
private val EntityMap = mapOf(
"&amp;" to "&",
"&lt;" to "<",
"&gt;" to ">",
"&quot;" to "\"",
"&#039;" to "'", // HTML uses &#039; instead of &apos;
)
fun String.unescapeXml(): String = Parser.unescapeEntities(this, true)
inline infix fun <T> CharSequence.trimAnd(block: CharSequence.() -> T): T = block(trim())
fun String.unescapeXml() = replace(EntityRegex) { EntityMap[it.value]!! }
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
+7 -15
View File
@@ -14,8 +14,6 @@ pub struct GalleryDetail {
pub apiUid: i64,
pub apiKey: Option<String>,
pub torrentCount: i32,
pub torrentUrl: Option<String>,
pub archiveUrl: Option<String>,
pub parent: Option<String>,
pub newerVersions: Vec<BaseGalleryInfo>,
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.galleryInfo.rating = caps[5].parse().ok()?;
let torrent_regex = regex!(
r#"<a[^<>]*onclick="return popUp\('([^']+)'[^)]+\)">Torrent Download \((\d+)\)</a>"#
);
let caps = torrent_regex.captures(body)?;
gd.torrentUrl = unescape(&caps[1]).ok().map(|s| s.to_string());
gd.torrentCount = caps[2].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 regex = regex!(r#"[^(]+\(([^)]+)"#);
let gd5 = dom.get_element_by_id("gd5")?.get(parser)?.as_tag()?;
let node = gd5.query_selector(parser, "a[onclick]")?.nth(1)?;
let text = node.get(parser)?.inner_text(parser);
let caps = regex.captures(&text)?;
gd.torrentCount = caps[1].parse().ok()?;
let gd1 = dom.get_element_by_id("gd1")?.get(parser)?.as_tag()?;
let style = get_tag_attr(get_first_child(gd1, parser)?, "style")?;
let cover_regex = regex!(r#"[^(]+\(([^)]+)"#);
let caps = cover_regex.captures(style)?;
let caps = regex.captures(style)?;
gd.galleryInfo.thumbKey = get_thumb_key(&caps[1]);
let title = dom.get_element_by_id("gn")?.get(parser)?.inner_text(parser);
+9 -8
View File
@@ -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\))"#)
.captures(str)
.map(|grp| {
grp.get(1)
.or_else(|| grp.get(2))
.unwrap()
.as_str()
.to_string()
let str = grp.get(1).or_else(|| grp.get(2)).unwrap().as_str();
unescape(str).as_deref().unwrap_or(str).to_string()
});
let pages = match regex!(r"<div>(\d+) pages</div>").captures(str) {
None => 0,
@@ -155,7 +152,8 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option<BaseGalleryInfo> {
None => ("".to_string(), None),
Some(node) => (
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")?
@@ -168,8 +166,11 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option<BaseGalleryInfo> {
None => (None, false, 0),
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())
.map(|e| e.inner_text(parser).to_string());
let favorite_note =
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 {
gid,
token,
+3 -1
View File
@@ -1,5 +1,6 @@
use crate::{EhError, get_node_handle_attr, get_tag_attr, select_first};
use anyhow::{Context, Result};
use quick_xml::escape::unescape;
use serde::Serialize;
use tl::{Parser, VDom};
@@ -26,7 +27,8 @@ pub fn parse_profile(dom: &VDom, parser: &Parser) -> Result<Profile> {
.next()
.and_then(|n| {
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 img = select_first(n.get(parser)?.as_tag()?, parser, "img")?;
get_tag_attr(img, "src").map(|src| {
-1
View File
@@ -98,7 +98,6 @@
- [Coil](https://coil-kt.github.io/coil/)
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
- [libarchive](https://www.libarchive.org/)
- [jsoup](https://jsoup.org/)
# ライセンス
-1
View File
@@ -97,7 +97,6 @@
- [Coil](https://coil-kt.github.io/coil/)
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
- [libarchive](https://www.libarchive.org/)
- [jsoup](https://jsoup.org/)
# 许可证
-1
View File
@@ -95,7 +95,6 @@
- [Coil](https://coil-kt.github.io/coil/)
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
- [libarchive](https://www.libarchive.org/)
- [jsoup](https://jsoup.org/)
# 許可證書
-1
View File
@@ -85,7 +85,6 @@ material-kolor = "com.materialkolor:material-kolor:2.1.1"
desugar = "com.android.tools:desugar_jdk_libs:2.1.5"
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-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }