From 11c9369ba097d2d95985b8dc0649e932cc4b6435 Mon Sep 17 00:00:00 2001 From: Claudemirovsky <63046606+Claudemirovsky@users.noreply.github.com> Date: Fri, 22 Sep 2023 05:19:04 -0300 Subject: [PATCH] fix(de/animebase): Some fixes + refactoration (#2236) --- src/de/animebase/build.gradle | 16 +- .../animeextension/de/animebase/AnimeBase.kt | 333 ++++++++++-------- .../de/animebase/CookieInterceptor.kt | 103 ------ .../animebase/extractors/UnpackerExtractor.kt | 31 ++ 4 files changed, 237 insertions(+), 246 deletions(-) delete mode 100644 src/de/animebase/src/eu/kanade/tachiyomi/animeextension/de/animebase/CookieInterceptor.kt create mode 100644 src/de/animebase/src/eu/kanade/tachiyomi/animeextension/de/animebase/extractors/UnpackerExtractor.kt diff --git a/src/de/animebase/build.gradle b/src/de/animebase/build.gradle index c931cda2af..f6973bb477 100644 --- a/src/de/animebase/build.gradle +++ b/src/de/animebase/build.gradle @@ -1,13 +1,21 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlinx-serialization' +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) +} ext { extName = 'Anime-Base' pkgNameSuffix = 'de.animebase' extClass = '.AnimeBase' - extVersionCode = 13 + extVersionCode = 14 libVersion = '13' } +dependencies { + implementation(project(":lib-voe-extractor")) + implementation(project(":lib-streamwish-extractor")) + implementation(project(":lib-playlist-utils")) + implementation("dev.datlag.jsunpacker:jsunpacker:1.0.1") +} + apply from: "$rootDir/common.gradle" diff --git a/src/de/animebase/src/eu/kanade/tachiyomi/animeextension/de/animebase/AnimeBase.kt b/src/de/animebase/src/eu/kanade/tachiyomi/animeextension/de/animebase/AnimeBase.kt index dc7c2fbeb5..1ad53bb73d 100644 --- a/src/de/animebase/src/eu/kanade/tachiyomi/animeextension/de/animebase/AnimeBase.kt +++ b/src/de/animebase/src/eu/kanade/tachiyomi/animeextension/de/animebase/AnimeBase.kt @@ -1,22 +1,27 @@ package eu.kanade.tachiyomi.animeextension.de.animebase import android.app.Application -import android.content.SharedPreferences import androidx.preference.ListPreference import androidx.preference.PreferenceScreen +import eu.kanade.tachiyomi.animeextension.de.animebase.extractors.UnpackerExtractor import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.model.AnimeFilterList 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.lib.streamwishextractor.StreamWishExtractor +import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.util.asJsoup -import okhttp3.MediaType.Companion.toMediaType +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.runBlocking +import okhttp3.FormBody import okhttp3.OkHttpClient import okhttp3.Request -import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.Response import org.jsoup.nodes.Document import org.jsoup.nodes.Element @@ -31,182 +36,213 @@ class AnimeBase : ConfigurableAnimeSource, ParsedAnimeHttpSource() { override val lang = "de" - override val supportsLatest = false + override val supportsLatest = true override val client: OkHttpClient = network.cloudflareClient - private val preferences: SharedPreferences by lazy { + private val preferences by lazy { Injekt.get().getSharedPreferences("source_$id", 0x0000) } - override fun popularAnimeSelector(): String = "div.table-responsive a" + // ============================== Popular =============================== + override fun popularAnimeRequest(page: Int) = GET("$baseUrl/favorites", headers) - override fun popularAnimeRequest(page: Int): Request { - val cookieInterceptor = client.newBuilder().addInterceptor(CookieInterceptor(baseUrl)).build() - val headers = cookieInterceptor.newCall(GET(baseUrl)).execute().request.headers - return GET("$baseUrl/favorites", headers = headers) - } + override fun popularAnimeSelector() = "div.table-responsive > a" - override fun popularAnimeFromElement(element: Element): SAnime { - val anime = SAnime.create() - anime.setUrlWithoutDomain(element.attr("href")) - anime.thumbnail_url = element.select("div.thumbnail img").attr("src") - anime.title = element.select("div.thumbnail div.caption h3").text() - return anime + override fun popularAnimeFromElement(element: Element) = SAnime.create().apply { + setUrlWithoutDomain(element.attr("href").replace("/link/", "/anime/")) + thumbnail_url = element.selectFirst("div.thumbnail img")?.absUrl("src") + title = element.selectFirst("div.caption h3")!!.text() } - override fun popularAnimeNextPageSelector(): String? = null + override fun popularAnimeNextPageSelector() = null - // episodes + // =============================== Latest =============================== + override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/updates", headers) - override fun episodeListSelector() = throw Exception("not used") + override fun latestUpdatesSelector() = "div.box-header + div.box-body > a" - override fun episodeListParse(response: Response): List { - val document = response.asJsoup() - val episodeList = mutableListOf() - val episodeElement = document.select( - "div.tab-content #gersub div.panel, div.tab-content #filme div.panel button[${ - if (document.select("div.tab-content #filme div.panel button[data-dubbed=\"0\"]").isNullOrEmpty()) { - "data-dubbed=\"1\"" - } else { - "data-dubbed=\"0\"" - } - }][data-hoster=\"1\"], div.tab-content #specials div.panel button[data-dubbed=\"0\"][data-hoster=\"1\"]", - ) - episodeElement.forEach { - val episode = episodeFromElement(it) - episodeList.add(episode) - } - return episodeList.reversed() + override fun latestUpdatesFromElement(element: Element) = popularAnimeFromElement(element) + + override fun latestUpdatesNextPageSelector() = null + + // =============================== Search =============================== + private val searchToken by lazy { + client.newCall(GET("$baseUrl/searching", headers)).execute() + .use { it.asJsoup() } + .selectFirst("form > input[name=_token]")!! + .attr("value") } - override fun episodeFromElement(element: Element): SEpisode { - val episode = SEpisode.create() - val id = element.select("button[data-hoster=\"1\"]").attr("data-serieid") - val epnum = element.select("button[data-hoster=\"1\"]").attr("data-folge") - val host = element.select("button[data-hoster=\"1\"]").attr("data-hoster") - if (element.attr("data-dubbed").contains("1")) { - if (element.attr("data-special").contains("2")) { - episode.episode_number = 1F - episode.name = "Film $epnum" - episode.setUrlWithoutDomain("/episode/$id/$epnum/1/$host/2") - } - } else { - if (element.select("button[data-hoster=\"1\"]").attr("data-special").contains("2")) { - episode.episode_number = 1F - episode.name = "Film ${epnum.toInt() - 1}" - episode.setUrlWithoutDomain("/episode/$id/$epnum/0/$host/2") - } else { - val season = element.select("button[data-hoster=\"1\"]").attr("data-embedcontainer") - .substringAfter("-").substringBefore("-") - episode.name = "Staffel $season Folge $epnum : " + element.select("h3.panel-title").text() - .substringAfter(": ") - .replace("Filler!", "").replace(" ", "") - episode.episode_number = element.select("button[data-hoster=\"1\"]").attr("data-folge").toFloat() - episode.setUrlWithoutDomain("/episode/$id/$epnum/0/$host/0") - } - if (element.select("button[data-hoster=\"1\"]").attr("data-special").contains("1")) { - episode.episode_number = 1F - episode.name = "Special ${epnum.toInt() - 1}" - episode.setUrlWithoutDomain("/episode/$id/$epnum/0/$host/1") - } - } - return episode + override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { + val body = FormBody.Builder() + .add("_token", searchToken) + .add("_token", searchToken) + .add("name_serie", query) + .add("jahr", "") + .build() + return POST("$baseUrl/searching", headers, body) } - // Video Extractor + override fun searchAnimeSelector(): String = "div.col-lg-9.col-md-8 div.box-body a" - override fun videoListParse(response: Response) = - throw Exception("This source only uses StreamSB as video hoster, and StreamSB is down.") + override fun searchAnimeFromElement(element: Element) = popularAnimeFromElement(element) - override fun List