diff --git a/.idea/runConfigurations/TestsAndReport.xml b/.idea/runConfigurations/TestsAndReport.xml new file mode 100644 index 000000000..614cfdf37 --- /dev/null +++ b/.idea/runConfigurations/TestsAndReport.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaParser.kt index 0ee27c34d..eb04d3dd3 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaParser.kt @@ -1,6 +1,8 @@ package org.koitharu.kotatsu.parsers import androidx.annotation.CallSuper +import androidx.annotation.VisibleForTesting +import okhttp3.Headers import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.exception.ParseException import org.koitharu.kotatsu.parsers.model.* @@ -31,6 +33,9 @@ abstract class MangaParser @InternalParsersApi constructor(val source: MangaSour */ protected abstract val configKeyDomain: ConfigKey.Domain + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) + internal open val headers: Headers? = null + /** * Used as fallback if value of `sortOrder` passed to [getList] is null */ @@ -113,7 +118,7 @@ abstract class MangaParser @InternalParsersApi constructor(val source: MangaSour open fun getFaviconUrl() = "https://${getDomain()}/favicon.ico" open suspend fun parseFavicons(): Favicons { - return FaviconParser(context, getDomain()).parseFavicons() + return FaviconParser(context, getDomain(), headers).parseFavicons() } @CallSuper diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/NineMangaParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/NineMangaParser.kt index 20c88be1b..26eee91bd 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/NineMangaParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/NineMangaParser.kt @@ -26,7 +26,7 @@ internal abstract class NineMangaParser( context.cookieJar.insertCookies(getDomain(), "ninemanga_template_desk=yes") } - private val headers = Headers.Builder() + override val headers = Headers.Builder() .add("Accept-Language", "en-US;q=0.7,en;q=0.3") .build() @@ -171,10 +171,6 @@ internal abstract class NineMangaParser( } ?: parseFailed("Root not found") } - override suspend fun parseFavicons(): Favicons { - return FaviconParser(context, getDomain()).addHeaders(headers).parseFavicons() - } - private fun parseStatus(status: String) = when { status.contains("Ongoing") -> MangaState.ONGOING status.contains("Completed") -> MangaState.FINISHED 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 073b68bfd..f7425c1d1 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 @@ -24,7 +24,7 @@ internal abstract class GroupleParser( private val siteId: Int, ) : MangaParser(source), MangaParserAuthProvider { - private val headers = Headers.Builder() + override val headers = Headers.Builder() .add("User-Agent", userAgent) .build() diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/FaviconParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/FaviconParser.kt index b7767a33f..fec7f706a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/FaviconParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/FaviconParser.kt @@ -7,18 +7,15 @@ import org.koitharu.kotatsu.parsers.model.Favicon import org.koitharu.kotatsu.parsers.model.Favicons import org.koitharu.kotatsu.parsers.util.json.mapJSON -class FaviconParser(private val context: MangaLoaderContext, private val domain: String) { - - private val headers = Headers.Builder() - - fun addHeaders(headers: Headers): FaviconParser { - this.headers.addAll(headers) - return this - } +class FaviconParser( + private val context: MangaLoaderContext, + private val domain: String, + private val headers: Headers?, +) { suspend fun parseFavicons(): Favicons { val url = "https://$domain" - val doc = context.httpGet(url, headers.build()).parseHtml() + val doc = context.httpGet(url, headers).parseHtml() val result = HashSet() val manifestLink = doc.getElementsByAttributeValue("rel", "manifest").firstOrNull() ?.attrAsAbsoluteUrlOrNull("href") @@ -59,7 +56,7 @@ class FaviconParser(private val context: MangaLoaderContext, private val domain: } private suspend fun parseManifest(url: String): List { - val json = context.httpGet(url, headers.build()).parseJson() + val json = context.httpGet(url, headers).parseJson() val icons = json.getJSONArray("icons") return icons.mapJSON { jo -> Favicon( diff --git a/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaLoaderContextMock.kt b/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaLoaderContextMock.kt index 60357aa43..95ebb59c3 100644 --- a/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaLoaderContextMock.kt +++ b/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaLoaderContextMock.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.parsers import com.koushikdutta.quack.QuackContext +import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response @@ -45,10 +46,13 @@ internal class MangaLoaderContextMock : MangaLoaderContext() { return SourceConfigMock() } - suspend fun doRequest(url: String, referer: String? = null): Response { + suspend fun doRequest(url: String, referer: String? = null, extraHeaders: Headers? = null): Response { val request = Request.Builder() .get() .url(url) + if (extraHeaders != null) { + request.headers(extraHeaders) + } if (referer != null) { request.header("Referer", referer) } diff --git a/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaParserTest.kt b/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaParserTest.kt index d02d3d6f9..4055cd8e0 100644 --- a/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaParserTest.kt +++ b/src/test/kotlin/org/koitharu/kotatsu/parsers/MangaParserTest.kt @@ -141,7 +141,7 @@ internal class MangaParserTest { .host(defaultDomain) .scheme("https") .toString() - val response = context.doRequest(url) + val response = context.doRequest(url, extraHeaders = parser.headers) val realUrl = response.request.url val realDomain = realUrl.topPrivateDomain() val realHost = realUrl.host