From 4744caaacca5e8c1911a075fc67a5365b5c34dc1 Mon Sep 17 00:00:00 2001
From: FooIbar <118464521+FooIbar@users.noreply.github.com>
Date: Sun, 27 Oct 2024 15:12:02 +0800
Subject: [PATCH] Show search warnings (if any) when no hits found
---
.../com/hippo/ehviewer/client/EhEngine.kt | 8 +++---
app/src/main/rust/src/lib.rs | 25 +++++++++++++++++--
app/src/main/rust/src/parser/fav.rs | 4 +--
app/src/main/rust/src/parser/list.rs | 11 +++++---
4 files changed, 36 insertions(+), 12 deletions(-)
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")?;