Convert GalleryListParser and FavoritesParser to kotlin

This commit is contained in:
FooIbar authored and tarsin committed 2023-03-10 20:08:52 +08:00
1 parent e076f34993
commit 9d9c09743c
5 files changed
+245 -316

No files matched your search

+1 -1
View File
@@ -192,7 +192,7 @@ object EhDB {
@Synchronized
fun containLocalFavorites(gid: Long): Boolean {
val dao = db.localFavoritesDao()
return null != dao.load(gid)
return dao.contains(gid)
}
@Synchronized
@@ -161,17 +161,7 @@ object EhEngine {
) {
// Filter title and uploader
if (filter) {
var i = 0
var n = list.size
while (i < n) {
val info = list[i]
if (!sEhFilter.filterTitle(info) || !sEhFilter.filterUploader(info)) {
list.removeAt(i)
i--
n--
}
i++
}
list.removeAll { !sEhFilter.filterTitle(it) || !sEhFilter.filterUploader(it) }
}
var hasTags = false
var hasPages = false
@@ -187,29 +177,18 @@ object EhEngine {
hasRated = true
}
}
val needApi =
filter && sEhFilter.needTags() && !hasTags || Settings.showGalleryPages && !hasPages ||
hasRated
val needApi = filter && sEhFilter.needTags() && !hasTags
|| Settings.showGalleryPages && !hasPages || hasRated
if (needApi) {
fillGalleryListByApi(list, url)
}
// Filter tag
if (filter) {
var i = 0
var n = list.size
while (i < n) {
val info = list[i]
// Thumbnail mode need filter uploader again
if (!sEhFilter.filterUploader(info) || !sEhFilter.filterTag(info) || !sEhFilter.filterTagNamespace(
info
)
) {
list.removeAt(i)
i--
n--
}
i++
// Thumbnail mode need filter uploader again
list.removeAll {
!sEhFilter.filterUploader(it) || !sEhFilter.filterTag(it)
|| !sEhFilter.filterTagNamespace(it)
}
}
}
@@ -556,7 +535,10 @@ object EhEngine {
suspend fun getProfile(): ProfileParser.Result {
val url = EhUrl.URL_FORUMS
Log.d(TAG, url)
return getProfileInternal(EhRequestBuilder(url).executeAndParsingWith(ForumsParser::parse), url)
return getProfileInternal(
EhRequestBuilder(url).executeAndParsingWith(ForumsParser::parse),
url
)
}
private suspend fun getUConfigInternal(url: String) {
@@ -13,69 +13,50 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.client.parser
package com.hippo.ehviewer.client.parser;
import com.hippo.ehviewer.GetText.getString
import com.hippo.ehviewer.R
import com.hippo.ehviewer.client.exception.EhException
import com.hippo.ehviewer.client.exception.ParseException
import com.hippo.util.ExceptionUtils
import com.hippo.util.JsoupUtils
import org.jsoup.Jsoup
import com.hippo.ehviewer.GetText;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.client.data.GalleryInfo;
import com.hippo.ehviewer.client.exception.EhException;
import com.hippo.ehviewer.client.exception.ParseException;
import com.hippo.util.ExceptionUtils;
import com.hippo.util.JsoupUtils;
import com.hippo.yorozuya.AssertUtilsKt;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.List;
public class FavoritesParser {
public static Result parse(String body) throws Exception {
object FavoritesParser {
fun parse(body: String): Result {
if (body.contains("This page requires you to log on.</p>")) {
throw new EhException(GetText.getString(R.string.need_sign_in));
throw EhException(getString(R.string.need_sign_in))
}
String[] catArray = new String[10];
int[] countArray = new int[10];
try {
Document d = Jsoup.parse(body);
Element ido = JsoupUtils.getElementByClass(d, "ido");
//noinspection ConstantConditions
Elements fps = ido.getElementsByClass("fp");
val catArray = arrayOfNulls<String>(10)
val countArray = IntArray(10)
val d = Jsoup.parse(body)
runCatching {
val ido = JsoupUtils.getElementByClass(d, "ido")
val fps = ido!!.getElementsByClass("fp")
// Last one is "fp fps"
AssertUtilsKt.assertEquals(11, fps.size());
for (int i = 0; i < 10; i++) {
Element fp = fps.get(i);
countArray[i] = ParserUtils.parseInt(fp.child(0).text(), 0);
catArray[i] = ParserUtils.trim(fp.child(2).text());
check(fps.size == 11)
for (i in 0..9) {
val fp = fps[i]
countArray[i] = ParserUtils.parseInt(fp.child(0).text(), 0)
catArray[i] = ParserUtils.trim(fp.child(2).text())
}
} catch (Throwable e) {
ExceptionUtils.throwIfFatal(e);
e.printStackTrace();
throw new ParseException("Parse favorites error", body);
}.onFailure {
ExceptionUtils.throwIfFatal(it)
it.printStackTrace()
throw ParseException("Parse favorites error", body)
}
GalleryListParser.Result result = GalleryListParser.parse(body);
Result re = new Result();
re.catArray = catArray;
re.countArray = countArray;
re.prev = result.prev;
re.next = result.next;
re.galleryInfoList = result.galleryInfoList;
return re;
val result = GalleryListParser.parse(d, body)
return Result(catArray, countArray, result)
}
public static class Result {
public String[] catArray; // Size 10
public int[] countArray; // Size 10
public String prev;
public String next;
public List<GalleryInfo> galleryInfoList;
class Result(
val catArray: Array<String?>,
val countArray: IntArray,
galleryListResult: GalleryListParser.Result
) {
val prev = galleryListResult.prev
val next = galleryListResult.next
val galleryInfoList = galleryListResult.galleryInfoList
}
}
}
@@ -13,362 +13,325 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.client.parser
package com.hippo.ehviewer.client.parser;
import android.util.Log
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.BaseGalleryInfo
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.client.exception.ParseException
import com.hippo.util.ExceptionUtils
import com.hippo.util.JsoupUtils
import com.hippo.yorozuya.NumberUtils
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import java.util.regex.Pattern
import android.text.TextUtils;
import android.util.Log;
object GalleryListParser {
private val TAG = GalleryListParser::class.java.simpleName
private const val NO_UNFILTERED_TEXT =
"No unfiltered results in this page range. You either requested an invalid page or used too aggressive filters."
private val PATTERN_RATING = Pattern.compile("\\d+px")
private val PATTERN_THUMB_SIZE = Pattern.compile("height:(\\d+)px;width:(\\d+)px")
private val PATTERN_FAVORITE_SLOT =
Pattern.compile("background-color:rgba\\((\\d+),(\\d+),(\\d+),")
private val PATTERN_PAGES = Pattern.compile("(\\d+) page")
private val PATTERN_NEXT_PAGE = Pattern.compile("p=(\\d+)")
private val PATTERN_PREV = Pattern.compile("prev=(\\d+(-\\d+)?)")
private val PATTERN_NEXT = Pattern.compile("next=(\\d+(-\\d+)?)")
private val FAVORITE_SLOT_RGB = arrayOf(
Triple("0", "0", "0"),
Triple("240", "0", "0"),
Triple("240", "160", "0"),
Triple("208", "208", "0"),
Triple("0", "128", "0"),
Triple("144", "240", "64"),
Triple("64", "176", "240"),
Triple("0", "0", "240"),
Triple("80", "0", "128"),
Triple("224", "128", "224")
)
import androidx.annotation.NonNull;
import com.hippo.ehviewer.EhDB;
import com.hippo.ehviewer.client.EhUtils;
import com.hippo.ehviewer.client.data.BaseGalleryInfo;
import com.hippo.ehviewer.client.data.GalleryInfo;
import com.hippo.ehviewer.client.exception.ParseException;
import com.hippo.util.ExceptionUtils;
import com.hippo.util.JsoupUtils;
import com.hippo.yorozuya.NumberUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GalleryListParser {
private static final String TAG = GalleryListParser.class.getSimpleName();
private static final String NO_UNFILTERED_TEXT = "No unfiltered results in this page range. You either requested an invalid page or used too aggressive filters.";
private static final Pattern PATTERN_RATING = Pattern.compile("\\d+px");
private static final Pattern PATTERN_THUMB_SIZE = Pattern.compile("height:(\\d+)px;width:(\\d+)px");
private static final Pattern PATTERN_FAVORITE_SLOT = Pattern.compile("background-color:rgba\\((\\d+),(\\d+),(\\d+),");
private static final Pattern PATTERN_PAGES = Pattern.compile("(\\d+) page");
private static final Pattern PATTERN_NEXT_PAGE = Pattern.compile("p=(\\d+)");
private static final Pattern PATTERN_PREV = Pattern.compile("prev=(\\d+(-\\d+)?)");
private static final Pattern PATTERN_NEXT = Pattern.compile("next=(\\d+(-\\d+)?)");
private static final String[][] FAVORITE_SLOT_RGB = new String[][]{
new String[]{"0", "0", "0"},
new String[]{"240", "0", "0"},
new String[]{"240", "160", "0"},
new String[]{"208", "208", "0"},
new String[]{"0", "128", "0"},
new String[]{"144", "240", "64"},
new String[]{"64", "176", "240"},
new String[]{"0", "0", "240"},
new String[]{"80", "0", "128"},
new String[]{"224", "128", "224"},
};
private static String parseRating(String ratingStyle) {
Matcher m = PATTERN_RATING.matcher(ratingStyle);
int num1 = Integer.MIN_VALUE;
int num2 = Integer.MIN_VALUE;
int rate = 5;
String re;
private fun parseRating(ratingStyle: String): String? {
val m = PATTERN_RATING.matcher(ratingStyle)
var num1 = Int.MIN_VALUE
var num2 = Int.MIN_VALUE
var rate = 5
if (m.find()) {
num1 = ParserUtils.parseInt(m.group().replace("px", ""), Integer.MIN_VALUE);
num1 = ParserUtils.parseInt(m.group().replace("px", ""), Int.MIN_VALUE)
}
if (m.find()) {
num2 = ParserUtils.parseInt(m.group().replace("px", ""), Integer.MIN_VALUE);
num2 = ParserUtils.parseInt(m.group().replace("px", ""), Int.MIN_VALUE)
}
if (num1 == Integer.MIN_VALUE || num2 == Integer.MIN_VALUE) {
return null;
if (num1 == Int.MIN_VALUE || num2 == Int.MIN_VALUE) {
return null
}
rate = rate - num1 / 16;
if (num2 == 21) {
rate--;
re = Integer.toString(rate);
re = re + ".5";
} else
re = Integer.toString(rate);
return re;
rate -= num1 / 16
return if (num2 == 21) {
"${rate - 1}.5"
} else rate.toString()
}
private static int parseFavoriteSlot(String style) {
Matcher m = PATTERN_FAVORITE_SLOT.matcher(style);
private fun parseFavoriteSlot(style: String): Int {
val m = PATTERN_FAVORITE_SLOT.matcher(style)
if (m.find()) {
String r = m.group(1);
String g = m.group(2);
String b = m.group(3);
int slot = 0;
for (String[] rgb : FAVORITE_SLOT_RGB) {
if (r.equals(rgb[0]) && g.equals(rgb[1]) && b.equals(rgb[2])) {
return slot;
}
slot++;
}
val r = m.group(1)!!
val g = m.group(2)!!
val b = m.group(3)!!
return FAVORITE_SLOT_RGB.indexOf(Triple(r, g, b))
}
return -2;
return -2
}
private static GalleryInfo parseGalleryInfo(Element e) {
GalleryInfo gi = new BaseGalleryInfo();
private fun parseGalleryInfo(e: Element): GalleryInfo? {
val gi: GalleryInfo = BaseGalleryInfo()
// Title, gid, token (required), tags
Element glname = JsoupUtils.getElementByClass(e, "glname");
val glname = JsoupUtils.getElementByClass(e, "glname")
if (glname != null) {
Element a = JsoupUtils.getElementByTag(glname, "a");
var a = JsoupUtils.getElementByTag(glname, "a")
if (a == null) {
Element parent = glname.parent();
if (parent != null && "a".equals(parent.tagName())) {
a = parent;
val parent = glname.parent()
if (parent != null && "a" == parent.tagName()) {
a = parent
}
}
if (a != null) {
GalleryDetailUrlParser.Result result = GalleryDetailUrlParser.parse(a.attr("href"));
val result = GalleryDetailUrlParser.parse(a.attr("href"))
if (result != null) {
gi.setGid(result.gid);
gi.setToken(result.token);
gi.gid = result.gid
gi.token = result.token
}
}
Element child = glname;
Elements children = glname.children();
while (children.size() != 0) {
child = children.get(0);
children = child.children();
var child: Element = glname
var children = glname.children()
while (children.size != 0) {
child = children[0]
children = child.children()
}
gi.setTitle(child.text().trim());
gi.title = child.text().trim { it <= ' ' }
}
if (gi.getTitle() == null) {
return null;
if (gi.title == null) {
return null
}
// Tags
Elements gts = e.select(".gt, .gtl");
if (gts.size() != 0) {
ArrayList<String> tags = new ArrayList<>();
for (Element gt : gts) {
tags.add(gt.attr("title"));
val gts = e.select(".gt, .gtl")
if (gts.size != 0) {
val tags = ArrayList<String>()
for (gt in gts) {
tags.add(gt.attr("title"))
}
gi.setSimpleTags(tags.toArray(new String[0]));
gi.simpleTags = tags.toTypedArray()
}
// Category
gi.setCategory(EhUtils.UNKNOWN);
Element ce = JsoupUtils.getElementByClass(e, "cn");
gi.category = EhUtils.UNKNOWN
var ce = JsoupUtils.getElementByClass(e, "cn")
if (ce == null) {
ce = JsoupUtils.getElementByClass(e, "cs");
ce = JsoupUtils.getElementByClass(e, "cs")
}
if (ce != null) {
gi.setCategory(EhUtils.getCategory(ce.text()));
gi.category = EhUtils.getCategory(ce.text())
}
// Thumb
Element glthumb = JsoupUtils.getElementByClass(e, "glthumb");
val glthumb = JsoupUtils.getElementByClass(e, "glthumb")
if (glthumb != null) {
Element img = glthumb.select("div:nth-child(1)>img").first();
val img = glthumb.select("div:nth-child(1)>img").first()
if (img != null) {
// Thumb size
Matcher m = PATTERN_THUMB_SIZE.matcher(img.attr("style"));
val m = PATTERN_THUMB_SIZE.matcher(img.attr("style"))
if (m.find()) {
gi.setThumbWidth(NumberUtils.parseIntSafely(m.group(2), 0));
gi.setThumbHeight(NumberUtils.parseIntSafely(m.group(1), 0));
gi.thumbWidth = NumberUtils.parseIntSafely(m.group(2), 0)
gi.thumbHeight = NumberUtils.parseIntSafely(m.group(1), 0)
} else {
Log.w(TAG, "Can't parse gallery info thumb size");
gi.setThumbWidth(0);
gi.setThumbHeight(0);
Log.w(TAG, "Can't parse gallery info thumb size")
gi.thumbWidth = 0
gi.thumbHeight = 0
}
// Thumb url
String url = img.attr("data-src");
if (TextUtils.isEmpty(url)) {
url = img.attr("src");
var url = img.attr("data-src")
if (url.isEmpty()) {
url = img.attr("src")
}
if (TextUtils.isEmpty(url)) {
url = null;
if (url.isNotEmpty()) {
gi.thumb = EhUtils.handleThumbUrlResolution(url)
}
gi.setThumb(EhUtils.handleThumbUrlResolution(url));
}
// Pages
Element div = glthumb.select("div:nth-child(2)>div:nth-child(2)>div:nth-child(2)").first();
val div = glthumb.select("div:nth-child(2)>div:nth-child(2)>div:nth-child(2)").first()
if (div != null) {
Matcher matcher = PATTERN_PAGES.matcher(div.text());
val matcher = PATTERN_PAGES.matcher(div.text())
if (matcher.find()) {
gi.setPages(NumberUtils.parseIntSafely(matcher.group(1), 0));
gi.pages = NumberUtils.parseIntSafely(matcher.group(1), 0)
}
}
}
// Try extended and thumbnail version
if (gi.getThumb() == null) {
Element gl = JsoupUtils.getElementByClass(e, "gl1e");
if (gi.thumb == null) {
var gl = JsoupUtils.getElementByClass(e, "gl1e")
if (gl == null) {
gl = JsoupUtils.getElementByClass(e, "gl3t");
gl = JsoupUtils.getElementByClass(e, "gl3t")
}
if (gl != null) {
Element img = JsoupUtils.getElementByTag(gl, "img");
val img = JsoupUtils.getElementByTag(gl, "img")
if (img != null) {
// Thumb size
Matcher m = PATTERN_THUMB_SIZE.matcher(img.attr("style"));
val m = PATTERN_THUMB_SIZE.matcher(img.attr("style"))
if (m.find()) {
gi.setThumbWidth(NumberUtils.parseIntSafely(m.group(2), 0));
gi.setThumbHeight(NumberUtils.parseIntSafely(m.group(1), 0));
gi.thumbWidth = NumberUtils.parseIntSafely(m.group(2), 0)
gi.thumbHeight = NumberUtils.parseIntSafely(m.group(1), 0)
} else {
Log.w(TAG, "Can't parse gallery info thumb size");
gi.setThumbWidth(0);
gi.setThumbHeight(0);
Log.w(TAG, "Can't parse gallery info thumb size")
gi.thumbWidth = 0
gi.thumbHeight = 0
}
gi.setThumb(EhUtils.handleThumbUrlResolution(img.attr("src")));
gi.thumb = EhUtils.handleThumbUrlResolution(img.attr("src"))
}
}
}
// Posted
gi.setFavoriteSlot(-2);
Element posted = e.getElementById("posted_" + gi.getGid());
val posted = e.getElementById("posted_" + gi.gid)
if (posted != null) {
gi.setPosted(posted.text().trim());
gi.setFavoriteSlot(parseFavoriteSlot(posted.attr("style")));
gi.posted = posted.text().trim { it <= ' ' }
gi.favoriteSlot = parseFavoriteSlot(posted.attr("style"))
}
if (gi.getFavoriteSlot() == -2) {
gi.setFavoriteSlot(EhDB.containLocalFavorites(gi.getGid()) ? -1 : -2);
if (gi.favoriteSlot < 0) {
gi.favoriteSlot = if (EhDB.containLocalFavorites(gi.gid)) -1 else -2
}
// Rating
Element ir = JsoupUtils.getElementByClass(e, "ir");
val ir = JsoupUtils.getElementByClass(e, "ir")
if (ir != null) {
gi.setRating(NumberUtils.parseFloatSafely(parseRating(ir.attr("style")), -1.0f));
gi.rating = NumberUtils.parseFloatSafely(parseRating(ir.attr("style")), -1.0f)
// TODO The gallery may be rated even if it doesn't has one of these classes
gi.setRated(ir.hasClass("irr") || ir.hasClass("irg") || ir.hasClass("irb"));
gi.rated = ir.hasClass("irr") || ir.hasClass("irg") || ir.hasClass("irb")
}
// Uploader and pages
Element gl = JsoupUtils.getElementByClass(e, "glhide");
int uploaderIndex = 0;
int pagesIndex = 1;
var gl = JsoupUtils.getElementByClass(e, "glhide")
var uploaderIndex = 0
var pagesIndex = 1
if (gl == null) {
// For extended
gl = JsoupUtils.getElementByClass(e, "gl3e");
uploaderIndex = 3;
pagesIndex = 4;
gl = JsoupUtils.getElementByClass(e, "gl3e")
uploaderIndex = 3
pagesIndex = 4
}
if (gl != null) {
Elements children = gl.children();
if (children.size() > uploaderIndex) {
Element div = children.get(uploaderIndex);
val children = gl.children()
if (children.size > uploaderIndex) {
val div = children[uploaderIndex]
if (div != null) {
gi.setDisowned(div.attr("style").contains("opacity:0.5"));
Element a = div.children().first();
gi.setUploader(a == null ? div.text().trim() : a.text().trim());
gi.disowned = div.attr("style").contains("opacity:0.5")
val a = div.children().first()
gi.uploader = a?.text()?.trim { it <= ' ' } ?: div.text().trim { it <= ' ' }
}
}
if (children.size() > pagesIndex) {
Matcher matcher = PATTERN_PAGES.matcher(children.get(pagesIndex).text());
if (children.size > pagesIndex) {
val matcher = PATTERN_PAGES.matcher(children[pagesIndex].text())
if (matcher.find()) {
gi.setPages(NumberUtils.parseIntSafely(matcher.group(1), 0));
gi.pages = NumberUtils.parseIntSafely(matcher.group(1), 0)
}
}
}
// For thumbnail
Element gl5t = JsoupUtils.getElementByClass(e, "gl5t");
val gl5t = JsoupUtils.getElementByClass(e, "gl5t")
if (gl5t != null) {
Element div = gl5t.select("div:nth-child(2)>div:nth-child(2)").first();
val div = gl5t.select("div:nth-child(2)>div:nth-child(2)").first()
if (div != null) {
Matcher matcher = PATTERN_PAGES.matcher(div.text());
val matcher = PATTERN_PAGES.matcher(div.text())
if (matcher.find()) {
gi.setPages(NumberUtils.parseIntSafely(matcher.group(1), 0));
gi.pages = NumberUtils.parseIntSafely(matcher.group(1), 0)
}
}
}
gi.generateSLang();
return gi;
gi.generateSLang()
return gi
}
public static Result parse(@NonNull String body) throws Exception {
fun parse(body: String): Result {
val d = Jsoup.parse(body)
return parse(d, body)
}
Result result = new Result();
Document d = Jsoup.parse(body);
fun parse(d: Document, body: String): Result {
val result = Result()
try {
Element prev = d.getElementById("uprev");
Element next = d.getElementById("unext");
assert prev != null;
assert next != null;
Matcher matcherPrev = PATTERN_PREV.matcher(prev.attr("href"));
Matcher matcherNext = PATTERN_NEXT.matcher(next.attr("href"));
if (matcherPrev.find())
result.prev = matcherPrev.group(1);
if (matcherNext.find())
result.next = matcherNext.group(1);
} catch (Throwable e) {
ExceptionUtils.throwIfFatal(e);
result.noWatchedTags = body.contains("<p>You do not have any watched tags");
val prev = d.getElementById("uprev")
val next = d.getElementById("unext")
assert(prev != null)
assert(next != null)
val matcherPrev = PATTERN_PREV.matcher(prev!!.attr("href"))
val matcherNext = PATTERN_NEXT.matcher(next!!.attr("href"))
if (matcherPrev.find()) result.prev = matcherPrev.group(1)
if (matcherNext.find()) result.next = matcherNext.group(1)
} catch (e: Throwable) {
ExceptionUtils.throwIfFatal(e)
result.noWatchedTags = body.contains("<p>You do not have any watched tags")
if (body.contains("No hits found</p>")) {
//noinspection unchecked
result.galleryInfoList = Collections.EMPTY_LIST;
return result;
return result
}
}
try { // For toplists
Element ptt = d.getElementsByClass("ptt").first();
val ptt = d.getElementsByClass("ptt").first()
if (ptt != null) {
Elements es = ptt.child(0).child(0).children();
result.pages = Integer.parseInt(es.get(es.size() - 2).text().trim());
Element e = es.get(es.size() - 1);
val es = ptt.child(0).child(0).children()
result.pages = es[es.size - 2].text().trim { it <= ' ' }.toInt()
var e = es[es.size - 1]
if (e != null) {
e = e.children().first();
e = e.children().first()
if (e != null) {
String href = e.attr("href");
Matcher matcher = PATTERN_NEXT_PAGE.matcher(href);
val href = e.attr("href")
val matcher = PATTERN_NEXT_PAGE.matcher(href)
if (matcher.find()) {
result.nextPage = NumberUtils.parseIntSafely(matcher.group(1), 0);
result.nextPage = NumberUtils.parseIntSafely(matcher.group(1), 0)
}
}
}
}
} catch (Throwable e) {
e.printStackTrace();
} catch (e: Throwable) {
e.printStackTrace()
}
try {
Element itg = d.getElementsByClass("itg").first();
Elements es;
if ("table".equalsIgnoreCase(itg.tagName())) {
es = itg.child(0).children();
val itg = d.getElementsByClass("itg").first()
val es = if ("table".equals(itg!!.tagName(), ignoreCase = true)) {
itg.child(0).children()
} else {
es = itg.children();
itg.children()
}
List<GalleryInfo> list = new ArrayList<>(es.size());
val list = result.galleryInfoList
// First one is table header, skip it
for (int i = 0; i < es.size(); i++) {
GalleryInfo gi = parseGalleryInfo(es.get(i));
for (i in es.indices) {
val gi = parseGalleryInfo(es[i])
if (null != gi) {
list.add(gi);
list.add(gi)
}
}
if (list.isEmpty()) {
if (es.size() < 2 || !NO_UNFILTERED_TEXT.equals(es.get(1).text())) {
Log.d(TAG, "No gallery found");
if (es.size < 2 || NO_UNFILTERED_TEXT != es[1].text()) {
Log.d(TAG, "No gallery found")
}
}
result.galleryInfoList = list;
} catch (Throwable e) {
ExceptionUtils.throwIfFatal(e);
e.printStackTrace();
throw new ParseException("Can't parse gallery list", body);
} catch (e: Throwable) {
ExceptionUtils.throwIfFatal(e)
e.printStackTrace()
throw ParseException("Can't parse gallery list", body)
}
return result;
return result
}
public static class Result {
public int pages;
public int nextPage;
public String prev;
public String next;
public boolean noWatchedTags;
public List<GalleryInfo> galleryInfoList;
class Result {
var pages = 0
var nextPage = 0
var prev: String? = null
var next: String? = null
var noWatchedTags = false
val galleryInfoList = mutableListOf<GalleryInfo>()
}
}
}
@@ -16,6 +16,9 @@ interface LocalFavoritesDao : BasicDao<LocalFavoriteInfo> {
@Query("SELECT * FROM LOCAL_FAVORITES WHERE GID = :gid")
fun load(gid: Long): LocalFavoriteInfo?
@Query("SELECT EXISTS(SELECT * FROM LOCAL_FAVORITES WHERE GID = :gid)")
fun contains(gid: Long): Boolean
@Insert
override fun insert(t: LocalFavoriteInfo): Long