From eae235fa10541f1368534db11658c7d696c39697 Mon Sep 17 00:00:00 2001 From: Dark25 Date: Fri, 18 Oct 2024 22:08:48 +0200 Subject: [PATCH] fix(pt/Anitube): Update extension (#111) --- src/pt/anitube/build.gradle | 2 +- .../animeextension/pt/anitube/Anitube.kt | 182 +++++++------- .../extractors/AnitubeDownloadExtractor.kt | 113 +++++++++ .../pt/anitube/extractors/AnitubeExtractor.kt | 232 +++++++++++++++++- 4 files changed, 435 insertions(+), 94 deletions(-) create mode 100644 src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeDownloadExtractor.kt diff --git a/src/pt/anitube/build.gradle b/src/pt/anitube/build.gradle index a70e106166..a468f926da 100644 --- a/src/pt/anitube/build.gradle +++ b/src/pt/anitube/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Anitube' extClass = '.Anitube' - extVersionCode = 18 + extVersionCode = 19 } apply from: "$rootDir/common.gradle" diff --git a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt index 4746bcf797..4f5f8ae6ac 100644 --- a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt +++ b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt @@ -1,31 +1,29 @@ package eu.kanade.tachiyomi.animeextension.pt.anitube import android.app.Application +import androidx.preference.EditTextPreference import androidx.preference.ListPreference import androidx.preference.PreferenceScreen +import androidx.preference.SwitchPreferenceCompat +import eu.kanade.tachiyomi.animeextension.pt.anitube.extractors.AnitubeDownloadExtractor import eu.kanade.tachiyomi.animeextension.pt.anitube.extractors.AnitubeExtractor import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.model.AnimeFilterList +import eu.kanade.tachiyomi.animesource.model.AnimesPage import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.POST +import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.util.asJsoup -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.decodeFromStream -import okhttp3.FormBody -import okhttp3.Headers -import okhttp3.HttpUrl.Companion.toHttpUrl -import okhttp3.OkHttpClient +import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking import okhttp3.Request import okhttp3.Response import org.jsoup.nodes.Document import org.jsoup.nodes.Element import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -import uy.kohesive.injekt.injectLazy import java.text.SimpleDateFormat import java.util.Locale @@ -43,10 +41,8 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { Injekt.get().getSharedPreferences("source_$id", 0x0000) } - private val json: Json by injectLazy() - override fun headersBuilder() = super.headersBuilder() - .add("Referer", baseUrl) + .add("Referer", "$baseUrl/") .add("Accept-Language", ACCEPT_LANGUAGE) // ============================== Popular =============================== @@ -86,6 +82,30 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { override fun latestUpdatesNextPageSelector() = popularAnimeNextPageSelector() // =============================== Search =============================== + override suspend fun getSearchAnime( + page: Int, + query: String, + filters: AnimeFilterList, + ): AnimesPage { + return if (query.startsWith(PREFIX_SEARCH)) { + val path = query.removePrefix(PREFIX_SEARCH) + client.newCall(GET("$baseUrl/$path")) + .awaitSuccess() + .use(::searchAnimeByIdParse) + } else { + super.getSearchAnime(page, query, filters) + } + } + + private fun searchAnimeByIdParse(response: Response): AnimesPage { + val details = animeDetailsParse(response).apply { + setUrlWithoutDomain(response.request.url.toString()) + initialized = true + } + + return AnimesPage(listOf(details), false) + } + override fun getFilterList(): AnimeFilterList = AnitubeFilters.FILTER_LIST override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { @@ -97,7 +117,14 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { val char = params.initialChar when { season.isNotBlank() -> "$baseUrl/temporada/$season/$year" - genre.isNotBlank() -> "$baseUrl/genero/$genre/page/$page/${char.replace("todos", "")}" + genre.isNotBlank() -> + "$baseUrl/genero/$genre/page/$page/${ + char.replace( + "todos", + "", + ) + }" + else -> "$baseUrl/anime/page/$page/letra/$char" } } else { @@ -119,7 +146,7 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { val infos = content.selectFirst("div.anime_infos")!! title = doc.selectFirst("div.anime_container_titulo")!!.text() - thumbnail_url = content.selectFirst("img")?.imgAttr() + thumbnail_url = content.selectFirst("img")?.attr("src") genre = infos.getInfo("Gêneros") author = infos.getInfo("Autor") artist = infos.getInfo("Estúdio") @@ -135,14 +162,6 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { } } - fun Element.imgAttr(): String = when { - hasAttr("data-cfsrc") -> absUrl("data-cfsrc") - hasAttr("data-lazy-src") -> absUrl("data-lazy-src") - hasAttr("data-src") -> absUrl("data-src").substringBefore(" ") - hasAttr("srcset") -> absUrl("srcset").substringBefore(" ") - else -> absUrl("src") - } - // ============================== Episodes ============================== override fun episodeListSelector() = "div.animepag_episodios_item > a" @@ -163,79 +182,39 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { override fun episodeFromElement(element: Element) = SEpisode.create().apply { setUrlWithoutDomain(element.attr("href")) episode_number = element.selectFirst("div.animepag_episodios_item_views")!! - .text().trim() + .text() .substringAfter(" ") .toFloatOrNull() ?: 0F - name = element.selectFirst("div[class*='animepag_episodios_item_views']")!!.text() + name = element.selectFirst("div.animepag_episodios_item_nome")!!.text() date_upload = element.selectFirst("div.animepag_episodios_item_date")!! .text() .toDate() } // ============================ Video Links ============================= - override fun videoListParse(response: Response) = AnitubeExtractor.getVideoList(response, headers).let { - val auth = getToken() - - it.map { video -> - Video( - url = video.url, - quality = video.quality, - videoUrl = "${video.videoUrl}${auth.value}", - headers = video.headers, - subtitleTracks = video.subtitleTracks, - audioTracks = video.audioTracks, - ) - } - } - - private fun getToken(): AnitubeToken { - val headers = Headers.Builder() - .set("Accept", "*/*") - .set("Accept-Encoding", "br, zstd") - .set("Accept-Language", "pt-BR,en-US;q=0.7,en;q=0.3") - .set("Cache-Control", "no-cache") - .set("Connection", "keep-alive") - .set("Pragma", "no-cache") - .set("Referer", "$baseUrl/") - .set("Sec-Fetch-Dest", "empty") - .set("Sec-Fetch-Mode", "cors") - .set("Sec-Fetch-Site", "same-site") - .apply { - headers["User-Agent"]?.let { - set("User-Agent", it) - } - } - .build() + private val anitubeExtractor by lazy { AnitubeExtractor(headers, client, preferences) } + private val downloadExtractor by lazy { AnitubeDownloadExtractor(headers, client) } - val client = OkHttpClient() + override fun videoListParse(response: Response): List