From d7188f1c6ef610868e65e42a96c615c42e927fcc Mon Sep 17 00:00:00 2001 From: LuftVerbot <97435834+LuftVerbot@users.noreply.github.com> Date: Fri, 4 Nov 2022 17:58:56 +0100 Subject: [PATCH] update aniking, add de.movie4k, remove anime-shitai & xcine (#998) --- src/de/aniking/build.gradle | 2 +- .../animeextension/de/aniking/Aniking.kt | 24 +- .../de/aniking/CloudflareInterceptor.kt | 5 +- .../res/mipmap-hdpi/ic_launcher.png | Bin 4856 -> 0 bytes .../res/mipmap-mdpi/ic_launcher.png | Bin 4856 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher.png | Bin 4856 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher.png | Bin 4856 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 4856 -> 0 bytes .../de/animeshitai/ASConstants.kt | 21 - .../de/animeshitai/ASFilters.kt | 204 -------- .../de/animeshitai/AnimeShitai.kt | 356 -------------- .../de/animeshitai/model/ASAnime.kt | 23 - .../AndroidManifest.xml | 0 src/de/{animeshitai => movie4k}/build.gradle | 10 +- .../movie4k/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3184 bytes .../mipmap-hdpi/ic_launcher_adaptive_back.png | Bin .../mipmap-hdpi/ic_launcher_adaptive_fore.png | Bin 0 -> 5560 bytes .../movie4k/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1875 bytes .../mipmap-mdpi/ic_launcher_adaptive_back.png | Bin .../mipmap-mdpi/ic_launcher_adaptive_fore.png | Bin 0 -> 3068 bytes .../movie4k/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4424 bytes .../ic_launcher_adaptive_back.png | Bin .../ic_launcher_adaptive_fore.png | Bin 0 -> 8214 bytes .../movie4k/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7725 bytes .../ic_launcher_adaptive_back.png | Bin .../ic_launcher_adaptive_fore.png | Bin 0 -> 16381 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 11481 bytes .../ic_launcher_adaptive_back.png | Bin .../ic_launcher_adaptive_fore.png | Bin 0 -> 24404 bytes .../animeextension/de/movie4k/Movie4k.kt | 452 ++++++++++++++++++ .../de/movie4k/extractors/StreamZExtractor.kt | 15 + .../de/movie4k/extractors/VidozaExtractor.kt | 17 + src/de/xcine/AndroidManifest.xml | 2 - src/de/xcine/build.gradle | 13 - src/de/xcine/res/mipmap-hdpi/ic_launcher.png | Bin 2639 -> 0 bytes .../mipmap-hdpi/ic_launcher_adaptive_fore.png | Bin 3954 -> 0 bytes src/de/xcine/res/mipmap-mdpi/ic_launcher.png | Bin 1511 -> 0 bytes .../mipmap-mdpi/ic_launcher_adaptive_fore.png | Bin 2265 -> 0 bytes src/de/xcine/res/mipmap-xhdpi/ic_launcher.png | Bin 3542 -> 0 bytes .../ic_launcher_adaptive_fore.png | Bin 6347 -> 0 bytes .../xcine/res/mipmap-xxhdpi/ic_launcher.png | Bin 6345 -> 0 bytes .../ic_launcher_adaptive_fore.png | Bin 12403 -> 0 bytes .../xcine/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9466 -> 0 bytes .../ic_launcher_adaptive_fore.png | Bin 19235 -> 0 bytes .../de/xcine/CookieInterceptor.kt | 88 ---- .../de/xcine/extractors/HDFilmExtractor.kt | 52 -- .../animeextension/de/xcine/xCine.kt | 216 --------- 47 files changed, 515 insertions(+), 985 deletions(-) delete mode 100644 src/de/animeshitai/res/mipmap-hdpi/ic_launcher.png delete mode 100644 src/de/animeshitai/res/mipmap-mdpi/ic_launcher.png delete mode 100644 src/de/animeshitai/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 src/de/animeshitai/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 src/de/animeshitai/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 src/de/animeshitai/src/eu/kanade/tachiyomi/animeextension/de/animeshitai/ASConstants.kt delete mode 100644 src/de/animeshitai/src/eu/kanade/tachiyomi/animeextension/de/animeshitai/ASFilters.kt delete mode 100644 src/de/animeshitai/src/eu/kanade/tachiyomi/animeextension/de/animeshitai/AnimeShitai.kt delete mode 100644 src/de/animeshitai/src/eu/kanade/tachiyomi/animeextension/de/animeshitai/model/ASAnime.kt rename src/de/{animeshitai => movie4k}/AndroidManifest.xml (100%) rename src/de/{animeshitai => movie4k}/build.gradle (59%) create mode 100644 src/de/movie4k/res/mipmap-hdpi/ic_launcher.png rename src/de/{xcine => movie4k}/res/mipmap-hdpi/ic_launcher_adaptive_back.png (100%) create mode 100644 src/de/movie4k/res/mipmap-hdpi/ic_launcher_adaptive_fore.png create mode 100644 src/de/movie4k/res/mipmap-mdpi/ic_launcher.png rename src/de/{xcine => movie4k}/res/mipmap-mdpi/ic_launcher_adaptive_back.png (100%) create mode 100644 src/de/movie4k/res/mipmap-mdpi/ic_launcher_adaptive_fore.png create mode 100644 src/de/movie4k/res/mipmap-xhdpi/ic_launcher.png rename src/de/{xcine => movie4k}/res/mipmap-xhdpi/ic_launcher_adaptive_back.png (100%) create mode 100644 src/de/movie4k/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png create mode 100644 src/de/movie4k/res/mipmap-xxhdpi/ic_launcher.png rename src/de/{xcine => movie4k}/res/mipmap-xxhdpi/ic_launcher_adaptive_back.png (100%) create mode 100644 src/de/movie4k/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png create mode 100644 src/de/movie4k/res/mipmap-xxxhdpi/ic_launcher.png rename src/de/{xcine => movie4k}/res/mipmap-xxxhdpi/ic_launcher_adaptive_back.png (100%) create mode 100644 src/de/movie4k/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png create mode 100644 src/de/movie4k/src/eu/kanade/tachiyomi/animeextension/de/movie4k/Movie4k.kt create mode 100644 src/de/movie4k/src/eu/kanade/tachiyomi/animeextension/de/movie4k/extractors/StreamZExtractor.kt create mode 100644 src/de/movie4k/src/eu/kanade/tachiyomi/animeextension/de/movie4k/extractors/VidozaExtractor.kt delete mode 100644 src/de/xcine/AndroidManifest.xml delete mode 100644 src/de/xcine/build.gradle delete mode 100644 src/de/xcine/res/mipmap-hdpi/ic_launcher.png delete mode 100644 src/de/xcine/res/mipmap-hdpi/ic_launcher_adaptive_fore.png delete mode 100644 src/de/xcine/res/mipmap-mdpi/ic_launcher.png delete mode 100644 src/de/xcine/res/mipmap-mdpi/ic_launcher_adaptive_fore.png delete mode 100644 src/de/xcine/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 src/de/xcine/res/mipmap-xhdpi/ic_launcher_adaptive_fore.png delete mode 100644 src/de/xcine/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 src/de/xcine/res/mipmap-xxhdpi/ic_launcher_adaptive_fore.png delete mode 100644 src/de/xcine/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 src/de/xcine/res/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png delete mode 100644 src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/CookieInterceptor.kt delete mode 100644 src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/extractors/HDFilmExtractor.kt delete mode 100644 src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/xCine.kt diff --git a/src/de/aniking/build.gradle b/src/de/aniking/build.gradle index 19c20ef90..debde2ed1 100644 --- a/src/de/aniking/build.gradle +++ b/src/de/aniking/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'Aniking' pkgNameSuffix = 'de.aniking' extClass = '.Aniking' - extVersionCode = 1 + extVersionCode = 2 libVersion = '13' } diff --git a/src/de/aniking/src/eu/kanade/tachiyomi/animeextension/de/aniking/Aniking.kt b/src/de/aniking/src/eu/kanade/tachiyomi/animeextension/de/aniking/Aniking.kt index 3ef5ab880..d329dd28b 100644 --- a/src/de/aniking/src/eu/kanade/tachiyomi/animeextension/de/aniking/Aniking.kt +++ b/src/de/aniking/src/eu/kanade/tachiyomi/animeextension/de/aniking/Aniking.kt @@ -65,7 +65,16 @@ class Aniking : ConfigurableAnimeSource, ParsedAnimeHttpSource() { // episodes override fun episodeListRequest(anime: SAnime): Request { - return GET("$baseUrl${anime.url}", headers = Headers.headersOf("if-modified-since", "")) + val interceptor = client.newBuilder().addInterceptor(CloudflareInterceptor()).build() + val headers = interceptor.newCall( + GET( + "$baseUrl${anime.url}", + headers = + Headers.headersOf("user-agent", "Mozilla/5.0 (Linux; Android 12; SM-T870 Build/SP2A.220305.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Safari/537.36") + ) + ) + .execute().request.headers + return GET("$baseUrl${anime.url}", headers = headers) } override fun episodeListSelector() = throw Exception("not used") @@ -268,6 +277,19 @@ class Aniking : ConfigurableAnimeSource, ParsedAnimeHttpSource() { // Details + override fun animeDetailsRequest(anime: SAnime): Request { + val interceptor = client.newBuilder().addInterceptor(CloudflareInterceptor()).build() + val headers = interceptor.newCall( + GET( + "$baseUrl${anime.url}", + headers = + Headers.headersOf("user-agent", "Mozilla/5.0 (Linux; Android 12; SM-T870 Build/SP2A.220305.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Safari/537.36") + ) + ) + .execute().request.headers + return GET("$baseUrl${anime.url}", headers = headers) + } + override fun animeDetailsParse(document: Document): SAnime { val anime = SAnime.create() anime.thumbnail_url = document.select("div.tv-poster img").attr("src") diff --git a/src/de/aniking/src/eu/kanade/tachiyomi/animeextension/de/aniking/CloudflareInterceptor.kt b/src/de/aniking/src/eu/kanade/tachiyomi/animeextension/de/aniking/CloudflareInterceptor.kt index 725c80176..b1651b4a3 100644 --- a/src/de/aniking/src/eu/kanade/tachiyomi/animeextension/de/aniking/CloudflareInterceptor.kt +++ b/src/de/aniking/src/eu/kanade/tachiyomi/animeextension/de/aniking/CloudflareInterceptor.kt @@ -53,8 +53,7 @@ class CloudflareInterceptor() : Interceptor { databaseEnabled = true useWideViewPort = false loadWithOverviewMode = false - userAgentString = request.header("User-Agent") - ?: "\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63\"" + userAgentString = "Mozilla/5.0 (Linux; Android 12; SM-T870 Build/SP2A.220305.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Safari/537.36" } webview.webViewClient = object : WebViewClient() { @@ -62,7 +61,7 @@ class CloudflareInterceptor() : Interceptor { view: WebView, request: WebResourceRequest, ): WebResourceResponse? { - if (request.url.toString().contains("https://aniking.cc")) { + if (request.url.toString().contains("wp-content/themes/moviewp")) { newRequest = GET(request.url.toString(), request.requestHeaders.toHeaders()) latch.countDown() } diff --git a/src/de/animeshitai/res/mipmap-hdpi/ic_launcher.png b/src/de/animeshitai/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 0d2b2076d7302cfd8a9dd1319a56b2a57dc8ee30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4856 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 : AnimeFilter.Group(name, values) - private class CheckBoxVal(name: String, state: Boolean = false) : AnimeFilter.CheckBox(name, state) - - open class TriStateFilterList(name: String, values: List) : AnimeFilter.Group(name, values) - private class TriStateVal(name: String) : AnimeFilter.TriState(name) - - class SortFilter : AnimeFilter.Sort( - "Sortieren", - ASFilterData.sortables.map { it.first }.toTypedArray(), - Selection(0, true) - ) - - class FormatFilter : CheckBoxFilterList( - "Format", - ASFilterData.formats.map { CheckBoxVal(it.first, true) } - ) - - class LanguageFilter : CheckBoxFilterList( - "Sprache", - ASFilterData.languages.map { CheckBoxVal(it.first, true) } - ) - - class GenreFilter : TriStateFilterList( - "Genres", - ASFilterData.genres.map { TriStateVal(it) } - ) - - class YearsFilter : CheckBoxFilterList( - "Jahre", - ASFilterData.years.map { CheckBoxVal(it.toString()) } - ) - - class ABCFilter : CheckBoxFilterList( - "ABC", - ASFilterData.abc.map { CheckBoxVal(it.toString()) } - ) - - val filterList = AnimeFilterList( - SortFilter(), - FormatFilter(), - LanguageFilter(), - GenreFilter(), - YearsFilter(), - ABCFilter(), - ) - - data class FilterSearchParams( - var orderBy: String = "az", - var orderAscending: Boolean = true, - val includedFormats: ArrayList = ArrayList(), - val includedLangs: ArrayList = ArrayList(), - val includedGenres: ArrayList = ArrayList(), - val blackListedGenres: ArrayList = ArrayList(), - val includedYears: ArrayList = ArrayList(), - val includedLetters: ArrayList = ArrayList(), - ) - - internal fun getSearchParameters(filters: AnimeFilterList): FilterSearchParams { - val params = FilterSearchParams() - filters.forEach { filter -> - when (filter) { - is SortFilter -> { - if (filter.state != null) { - val query = ASFilterData.sortables[filter.state!!.index].second - params.orderAscending = filter.state!!.ascending - params.orderBy = query - } - } - is FormatFilter -> { - filter.state.forEach { format -> - if (format.state) { - val query = ASFilterData.formats.find { it.first == format.name }!!.second - params.includedFormats.add(query) - } - } - } - is LanguageFilter -> { - filter.state.forEach { lang -> - if (lang.state) { - val query = ASFilterData.languages.find { it.first == lang.name }!!.second - params.includedLangs.add(query) - } - } - } - is GenreFilter -> { - filter.state.forEach { genre -> - if (genre.isIncluded()) { - params.includedGenres.add(genre.name) - } else if (genre.isExcluded()) { - params.blackListedGenres.add(genre.name) - } - } - } - is YearsFilter -> { - filter.state.forEach { year -> - if (year.state) - params.includedYears.add(year.name) - } - } - is ABCFilter -> { - filter.state.forEach { letter -> - if (letter.state) - params.includedLetters.add(letter.name) - } - } - else -> {} - } - } - return params - } - - fun MutableList.applyFilterParams(params: FilterSearchParams) { - // Remove all entries with blacklisted genres - this.removeAll { anime -> params.blackListedGenres.any { it in anime.genre ?: "" } } - - // Sort animes - when (params.orderBy) { - // Sort animes alphabetically - "az" -> { - if (!params.orderAscending) - this.reverse() - } - // Sort animes by year - "year" -> { - if (params.orderAscending) - this.sortBy { it.year } - else - this.sortByDescending { it.year } - } - } - } -} - -private object ASFilterData { - // (1990..(Year.now().value)).reversed() - val years = (1990..(Calendar.getInstance().get(Calendar.YEAR))).reversed() - - val abc = 'A'..'Z' - - val sortables = arrayOf( - Pair("Alphabetisch", "az"), - Pair("Jahr", "year"), - ) - - val formats = arrayOf( - Pair("\uD83D\uDCFA Serien", "Serien"), - Pair("\uD83C\uDF10 OVAs", "OVAs"), - Pair("\uD83C\uDFAC Filme", "Filme") - ) - - val languages = arrayOf( - Pair("\uD83C\uDDE9\uD83C\uDDEA Ger Dub", "Ger Dub"), - Pair("\uD83C\uDDEF\uD83C\uDDF5 Ger Sub", "Ger Sub"), - Pair("\uD83C\uDDEC\uD83C\uDDE7 Eng Dub & Ger Sub", "Eng Dub") - ) - - val genres = listOf( - "Abenteuer", - "Action", - "Alltagsleben", - "Alternative Welt", - "Drama", - "Ecchi", - "Erotik", - "Fantasy", - "Fighting-Shounen", - "Ganbatte", - "Geistergeschichten", - "Harem", - "Historisch", - "Horror", - "Komödie", - "Krimi", - "Liebesdrama", - "Magical Girl", - "Magie", - "Mecha", - "Mystery", - "Nonsense-Komödie", - "Psychodrama", - "Romantische Komödie", - "Romanze", - "Schule", - "Sci-Fi", - "Sentimentales Drama", - "Shoujou", - "Shounen", - "Sport", - "Superpower", - "Thriller", - "Übermäßige Gewaltdarstellung", - "Unbestimmt", - "Yaoi", - "Yuri" - ) -} diff --git a/src/de/animeshitai/src/eu/kanade/tachiyomi/animeextension/de/animeshitai/AnimeShitai.kt b/src/de/animeshitai/src/eu/kanade/tachiyomi/animeextension/de/animeshitai/AnimeShitai.kt deleted file mode 100644 index fdf9bf1c2..000000000 --- a/src/de/animeshitai/src/eu/kanade/tachiyomi/animeextension/de/animeshitai/AnimeShitai.kt +++ /dev/null @@ -1,356 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.de.animeshitai - -import android.app.Application -import android.content.SharedPreferences -import android.util.Base64 -import androidx.preference.ListPreference -import androidx.preference.MultiSelectListPreference -import androidx.preference.PreferenceScreen -import eu.kanade.tachiyomi.animeextension.de.animeshitai.ASFilters.applyFilterParams -import eu.kanade.tachiyomi.animeextension.de.animeshitai.model.ASAnime -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.lib.doodextractor.DoodExtractor -import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.POST -import eu.kanade.tachiyomi.network.asObservableSuccess -import eu.kanade.tachiyomi.util.asJsoup -import okhttp3.FormBody -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import org.jsoup.Jsoup -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import rx.Observable -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import kotlin.collections.ArrayList - -class AnimeShitai : ConfigurableAnimeSource, ParsedAnimeHttpSource() { - - override val name = "Anime Shitai" - - override val baseUrl = "https://anime-shitai.com" - - override val lang = "de" - - override val supportsLatest = true - - override val client: OkHttpClient = network.cloudflareClient - - private val preferences: SharedPreferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) - } - - // ===== POPULAR ANIME ===== - override fun popularAnimeSelector(): String = ".newanimes .newbox" - - override fun popularAnimeNextPageSelector(): String? = null - - override fun popularAnimeRequest(page: Int): Request = GET(baseUrl) - - override fun popularAnimeFromElement(element: Element): SAnime { - val anime = SAnime.create() - val linkElement = element.selectFirst("a") - anime.url = linkElement.attr("href") - anime.thumbnail_url = linkElement.selectFirst("img").attr("src") - anime.title = element.selectFirst(".ntitel").text() - return anime - } - - // ===== LATEST ANIME ===== - override fun latestUpdatesSelector(): String = "a" - - override fun latestUpdatesNextPageSelector(): String? = null - - override fun latestUpdatesRequest(page: Int): Request = POST("$baseUrl/ichigo/indexep.php?option=1") - - override fun latestUpdatesParse(response: Response): AnimesPage { - val document = Jsoup.parseBodyFragment(response.body?.string()) - val animeList = mutableSetOf() - val animes = document.select(latestUpdatesSelector()).mapNotNull { element -> - val animeName = element.selectFirst("span.t").text().substringBefore("...") - // Check if any anime is multiple times in the list - if (!animeList.contains(animeName)) { - animeList.add(animeName) - latestUpdatesFromElement(element) - } else - null - } - - return AnimesPage(animes, false) - } - - override fun latestUpdatesFromElement(element: Element): SAnime { - val anime = SAnime.create() - val animeId = element.attr("href").substringAfter("/anschauen/").substringBefore('/') - anime.url = "/anime/$animeId/" - anime.thumbnail_url = element.selectFirst("div.c").attr("style").substringAfter("background:url('").substringBefore("');") - anime.title = anime.thumbnail_url!!.substringAfter("/cover/").substringBefore(".jpg").replace("__", ": ").replace('_', ' ') - return anime - } - - // ===== ANIME SEARCH ===== - override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable { - val params = ASFilters.getSearchParameters(filters) - return client.newCall(searchAnimeRequest(page, query, params)) - .asObservableSuccess() - .map { response -> - searchAnimeParse(response, params) - } - } - - override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request = throw UnsupportedOperationException("Not used.") - - private fun searchAnimeRequest(page: Int, query: String, params: ASFilters.FilterSearchParams): Request { - fun listToFormStr(list: ArrayList): String { - if (list.size > 0) - return list.joinToString(" - ", " - ") - return "" - } - val body = FormBody.Builder() - .add("p", page.toString()) - .add("get_val", query) - .add("genre", listToFormStr(params.includedGenres)) - .add("jahr", listToFormStr(params.includedYears)) - .add("format", listToFormStr(params.includedFormats)) - .add("omu", listToFormStr(params.includedLangs)) - .add("abc", listToFormStr(params.includedLetters)) - .build() - - return POST("$baseUrl/ichigo/get_anilist.php", headers, body) - } - - override fun searchAnimeSelector(): String = ".listinganime" - - override fun searchAnimeNextPageSelector(): String? = ".nav" - - override fun searchAnimeParse(response: Response): AnimesPage = throw UnsupportedOperationException("Not used.") - - private fun searchAnimeParse(response: Response, params: ASFilters.FilterSearchParams): AnimesPage { - val document = Jsoup.parseBodyFragment(response.body?.string()) - - val animeTrackList = mutableSetOf() - val animes = document.select(searchAnimeSelector()).mapNotNull { element -> - val anime = searchAnimeFromElement(element) - // Shows with sub and dub have two separate entries, exclude the second entry - if (!animeTrackList.contains(anime.thumbnail_url)) { - animeTrackList.add(anime.thumbnail_url!!) - anime - } else - null - }.toMutableList() - - // Apply client-side filters - animes.applyFilterParams(params) - - val hasNextPage = searchAnimeNextPageSelector()?.let { selector -> - document.select(selector).first() - } != null - - return AnimesPage(animes, hasNextPage) - } - - override fun searchAnimeFromElement(element: Element): ASAnime { - val anime = ASAnime.create() - anime.url = element.selectFirst("a").attr("href") - anime.thumbnail_url = element.selectFirst(".listinganicover").attr("style").substringAfter("url('").substringBefore("')") - anime.title = element.selectFirst(".listingtitle").text().replaceAfterLast(' ', "").trimStart() - // Get genres for client-side genre filtering - anime.genre = element.select(".listingdesc .alternativ").mapNotNull { - if (it.text().startsWith("Hauptgenre") || it.text().startsWith("Genres")) - it.text().substringAfter(':') - else - null - }.joinToString(", ") - - anime.year = element.selectFirst(".listingtitle").text().substringAfterLast('(').substringBefore(')').toInt() - return anime - } - - override fun getFilterList(): AnimeFilterList = ASFilters.filterList - - // ===== ANIME DETAILS ===== - override fun animeDetailsParse(document: Document): SAnime { - val anime = SAnime.create() - val content = document.selectFirst("#ani .body") - anime.title = content.selectFirst("animename").ownText().trim() - anime.thumbnail_url = document.selectFirst("#ani .pic").attr("data-src") - anime.genre = content.select("div:eq(1) .hg, a").joinToString(", ") { it.text() } - anime.description = content.selectFirst(".br").ownText() - anime.status = SAnime.UNKNOWN - return anime - } - - // ===== EPISODE ===== - override fun episodeListSelector(): String = ".ep_table tbody tr" - - override fun episodeListParse(response: Response): List { - val document = response.asJsoup() - return document.select(episodeListSelector()).reversed().map { episodeFromElement(it) } - } - - override fun episodeFromElement(element: Element): SEpisode { - val episode = SEpisode.create() - episode.setUrlWithoutDomain(baseUrl + element.attr("onclick").substringAfter("window.location.href='").substringBefore('#')) - val ep = element.child(0).text() - episode.episode_number = ep.toFloat() - episode.name = "Episode $ep" - return episode - } - - // ===== VIDEO SOURCES ===== - override fun videoListSelector(): String = "center a" - - override fun videoListParse(response: Response): List