diff --git a/src/en/dramacool/build.gradle b/src/en/dramacool/build.gradle index d56ae42b8..af9ce6eab 100644 --- a/src/en/dramacool/build.gradle +++ b/src/en/dramacool/build.gradle @@ -1,11 +1,13 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) +} ext { extName = 'DramaCool' pkgNameSuffix = 'en.dramacool' extClass = '.DramaCool' - extVersionCode = 44 + extVersionCode = 45 libVersion = '13' } @@ -13,8 +15,6 @@ dependencies { implementation(project(':lib-streamwish-extractor')) implementation(project(':lib-streamtape-extractor')) implementation(project(':lib-dood-extractor')) - implementation(project(':lib-playlist-utils')) - implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1" } apply from: "$rootDir/common.gradle" diff --git a/src/en/dramacool/src/eu/kanade/tachiyomi/animeextension/en/dramacool/DramaCool.kt b/src/en/dramacool/src/eu/kanade/tachiyomi/animeextension/en/dramacool/DramaCool.kt index ea8e07c9c..cf2f91b1b 100644 --- a/src/en/dramacool/src/eu/kanade/tachiyomi/animeextension/en/dramacool/DramaCool.kt +++ b/src/en/dramacool/src/eu/kanade/tachiyomi/animeextension/en/dramacool/DramaCool.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.animeextension.en.dramacool import android.app.Application -import android.content.SharedPreferences import android.widget.Toast import androidx.preference.EditTextPreference import androidx.preference.ListPreference @@ -9,7 +8,6 @@ import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.animeextension.BuildConfig 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 @@ -19,7 +17,6 @@ import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.util.asJsoup -import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response import org.jsoup.nodes.Document @@ -42,197 +39,124 @@ class DramaCool : ConfigurableAnimeSource, ParsedAnimeHttpSource() { override val supportsLatest = true - override val client: OkHttpClient = network.cloudflareClient + override val client = network.cloudflareClient - private val preferences: SharedPreferences by lazy { + private val preferences by lazy { Injekt.get().getSharedPreferences("source_$id", 0x0000) } // ============================== Popular =============================== + override fun popularAnimeRequest(page: Int) = GET("$baseUrl/most-popular-drama?page=$page") // page/$page - override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/most-popular-drama?page=$page") // page/$page + override fun popularAnimeSelector() = "ul.list-episode-item li a" - override fun popularAnimeSelector(): String = "ul.list-episode-item li a" - - override fun popularAnimeFromElement(element: Element): SAnime = SAnime.create().apply { - setUrlWithoutDomain(element.attr("abs:href")) - thumbnail_url = element.select("img").attr("data-original").replace(" ", "%20") - title = element.select("h3").text() + override fun popularAnimeFromElement(element: Element) = SAnime.create().apply { + setUrlWithoutDomain(element.attr("href")) + thumbnail_url = element.selectFirst("img")?.attr("data-original")?.replace(" ", "%20") + title = element.selectFirst("h3")?.text() ?: "Serie" } - override fun popularAnimeNextPageSelector(): String = "li.next a" + override fun popularAnimeNextPageSelector() = "li.next a" // =============================== Latest =============================== + override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/recently-added?page=$page") - override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/recently-added?page=$page") + override fun latestUpdatesSelector() = "ul.switch-block a" - override fun latestUpdatesParse(response: Response): AnimesPage { - val document = response.asJsoup() + override fun latestUpdatesFromElement(element: Element) = popularAnimeFromElement(element) - val animes = document.select("ul.switch-block a").map { element -> - val hrefDocument = client.newCall(GET(element.attr("abs:href"))).execute().asJsoup() - SAnime.create().apply { - title = element.select("h3").text() - setUrlWithoutDomain(hrefDocument.select("div.category a").attr("abs:href")) - thumbnail_url = element.select("img").attr("data-original").replace(" ", "%20") - } - } - val hasNextPage = document.select("li.next a").first() != null - - return AnimesPage(animes, hasNextPage) - } - - override fun latestUpdatesSelector(): String = throw Exception("not used") - - override fun latestUpdatesFromElement(element: Element): SAnime = throw Exception("not used") - - override fun latestUpdatesNextPageSelector(): String = throw Exception("not used") + override fun latestUpdatesNextPageSelector() = popularAnimeNextPageSelector() // =============================== Search =============================== - - override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = + override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList) = GET("$baseUrl/search?keyword=$query&page=$page") - override fun searchAnimeSelector(): String = "ul.list-episode-item li a" + override fun searchAnimeSelector() = popularAnimeSelector() - override fun searchAnimeFromElement(element: Element): SAnime = SAnime.create().apply { - setUrlWithoutDomain(element.attr("abs:href")) - thumbnail_url = element.select("img").attr("data-original").replace(" ", "%20") - title = element.select("h3").text() - } + override fun searchAnimeFromElement(element: Element) = popularAnimeFromElement(element) - override fun searchAnimeNextPageSelector(): String = "li.next a" + override fun searchAnimeNextPageSelector() = popularAnimeNextPageSelector() // =========================== Anime Details ============================ + override fun animeDetailsRequest(anime: SAnime): Request { + if (anime.url.contains("-episode-") && anime.url.endsWith(".html")) { + val doc = client.newCall(GET(baseUrl + anime.url)).execute().use { it.asJsoup() } + anime.setUrlWithoutDomain(doc.selectFirst("div.category a")!!.attr("href")) + } + return GET(baseUrl + anime.url) + } - override fun animeDetailsParse(document: Document): SAnime = SAnime.create().apply { - title = document.select("div.img img").attr("alt") - thumbnail_url = document.select("div.img img").attr("src") - description = document.select("div.info p").text().substringAfter("Description: ").substringBefore("Country: ").substringBefore("Director: ").substringBefore("Original Network: ") - author = document.select("div.info p:contains(Original Network) a").text() - genre = document.select("div.info p:contains(Genre) a").joinToString(", ") { it.text() } - status = parseStatus(document.select("div.info p:contains(Status) a").text()) + override fun animeDetailsParse(document: Document) = SAnime.create().apply { + document.selectFirst("div.img img")!!.run { + title = attr("alt") + thumbnail_url = absUrl("src") + } + + with(document.selectFirst("div.info")!!) { + description = select("p:contains(Description) ~ p:not(:has(span))").eachText() + .joinToString("\n") + .takeUnless(String::isBlank) + author = selectFirst("p:contains(Original Network:) > a")?.text() + genre = select("p:contains(Genre:) > a").joinToString { it.text() }.takeUnless(String::isBlank) + status = parseStatus(selectFirst("p:contains(Status) a")?.text()) + } } // ============================== Episodes ============================== - override fun episodeListSelector() = "ul.all-episode li a" - override fun episodeFromElement(element: Element): SEpisode { - val epNum = element.select("h3").text().substringAfter("Episode ") - - return SEpisode.create().apply { - setUrlWithoutDomain(element.attr("abs:href")) - name = element.select("span.type").text() + ": Episode " + element.select("h3").text().substringAfter("Episode ") - episode_number = when { - epNum.isNotEmpty() -> epNum.toFloatOrNull() ?: 1F - else -> 1F - } - date_upload = parseDate(element.select("span.time").text()) + override fun episodeFromElement(element: Element) = SEpisode.create().apply { + setUrlWithoutDomain(element.attr("href")) + val epNum = element.selectFirst("h3")!!.text().substringAfterLast("Episode ") + val type = element.selectFirst("span.type")?.text() ?: "RAW" + name = "$type: Episode $epNum".trimEnd() + episode_number = when { + epNum.isNotEmpty() -> epNum.toFloatOrNull() ?: 1F + else -> 1F } + date_upload = element.selectFirst("span.time")?.text().orEmpty().toDate() } // ============================ Video Links ============================= - - override fun videoListRequest(episode: SEpisode): Request { - val document = client.newCall(GET(baseUrl + episode.url)).execute().asJsoup() - val iframe = document.select("iframe").attr("abs:src") - return GET(iframe) - } - - override fun videoListParse(response: Response): List