diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/EhEngine.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/EhEngine.kt index 1a8a1d2db..aec899024 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/client/EhEngine.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/client/EhEngine.kt @@ -132,10 +132,10 @@ fun rethrowExactly(status: HttpStatusCode, body: Either, e: if (e is ParseException || e is SerializationException) { body.onLeft { if ("<" !in it) throw EhException(it) } when (val message = e.cause?.message) { - "No hits found!" -> throw NoHitsFoundException() - "No watched tags!" -> throw EhException(R.string.gallery_list_empty_hit_subscription) - "Not logged in!" -> throw NotLoggedInException() - is String -> if (message.startsWith("Your IP address")) throw EhException(message) + "0" -> throw NoHitsFoundException() + "1" -> throw EhException(R.string.gallery_list_empty_hit_subscription) + "2" -> throw NotLoggedInException() + is String if message.startsWith('3') -> throw EhException(message.drop(1)) } if (Settings.saveParseErrorBody) body.saveParseError(e) throw EhException(appCtx.getString(R.string.error_parse_error), e) diff --git a/app/src/main/rust/src/lib.rs b/app/src/main/rust/src/lib.rs index 55a4f1dfa..b60d15ece 100644 --- a/app/src/main/rust/src/lib.rs +++ b/app/src/main/rust/src/lib.rs @@ -11,6 +11,7 @@ use log::LevelFilter; use ndk::bitmap::Bitmap; use serde::Serialize; use std::ffi::c_void; +use std::fmt::{Debug, Display, Formatter}; use std::io::Cursor; use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut}; use std::str::from_utf8_unchecked; @@ -26,7 +27,7 @@ macro_rules! regex { } const EHGT_PREFIX: &str = "https://ehgt.org/"; -const EX_PREFIX: &str = "https://s.exhentai.org/"; +const EX_PREFIX: &str = "https://s.exhentai.org/t/"; fn get_vdom_first_element_by_class_name<'a>(dom: &'a VDom, name: &str) -> Option<&'a Node<'a>> { let handle = dom.get_elements_by_class_name(name).next()?; @@ -94,6 +95,26 @@ impl ThrowingHasDefault for () { fn default() -> Self {} } +#[derive(Debug)] +enum EhError { + NoHits, + NoWatched, + NeedLogin, + Error(String), +} + +impl Display for EhError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let msg = match self { + EhError::NoHits => "0", + EhError::NoWatched => "1", + EhError::NeedLogin => "2", + EhError::Error(s) => &format!("3{s}"), + }; + f.write_str(msg) + } +} + fn jni_throwing(env: &mut JNIEnv, f: F) -> R where F: FnOnce(&mut JNIEnv) -> Result, @@ -121,7 +142,7 @@ where let html = unsafe { from_utf8_unchecked(&buffer[..limit as usize]) }; let dom = tl::parse(html, ParserOptions::default())?; - ensure!(dom.version().is_some(), "{html}"); + ensure!(dom.version().is_some(), EhError::Error(html.to_string())); f(&dom, html)? }; let mut cursor = Cursor::new(buffer); diff --git a/app/src/main/rust/src/parser/fav.rs b/app/src/main/rust/src/parser/fav.rs index f7f97cf57..c52a36a7c 100644 --- a/app/src/main/rust/src/parser/fav.rs +++ b/app/src/main/rust/src/parser/fav.rs @@ -1,5 +1,5 @@ -use crate::parse_marshal_inplace; use crate::parser::list::{parse_info_list, GalleryListResult}; +use crate::{parse_marshal_inplace, EhError}; use anyhow::{bail, Result}; use jni::objects::{JByteBuffer, JClass}; use jni::sys::jint; @@ -20,7 +20,7 @@ struct FavResult { fn parse_fav(dom: &VDom, parser: &Parser, html: &str) -> Result { if html.contains("This page requires you to log on.

") { - bail!("Not logged in!") + bail!(EhError::NeedLogin) } let vec: Vec<(String, i32)> = dom .get_elements_by_class_name("fp") diff --git a/app/src/main/rust/src/parser/list.rs b/app/src/main/rust/src/parser/list.rs index b02590232..3bc9a2365 100644 --- a/app/src/main/rust/src/parser/list.rs +++ b/app/src/main/rust/src/parser/list.rs @@ -1,7 +1,7 @@ -use crate::parse_marshal_inplace; use crate::{get_element_by_id, get_vdom_first_element_by_class_name}; use crate::{get_first_element_by_class_name, query_childs_first_match_attr}; use crate::{get_node_attr, get_node_handle_attr, regex}; +use crate::{parse_marshal_inplace, EhError}; use crate::{EHGT_PREFIX, EX_PREFIX}; use anyhow::{bail, Context, Result}; use jni::objects::{JByteBuffer, JClass}; @@ -82,7 +82,6 @@ fn parse_rating(str: &str) -> f32 { fn get_thumb_key(url: &str) -> String { url.trim_start_matches(EHGT_PREFIX) .trim_start_matches(EX_PREFIX) - .trim_start_matches("t/") .to_string() } @@ -199,10 +198,14 @@ fn parse_gallery_info(node: &Node, parser: &Parser) -> Option { pub fn parse_info_list(dom: &VDom, parser: &Parser, str: &str) -> Result { if str.contains("

You do not have any watched tags") { - bail!("No watched tags!") + bail!(EhError::NoWatched) } if str.contains("No hits found

") || str.contains("No unfiltered results") { - bail!("No hits found!") + let e = get_vdom_first_element_by_class_name(dom, "searchwarn") + .map_or(EhError::NoHits, |n| { + EhError::Error(n.inner_text(parser).to_string()) + }); + bail!(e) } let f = || { let itg = get_vdom_first_element_by_class_name(dom, "itg")?;