From 4c557e29bfd0b8deecbcd9ca62942437081c4e01 Mon Sep 17 00:00:00 2001 From: Maxim Molochkov <48491463+klaseca@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:21:36 +0400 Subject: [PATCH] AllHentai: fix image loading (#5868) --- lib-multisrc/grouple/build.gradle.kts | 2 +- .../tachiyomi/multisrc/grouple/GroupLe.kt | 43 ++++++--- src/ru/allhentai/build.gradle | 2 +- .../extension/ru/allhentai/AllHentai.kt | 87 ++++++++++++++----- 4 files changed, 97 insertions(+), 37 deletions(-) diff --git a/lib-multisrc/grouple/build.gradle.kts b/lib-multisrc/grouple/build.gradle.kts index 1258098ad..f24e51157 100644 --- a/lib-multisrc/grouple/build.gradle.kts +++ b/lib-multisrc/grouple/build.gradle.kts @@ -2,4 +2,4 @@ plugins { id("lib-multisrc") } -baseVersionCode = 24 +baseVersionCode = 25 diff --git a/lib-multisrc/grouple/src/eu/kanade/tachiyomi/multisrc/grouple/GroupLe.kt b/lib-multisrc/grouple/src/eu/kanade/tachiyomi/multisrc/grouple/GroupLe.kt index 59e58913a..c8af3934c 100644 --- a/lib-multisrc/grouple/src/eu/kanade/tachiyomi/multisrc/grouple/GroupLe.kt +++ b/lib-multisrc/grouple/src/eu/kanade/tachiyomi/multisrc/grouple/GroupLe.kt @@ -65,7 +65,8 @@ abstract class GroupLe( } .build() - private var uagent: String = preferences.getString(UAGENT_TITLE, UAGENT_DEFAULT)!! + private var uagent = preferences.getString(UAGENT_TITLE, UAGENT_DEFAULT)!! + override fun headersBuilder() = Headers.Builder().apply { add("User-Agent", uagent) add("Referer", baseUrl) @@ -206,28 +207,44 @@ abstract class GroupLe( } } + protected open fun getChapterSearchParams(document: Document): String { + return "?mtr=true" + } + private fun chapterListParse(response: Response, manga: SManga): List { val document = response.asJsoup() - if ((document.select(".expandable.hide-dn").isNotEmpty() && document.select(".user-avatar").isNullOrEmpty() && document.toString().contains("current_user_country_code = 'RU'")) || (document.select("img.logo").first()?.attr("title")?.contains("Allhentai") == true && document.select(".user-avatar").isNullOrEmpty())) { + if (( + document.select(".expandable.hide-dn").isNotEmpty() && document.select(".user-avatar") + .isEmpty() && document.toString() + .contains("current_user_country_code = 'RU'") + ) || ( + document.select("img.logo") + .first()?.attr("title") + ?.contains("Allhentai") == true && document.select(".user-avatar").isEmpty() + ) + ) { throw Exception("Для просмотра контента необходима авторизация через WebView\uD83C\uDF0E") } - return document.select(chapterListSelector()).map { chapterFromElement(it, manga) } + + val chapterSearchParams = getChapterSearchParams(document) + + return document.select(chapterListSelector()).map { chapterFromElement(it, manga, chapterSearchParams) } } override fun chapterListSelector() = "tr.item-row:has(td > a):has(td.date:not(.text-info))" - private fun chapterFromElement(element: Element, manga: SManga): SChapter { + private fun chapterFromElement(element: Element, manga: SManga, chapterSearchParams: String): SChapter { val urlElement = element.select("a.chapter-link").first()!! val chapterInf = element.select("td.item-title").first()!! val urlText = urlElement.text() val chapter = SChapter.create() - chapter.setUrlWithoutDomain(urlElement.attr("href") + "?mtr=true") // mtr is 18+ fractional skip + chapter.setUrlWithoutDomain(urlElement.attr("href") + chapterSearchParams) val translatorElement = urlElement.attr("title") - chapter.scanlator = if (!translatorElement.isNullOrBlank()) { + chapter.scanlator = if (translatorElement.isNotBlank()) { translatorElement .replace("(Переводчик),", "&") .removeSuffix(" (Переводчик)") @@ -292,15 +309,15 @@ abstract class GroupLe( val html = document.html() - var readerMark = "rm_h.readerDoInit([" - - // allhentai necessary - if (!html.contains(readerMark)) { - readerMark = "rm_h.readerInit( 0,[" - } + val readerMark = "rm_h.readerDoInit([" if (!html.contains(readerMark)) { - if (document.select(".input-lg").isNotEmpty() || (document.select(".user-avatar").isNullOrEmpty() && document.select("img.logo").first()?.attr("title")?.contains("Allhentai") == true)) { + if (document.select(".input-lg").isNotEmpty() || ( + document.select(".user-avatar") + .isEmpty() && document.select("img.logo").first()?.attr("title") + ?.contains("Allhentai") == true + ) + ) { throw Exception("Для просмотра контента необходима авторизация через WebView\uD83C\uDF0E") } if (!response.request.url.toString().contains(baseUrl)) { diff --git a/src/ru/allhentai/build.gradle b/src/ru/allhentai/build.gradle index edb602420..ac7608972 100644 --- a/src/ru/allhentai/build.gradle +++ b/src/ru/allhentai/build.gradle @@ -3,7 +3,7 @@ ext { extClass = '.AllHentai' themePkg = 'grouple' baseUrl = 'https://z.ahen.me' - overrideVersionCode = 23 + overrideVersionCode = 24 isNsfw = true } diff --git a/src/ru/allhentai/src/eu/kanade/tachiyomi/extension/ru/allhentai/AllHentai.kt b/src/ru/allhentai/src/eu/kanade/tachiyomi/extension/ru/allhentai/AllHentai.kt index bfd73028e..3225fcecb 100644 --- a/src/ru/allhentai/src/eu/kanade/tachiyomi/extension/ru/allhentai/AllHentai.kt +++ b/src/ru/allhentai/src/eu/kanade/tachiyomi/extension/ru/allhentai/AllHentai.kt @@ -8,18 +8,27 @@ import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.FilterList import okhttp3.Request +import org.jsoup.nodes.Document import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { + override val id = 1809051393403180443 - override val id: Long = 1809051393403180443 - - private val preferences = - Injekt.get().getSharedPreferences("source_$id", 0x0000) + private val preferences = Injekt.get().getSharedPreferences("source_$id", 0x0000) override val baseUrl by lazy { getPrefBaseUrl() } + override fun getChapterSearchParams(document: Document): String { + val html = document.html() + + val userHashRegex = "user_hash.+'(.+)'".toRegex() + + val userHash = userHashRegex.find(html)?.groupValues?.get(1) + + return userHash?.let { "?d=$it" } ?: "" + } + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { val url = super.searchMangaRequest(page, query, filters).url.newBuilder() (if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> @@ -29,28 +38,47 @@ class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { url.addQueryParameter(genre.id, arrayOf("=", "=in", "=ex")[genre.state]) } } + is Category -> filter.state.forEach { category -> if (category.state != Filter.TriState.STATE_IGNORE) { - url.addQueryParameter(category.id, arrayOf("=", "=in", "=ex")[category.state]) + url.addQueryParameter( + category.id, + arrayOf("=", "=in", "=ex")[category.state], + ) } } - is FilList -> filter.state.forEach { fils -> - if (fils.state != Filter.TriState.STATE_IGNORE) { - url.addQueryParameter(fils.id, arrayOf("=", "=in", "=ex")[fils.state]) + + is FiltersList -> filter.state.forEach { filters -> + if (filters.state != Filter.TriState.STATE_IGNORE) { + url.addQueryParameter(filters.id, arrayOf("=", "=in", "=ex")[filters.state]) } } + is OrderBy -> { if (filter.state > 0) { - val ord = arrayOf("not", "year", "rate", "popularity", "votes", "created", "updated")[filter.state] - return GET("$baseUrl/list?sortType=$ord&offset=${70 * (page - 1)}", headers) + val sortType = arrayOf( + "not", + "year", + "rate", + "popularity", + "votes", + "created", + "updated", + )[filter.state] + return GET( + "$baseUrl/list?sortType=$sortType&offset=${70 * (page - 1)}", + headers, + ) } } + is Tags -> { if (filter.state > 0) { - val tagName = getTagsList()[filter.state].url + val tagName = tagsList[filter.state].url return GET("$baseUrl/list/tag/$tagName?offset=${70 * (page - 1)}", headers) } } + else -> {} } } @@ -63,14 +91,25 @@ class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { private class OrderBy : Filter.Select( "Сортировка (только)", - arrayOf("Без сортировки", "По году", "По популярности", "Популярно сейчас", "По рейтингу", "Новинки", "По дате обновления"), + arrayOf( + "Без сортировки", + "По году", + "По популярности", + "Популярно сейчас", + "По рейтингу", + "Новинки", + "По дате обновления", + ), ) private class Genre(name: String, val id: String) : Filter.TriState(name) private class GenreList(genres: List) : Filter.Group("Жанры", genres) + private class Category(categories: List) : Filter.Group("Категории", categories) - private class FilList(fils: List) : Filter.Group("Фильтры", fils) + + private class FiltersList(filters: List) : Filter.Group("Фильтры", filters) + private class Tags(tags: Array) : Filter.Select("Тэг (только)", tags) private data class Tag(val name: String, val url: String) @@ -78,12 +117,12 @@ class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { override fun getFilterList() = FilterList( OrderBy(), Tags(tagsName), - GenreList(getGenreList()), - Category(getCategoryList()), - FilList(getFilList()), + GenreList(genreList), + Category(categoryList), + FiltersList(filtersList), ) - private fun getGenreList() = listOf( + private val genreList = listOf( Genre("ahegao", "el_855"), Genre("анал", "el_828"), Genre("бдсм", "el_78"), @@ -120,7 +159,7 @@ class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { Genre("яой", "el_83"), ) - private fun getCategoryList() = listOf( + private val categoryList = listOf( Genre("3D", "el_626"), Genre("Анимация", "el_5777"), Genre("Без текста", "el_3157"), @@ -128,7 +167,7 @@ class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { Genre("Порно манхва", "el_1104"), ) - private fun getFilList() = listOf( + private val filtersList = listOf( Genre("Высокий рейтинг", "s_high_rate"), Genre("Сингл", "s_single"), Genre("Для взрослых", "s_mature"), @@ -139,7 +178,7 @@ class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { Genre("Продается", "s_sale"), ) - private fun getTagsList() = listOf( + private val tagsList = listOf( Tag("Без тега", "not"), Tag("handjob", "handjob"), Tag("inseki", "inseki"), @@ -259,7 +298,7 @@ class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { Tag("яндере", "yandere"), ) - private val tagsName = getTagsList().map { + private val tagsName = tagsList.map { it.name }.toTypedArray() @@ -272,7 +311,11 @@ class AllHentai : GroupLe("AllHentai", "https://z.ahen.me", "ru") { dialogTitle = DOMAIN_TITLE dialogMessage = "Default URL:\n\t${super.baseUrl}" setOnPreferenceChangeListener { _, _ -> - Toast.makeText(screen.context, "Для смены домена необходимо перезапустить приложение с полной остановкой.", Toast.LENGTH_LONG).show() + Toast.makeText( + screen.context, + "Для смены домена необходимо перезапустить приложение с полной остановкой.", + Toast.LENGTH_LONG, + ).show() true } }.let(screen::addPreference)