From 839a04725fd0c078845b73bb0767a23af2c2bfd5 Mon Sep 17 00:00:00 2001 From: amr elnabawy <116549982+Amrd12@users.noreply.github.com> Date: Sat, 9 Mar 2024 01:50:08 +0200 Subject: [PATCH 01/15] Update Anime4Up.kt enable last eps tab and add the fun to filter by season --- .../animeextension/ar/anime4up/Anime4Up.kt | 211 +++++++++++++----- 1 file changed, 149 insertions(+), 62 deletions(-) diff --git a/src/ar/anime4up/src/eu/kanade/tachiyomi/animeextension/ar/anime4up/Anime4Up.kt b/src/ar/anime4up/src/eu/kanade/tachiyomi/animeextension/ar/anime4up/Anime4Up.kt index 68028c00bf..9393fea7b3 100644 --- a/src/ar/anime4up/src/eu/kanade/tachiyomi/animeextension/ar/anime4up/Anime4Up.kt +++ b/src/ar/anime4up/src/eu/kanade/tachiyomi/animeextension/ar/anime4up/Anime4Up.kt @@ -1,5 +1,4 @@ package eu.kanade.tachiyomi.animeextension.ar.anime4up - import android.app.Application import android.util.Base64 import androidx.preference.ListPreference @@ -22,7 +21,10 @@ import eu.kanade.tachiyomi.lib.vidbomextractor.VidBomExtractor import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.util.asJsoup -import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.runBlocking import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json @@ -36,14 +38,15 @@ import uy.kohesive.injekt.injectLazy import java.lang.Exception class Anime4Up : ConfigurableAnimeSource, ParsedAnimeHttpSource() { - override val name = "Anime4Up" override val baseUrl = "https://anime4up.cam" override val lang = "ar" - override val supportsLatest = false + override val supportsLatest = true + + override val client = network.cloudflareClient private val json: Json by injectLazy() @@ -58,84 +61,108 @@ class Anime4Up : ConfigurableAnimeSource, ParsedAnimeHttpSource() { override fun popularAnimeSelector() = "div.anime-list-content div.anime-card-poster > div.hover" - override fun popularAnimeFromElement(element: Element) = SAnime.create().apply { - element.selectFirst("img")!!.run { - thumbnail_url = absUrl("src") - title = attr("alt") + override fun popularAnimeFromElement(element: Element) = + SAnime.create().apply { + element.selectFirst("img")!!.run { + thumbnail_url = absUrl("src") + title = attr("alt") + } + setUrlWithoutDomain(element.selectFirst("a")!!.attr("href")) } - setUrlWithoutDomain(element.selectFirst("a")!!.attr("href")) - } override fun popularAnimeNextPageSelector() = "ul.pagination > li > a.next" // =============================== Latest =============================== - override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() - override fun latestUpdatesSelector() = throw UnsupportedOperationException() - override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException() - override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException() + override fun latestUpdatesRequest(page: Int) = GET(baseUrl + if (page > 1) "/episode/page/$page" else "/episode/", headers) + + override fun latestUpdatesSelector() = popularAnimeSelector() + + override fun latestUpdatesFromElement(element: Element) = popularAnimeFromElement(element) + // SAnime.create().apply { + // element.selectFirst("img")!!.run { + // thumbnail_url = absUrl("src") + // } + // title = element.select("div.anime-card-details > div.anime-card-title > h3")!!.text() + + // setUrlWithoutDomain(element.select("div.anime-card-details > div.anime-card-title > h3 a")!!.attr("href")) + // } + + override fun latestUpdatesNextPageSelector() = "ul.pagination > li:last-child >a" // =============================== Search =============================== override fun getFilterList() = Anime4UpFilters.FILTER_LIST - override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { + override fun searchAnimeRequest( + page: Int, + query: String, + filters: AnimeFilterList, + ): Request { if (query.isNotBlank()) { return GET("$baseUrl/?search_param=animes&s=$query", headers) } return with(Anime4UpFilters.getSearchParameters(filters)) { - val url = when { - genre.isNotBlank() -> "$baseUrl/anime-genre/$genre" - type.isNotBlank() -> "$baseUrl/anime-type/$type" - status.isNotBlank() -> "$baseUrl/anime-status/$status" - else -> throw Exception("اختر فلتر") - } + val url = + when { + genre.isNotBlank() -> "$baseUrl/anime-genre/$genre" + type.isNotBlank() -> "$baseUrl/anime-type/$type" + status.isNotBlank() -> "$baseUrl/anime-status/$status" + season.isNotBlank() -> "$baseUrl/anime-season/$season" + else -> throw Exception("اختر فلتر") + } GET(url, headers) } } override fun searchAnimeFromElement(element: Element) = popularAnimeFromElement(element) + override fun searchAnimeNextPageSelector() = popularAnimeNextPageSelector() + override fun searchAnimeSelector() = popularAnimeSelector() // =========================== Anime Details ============================ - override fun animeDetailsParse(document: Document) = SAnime.create().apply { - val doc = document // Shortcut - - thumbnail_url = doc.selectFirst("img.thumbnail")!!.attr("src") - title = doc.selectFirst("h1.anime-details-title")!!.text() - // Genres + useful info - genre = doc.select("ul.anime-genres > li > a, div.anime-info > a").eachText().joinToString() - - description = buildString { - // Additional info - doc.select("div.anime-info").eachText().forEach { - append("$it\n") - } - // Description - doc.selectFirst("p.anime-story")?.text()?.also { - append("\n$it") + override fun animeDetailsParse(document: Document) = + SAnime.create().apply { + val doc = document // Shortcut + + thumbnail_url = doc.selectFirst("img.thumbnail")!!.attr("src") + title = doc.selectFirst("h1.anime-details-title")!!.text() + // Genres + useful info + genre = doc.select("ul.anime-genres > li > a, div.anime-info > a").eachText().joinToString() + + description = + buildString { + // Additional info + doc.select("div.anime-info").eachText().forEach { + append("$it\n") + } + // Description + doc.selectFirst("p.anime-story")?.text()?.also { + append("\n$it") + } + } + + doc.selectFirst("div.anime-info:contains(حالة الأنمي)")?.text()?.also { + status = + when { + it.contains("يعرض الان", true) -> SAnime.ONGOING + it.contains("مكتمل", true) -> SAnime.COMPLETED + else -> SAnime.UNKNOWN + } } } - doc.selectFirst("div.anime-info:contains(حالة الأنمي)")?.text()?.also { - status = when { - it.contains("يعرض الان", true) -> SAnime.ONGOING - it.contains("مكتمل", true) -> SAnime.COMPLETED - else -> SAnime.UNKNOWN - } - } - } - // ============================== Episodes ============================== override fun episodeListParse(response: Response) = super.episodeListParse(response).reversed() override fun episodeListSelector() = "div.ehover6 > div.episodes-card-title > h3 > a, ul.all-episodes-list li > a" - override fun episodeFromElement(element: Element) = SEpisode.create().apply { - setUrlWithoutDomain(element.attr("href")) - name = element.text() - episode_number = name.substringAfterLast(" ").toFloatOrNull() ?: 0F - } + override fun episodeFromElement(element: Element) = + SEpisode.create().apply { + setUrlWithoutDomain(element.attr("href")) + name = element.text() + episode_number = name.substringAfterLast(" ").toFloatOrNull() ?: 0F + } // ============================ Video Links ============================= @Serializable @@ -146,15 +173,16 @@ class Anime4Up : ConfigurableAnimeSource, ParsedAnimeHttpSource() { ) override fun videoListParse(response: Response): List