diff --git a/lib-multisrc/gattsu/build.gradle.kts b/lib-multisrc/gattsu/build.gradle.kts index 02080b6c0f4..9f0283a0c5d 100644 --- a/lib-multisrc/gattsu/build.gradle.kts +++ b/lib-multisrc/gattsu/build.gradle.kts @@ -3,6 +3,6 @@ plugins { } keiyoushi { - baseVersionCode = 6 - libVersion = "1.4" + baseVersionCode = 0 + libVersion = "1.6" } diff --git a/lib-multisrc/gattsu/src/eu/kanade/tachiyomi/multisrc/gattsu/Gattsu.kt b/lib-multisrc/gattsu/src/eu/kanade/tachiyomi/multisrc/gattsu/Gattsu.kt index 74c761cf701..ec6b67931d9 100644 --- a/lib-multisrc/gattsu/src/eu/kanade/tachiyomi/multisrc/gattsu/Gattsu.kt +++ b/lib-multisrc/gattsu/src/eu/kanade/tachiyomi/multisrc/gattsu/Gattsu.kt @@ -2,44 +2,38 @@ package eu.kanade.tachiyomi.multisrc.gattsu -import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.source.model.SMangaUpdate +import keiyoushi.network.get +import keiyoushi.source.KeiSource import keiyoushi.utils.asJsoup -import keiyoushi.utils.tryParse +import keiyoushi.utils.tryParseDate import okhttp3.Headers +import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Request -import okhttp3.Response +import org.jsoup.nodes.Document import org.jsoup.nodes.Element -import java.text.SimpleDateFormat +import java.time.format.DateTimeFormatter import java.util.Locale -abstract class Gattsu : HttpSource() { +abstract class Gattsu : KeiSource() { - override val supportsLatest = true + override fun Headers.Builder.configureHeaders(): Headers.Builder = set("Accept", ACCEPT) + .set("Accept-Language", ACCEPT_LANGUAGE) - override fun headersBuilder() = Headers.Builder() - .add("Accept", ACCEPT) - .add("Accept-Language", ACCEPT_LANGUAGE) - .add("Referer", baseUrl) + // Website does not have a popular, so the latest listing is used instead. + override val supportsLatest = false - // Website does not have a popular, so use latest instead. - override fun popularMangaRequest(page: Int): Request = latestUpdatesRequest(page) + override suspend fun getLatestUpdates(page: Int): MangasPage = throw UnsupportedOperationException() - override fun popularMangaParse(response: Response): MangasPage = latestUpdatesParse(response) - - override fun latestUpdatesRequest(page: Int): Request { + override suspend fun getPopularManga(page: Int): MangasPage { val path = if (page == 1) "" else "page/$page" - return GET("$baseUrl/$path", headers) - } - - override fun latestUpdatesParse(response: Response): MangasPage { - val document = response.asJsoup() + val document = client.get("$baseUrl/$path").asJsoup() val mangas = document.select(latestUpdatesSelector()).map { element -> latestUpdatesFromElement(element) } @@ -60,17 +54,13 @@ abstract class Gattsu : HttpSource() { open fun latestUpdatesNextPageSelector(): String? = "ul.paginacao li.next > a" - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + override suspend fun getSearchMangaList(page: Int, query: String, filters: FilterList): MangasPage { val searchUrl = "$baseUrl/page/$page/".toHttpUrl().newBuilder() .addQueryParameter("s", query) .addQueryParameter("post_type", "post") - .toString() - - return GET(searchUrl, headers) - } + .build() - override fun searchMangaParse(response: Response): MangasPage { - val document = response.asJsoup() + val document = client.get(searchUrl).asJsoup() val mangas = document.select(searchMangaSelector()).map { element -> searchMangaFromElement(element) } @@ -87,8 +77,24 @@ abstract class Gattsu : HttpSource() { open fun searchMangaNextPageSelector(): String? = latestUpdatesNextPageSelector() - override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply { - val document = response.asJsoup() + override suspend fun getMangaByUrl(url: HttpUrl): SManga? { + if (url.host != baseUrl.toHttpUrl().host || url.pathSegments.all(String::isEmpty)) return null + + return mangaDetailsParse(client.get(url).asJsoup()).apply { setUrlWithoutDomain(url.toString()) } + } + + // Details and chapters come from the same page + override suspend fun fetchMangaUpdate( + manga: SManga, + chapters: List, + fetchDetails: Boolean, + fetchChapters: Boolean, + ): SMangaUpdate { + val document = client.get(getMangaUrl(manga)).asJsoup() + return SMangaUpdate(mangaDetailsParse(document), chapterListParse(document)) + } + + open fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { val postBox = document.select("div.meio div.post-box").first()!! title = postBox.select("h1.post-titulo").first()!!.text() @@ -105,9 +111,7 @@ abstract class Gattsu : HttpSource() { .withoutSize() } - override fun chapterListParse(response: Response): List { - val document = response.asJsoup() - + open fun chapterListParse(document: Document): List { if (document.selectFirst(pageListSelector()) == null) { return emptyList() } @@ -116,7 +120,7 @@ abstract class Gattsu : HttpSource() { .map { chapterFromElement(it) } } - open fun chapterListSelector() = "div.meio div.post-box:first-of-type" + open fun chapterListSelector() = "div.meio div.post-box:has(h1.post-titulo)" open fun chapterFromElement(element: Element): SChapter = SChapter.create().apply { name = "CapĂ­tulo Ășnico" @@ -131,24 +135,18 @@ abstract class Gattsu : HttpSource() { protected open fun pageListSelector(): String = "div.meio div.post-box ul.post-fotos li a > img, " + "div.meio div.post-box.listaImagens div.galeriaHtml img" - override fun pageListParse(response: Response): List { - val document = response.asJsoup() + override suspend fun getPageList(chapter: SChapter): List { + val document = client.get(getChapterUrl(chapter)).asJsoup() return document.select(pageListSelector()) .mapIndexed { i, el -> Page(i, document.location(), imageUrl = el.imgAttr().withoutSize()) } } - override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException() - - override fun imageRequest(page: Page): Request { - val imageHeaders = headersBuilder() - .add("Accept", ACCEPT_IMAGE) - .add("Referer", page.url) - .build() - - return GET(page.imageUrl!!, imageHeaders) - } + override fun imageRequest(page: Page): Request = super.imageRequest(page).newBuilder() + .header("Accept", ACCEPT_IMAGE) + .header("Referer", page.url) + .build() protected fun Element.imgAttr(): String = if (hasAttr("data-src")) { attr("abs:data-src") @@ -156,7 +154,7 @@ abstract class Gattsu : HttpSource() { attr("abs:src") } - protected fun String.toDate(): Long = DATE_FORMATTER.tryParse(this.substringBefore("T")) + protected fun String.toDate(): Long = DATE_FORMATTER.tryParseDate(this.substringBefore("T")) protected fun String.withoutSize(): String = this.replace(THUMB_SIZE_REGEX, ".") @@ -168,8 +166,6 @@ abstract class Gattsu : HttpSource() { private val THUMB_SIZE_REGEX = "-\\d+x\\d+\\.".toRegex() - private val DATE_FORMATTER by lazy { - SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) - } + private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.ENGLISH) } } diff --git a/src/pt/hentaiseason/build.gradle.kts b/src/pt/hentaiseason/build.gradle.kts index 3ee0ae88548..8dde603da47 100644 --- a/src/pt/hentaiseason/build.gradle.kts +++ b/src/pt/hentaiseason/build.gradle.kts @@ -6,9 +6,9 @@ plugins { keiyoushi { name = "Hentai Season" - versionCode = 1 + versionCode = 0 contentWarning = ContentWarning.NSFW - libVersion = "1.4" + libVersion = "1.6" theme = "gattsu" source { diff --git a/src/pt/hentaiseason/src/eu/kanade/tachiyomi/extension/pt/hentaiseason/HentaiSeason.kt b/src/pt/hentaiseason/src/eu/kanade/tachiyomi/extension/pt/hentaiseason/HentaiSeason.kt index f6e8c9e6877..851d94ac5e2 100644 --- a/src/pt/hentaiseason/src/eu/kanade/tachiyomi/extension/pt/hentaiseason/HentaiSeason.kt +++ b/src/pt/hentaiseason/src/eu/kanade/tachiyomi/extension/pt/hentaiseason/HentaiSeason.kt @@ -9,7 +9,5 @@ import kotlin.time.Duration.Companion.seconds @Source abstract class HentaiSeason : Gattsu() { - override val client: OkHttpClient = super.client.newBuilder() - .rateLimit(1, 2.seconds) - .build() + override fun OkHttpClient.Builder.configureClient(): OkHttpClient.Builder = rateLimit(1, 2.seconds) } diff --git a/src/pt/hentaitokyo/build.gradle.kts b/src/pt/hentaitokyo/build.gradle.kts index f1ec407de3a..4eec5ba090f 100644 --- a/src/pt/hentaitokyo/build.gradle.kts +++ b/src/pt/hentaitokyo/build.gradle.kts @@ -6,9 +6,9 @@ plugins { keiyoushi { name = "Hentai Tokyo" - versionCode = 1 + versionCode = 0 contentWarning = ContentWarning.NSFW - libVersion = "1.4" + libVersion = "1.6" theme = "gattsu" source { diff --git a/src/pt/hentaitokyo/src/eu/kanade/tachiyomi/extension/pt/hentaitokyo/HentaiTokyo.kt b/src/pt/hentaitokyo/src/eu/kanade/tachiyomi/extension/pt/hentaitokyo/HentaiTokyo.kt index 420bff3dd6d..096038c6c53 100644 --- a/src/pt/hentaitokyo/src/eu/kanade/tachiyomi/extension/pt/hentaitokyo/HentaiTokyo.kt +++ b/src/pt/hentaitokyo/src/eu/kanade/tachiyomi/extension/pt/hentaitokyo/HentaiTokyo.kt @@ -9,7 +9,5 @@ import kotlin.time.Duration.Companion.seconds @Source abstract class HentaiTokyo : Gattsu() { - override val client: OkHttpClient = super.client.newBuilder() - .rateLimit(1, 2.seconds) - .build() + override fun OkHttpClient.Builder.configureClient(): OkHttpClient.Builder = rateLimit(1, 2.seconds) } diff --git a/src/pt/universohentai/build.gradle.kts b/src/pt/universohentai/build.gradle.kts index 6c563966358..46b209844da 100644 --- a/src/pt/universohentai/build.gradle.kts +++ b/src/pt/universohentai/build.gradle.kts @@ -6,9 +6,9 @@ plugins { keiyoushi { name = "Universo Hentai" - versionCode = 1 + versionCode = 0 contentWarning = ContentWarning.NSFW - libVersion = "1.4" + libVersion = "1.6" theme = "gattsu" source { diff --git a/src/pt/universohentai/src/eu/kanade/tachiyomi/extension/pt/universohentai/UniversoHentai.kt b/src/pt/universohentai/src/eu/kanade/tachiyomi/extension/pt/universohentai/UniversoHentai.kt index 7582f7e215c..1cad2d8b0c4 100644 --- a/src/pt/universohentai/src/eu/kanade/tachiyomi/extension/pt/universohentai/UniversoHentai.kt +++ b/src/pt/universohentai/src/eu/kanade/tachiyomi/extension/pt/universohentai/UniversoHentai.kt @@ -5,18 +5,15 @@ import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import keiyoushi.annotation.Source import keiyoushi.network.rateLimit -import keiyoushi.utils.asJsoup import okhttp3.OkHttpClient -import okhttp3.Response +import org.jsoup.nodes.Document import org.jsoup.nodes.Element import kotlin.time.Duration.Companion.seconds @Source abstract class UniversoHentai : Gattsu() { - override val client: OkHttpClient = super.client.newBuilder() - .rateLimit(1, 2.seconds) - .build() + override fun OkHttpClient.Builder.configureClient(): OkHttpClient.Builder = rateLimit(1, 2.seconds) override fun latestUpdatesSelector() = "div.meio div.videos div.video a[href^=$baseUrl]:not(:has(span.selo-hd))" @@ -26,8 +23,7 @@ abstract class UniversoHentai : Gattsu() { setUrlWithoutDomain(element.attr("href")) } - override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply { - val document = response.asJsoup() + override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { val postBox = document.selectFirst(chapterListSelector())!! title = postBox.select("h1.post-titulo").first()!!.text() @@ -40,12 +36,8 @@ abstract class UniversoHentai : Gattsu() { .withoutSize() } - override fun chapterListParse(response: Response): List { - val document = response.asJsoup() - - return document.select(chapterListSelector()) - .map { chapterFromElement(it) } - } + override fun chapterListParse(document: Document): List = document.select(chapterListSelector()) + .map { chapterFromElement(it) } override fun chapterListSelector() = "div.meio div.post[itemscope]:has(a[title=Abrir galeria])"