diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/AllHentaiParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/AllHentaiParser.kt index b3936f8e..087cd8f0 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/AllHentaiParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/AllHentaiParser.kt @@ -8,19 +8,14 @@ import org.koitharu.kotatsu.parsers.exception.ParseException import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.util.domain -import org.koitharu.kotatsu.parsers.util.parseFailed -import org.koitharu.kotatsu.parsers.util.parseHtml -import org.koitharu.kotatsu.parsers.util.urlEncoded +import org.koitharu.kotatsu.parsers.util.* @MangaSourceParser("ALLHENTAI", "ALlHentai", "ru") internal class AllHentaiParser( context: MangaLoaderContext, ) : GroupleParser(context, MangaSource.ALLHENTAI, 1) { - override val configKeyDomain = ConfigKey.Domain( - "2023.allhen.online", - ) + override val configKeyDomain = ConfigKey.Domain("2023.allhen.online") override val defaultIsNsfw = true override val authUrl: String @@ -29,6 +24,9 @@ internal class AllHentaiParser( return "https://qawa.org/internal/auth/login?targetUri=$targetUri&siteId=1" } + override val isAuthorized: Boolean + get() = context.cookieJar.getCookies(domain).any { it.name == "trSessionId" } + override suspend fun getPages(chapter: MangaChapter): List { try { return super.getPages(chapter) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/GroupleParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/GroupleParser.kt index 12ab60b0..910a8078 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/GroupleParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/GroupleParser.kt @@ -336,7 +336,8 @@ internal abstract class GroupleParser( val tagsIndex = webClient.httpGet(url).parseHtml() .body().selectFirst("form.search-form") ?.select("div.form-group") - ?.get(1) ?: throw ParseException("Genres filter element not found", url) + ?.find { it.selectFirst("li.property") != null } + ?: throw ParseException("Genres filter element not found", url) val tagNames = tags.map { it.title.lowercase() } val payload = HashMap() var foundGenres = 0 @@ -372,7 +373,7 @@ internal abstract class GroupleParser( response.isSuccessful && response.headersContentLength() >= MIN_IMAGE_SIZE }.getOrDefault(false) - private fun Response.checkAuthRequired(): Response { + protected fun Response.checkAuthRequired(): Response { val lastPathSegment = request.url.pathSegments.lastOrNull() ?: return this if (lastPathSegment == "login") { throw AuthRequiredException(source) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Parse.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Parse.kt index d1aecc44..342b71cf 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Parse.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Parse.kt @@ -76,10 +76,11 @@ fun String.toAbsoluteUrl(domain: String): String = when { fun concatUrl(host: String, path: String): String { val hostWithSlash = host.endsWith('/') val pathWithSlash = path.startsWith('/') + val hostWithScheme = if (host.startsWith("//")) "https:$host" else host return when { - hostWithSlash && pathWithSlash -> host + path.drop(1) - !hostWithSlash && !pathWithSlash -> "$host/$path" - else -> host + path + hostWithSlash && pathWithSlash -> hostWithScheme + path.drop(1) + !hostWithSlash && !pathWithSlash -> "$hostWithScheme/$path" + else -> hostWithScheme + path } } diff --git a/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaParserTest.kt b/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaParserTest.kt index f61eb77a..19e132ab 100644 --- a/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaParserTest.kt +++ b/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaParserTest.kt @@ -79,7 +79,7 @@ internal class MangaParserTest { assert(keys.isDistinct()) assert("" !in keys) val titles = tags.map { it.title } -// assert(titles.isDistinct()) + assert(titles.isDistinct()) assert("" !in titles) assert(tags.all { it.source == source }) @@ -89,6 +89,25 @@ internal class MangaParserTest { assert(list.all { it.source == source }) } + @ParameterizedTest(name = "{index}|tags_multiple|{0}") + @MangaSources + fun tagsMultiple(source: MangaSource) = runTest { + val parser = source.newParser(context) + val tags = parser.getTags().shuffled().take(2).toSet() + + val list = try { + parser.getList(offset = 0, tags = tags, sortOrder = null) + } catch (e: IllegalArgumentException) { + if (e.message == "Multiple genres are not supported by this source") { + return@runTest + } else { + throw e + } + } + checkMangaList(list, "${tags.joinToString { it.title }} (${tags.joinToString { it.key }})") + assert(list.all { it.source == source }) + } + @ParameterizedTest(name = "{index}|details|{0}") @MangaSources fun details(source: MangaSource) = runTest { @@ -163,10 +182,7 @@ internal class MangaParserTest { fun domain(source: MangaSource) = runTest { val parser = source.newParser(context) val defaultDomain = parser.domain - val url = HttpUrl.Builder() - .host(defaultDomain) - .scheme("https") - .toString() + val url = HttpUrl.Builder().host(defaultDomain).scheme("https").toString() val response = context.doRequest(url, source) val realUrl = response.request.url val realDomain = realUrl.topPrivateDomain()