diff --git a/src/en/sflix/build.gradle b/src/en/sflix/build.gradle index bb3118c76..a00979b4d 100644 --- a/src/en/sflix/build.gradle +++ b/src/en/sflix/build.gradle @@ -5,8 +5,12 @@ ext { extName = 'Sflix' pkgNameSuffix = 'en.sflix' extClass = '.SFlix' - extVersionCode = 9 + extVersionCode = 10 libVersion = '13' } +dependencies { + compileOnly libs.bundles.coroutines +} + apply from: "$rootDir/common.gradle" diff --git a/src/en/sflix/src/eu/kanade/tachiyomi/animeextension/en/sflix/SFlix.kt b/src/en/sflix/src/eu/kanade/tachiyomi/animeextension/en/sflix/SFlix.kt index 9d9dd3c8b..436c92a04 100644 --- a/src/en/sflix/src/eu/kanade/tachiyomi/animeextension/en/sflix/SFlix.kt +++ b/src/en/sflix/src/eu/kanade/tachiyomi/animeextension/en/sflix/SFlix.kt @@ -2,73 +2,86 @@ package eu.kanade.tachiyomi.animeextension.en.sflix import android.app.Application import android.content.SharedPreferences -import android.net.Uri -import android.util.Base64 import androidx.preference.ListPreference import androidx.preference.PreferenceScreen +import eu.kanade.tachiyomi.animeextension.en.sflix.extractors.DoodExtractor +import eu.kanade.tachiyomi.animeextension.en.sflix.extractors.SFlixExtractor import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource -import eu.kanade.tachiyomi.animesource.model.AnimeFilter 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.Track 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.asObservableSuccess import eu.kanade.tachiyomi.util.asJsoup +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.runBlocking import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.jsonArray import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import okhttp3.Headers import okhttp3.HttpUrl.Companion.toHttpUrlOrNull 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 uy.kohesive.injekt.injectLazy class SFlix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { - override val name = "Sflix" + override val name = "SFlix" - override val baseUrl by lazy { preferences.getString("preferred_domain", "https://sflix.to")!! } + override val baseUrl by lazy { + "https://" + preferences.getString(PREF_DOMAIN_KEY, "dopebox.to")!! + } override val lang = "en" - override val supportsLatest = false + override val supportsLatest = true override val client: OkHttpClient = network.cloudflareClient - // private val domain = "aHR0cHM6Ly9yYWJiaXRzdHJlYW0ubmV0OjQ0Mw.." - private val preferences: SharedPreferences by lazy { Injekt.get().getSharedPreferences("source_$id", 0x0000) } - override fun headersBuilder(): Headers.Builder { - return super.headersBuilder() - .add("Referer", "$baseUrl/") - } + + private val json: Json by injectLazy() + + override fun headersBuilder(): Headers.Builder = Headers.Builder() + .add("Referer", "$baseUrl/") + + // ============================== Popular =============================== override fun popularAnimeSelector(): String = "div.film_list-wrap div.flw-item div.film-poster" - override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/movie?page=$page") + override fun popularAnimeRequest(page: Int): Request { + val type = preferences.getString(PREF_POPULAR_KEY, "movie")!! + return GET("$baseUrl/$type?page=$page") + } override fun popularAnimeFromElement(element: Element): SAnime { val anime = SAnime.create() - anime.setUrlWithoutDomain(element.select("a").attr("href")) - anime.thumbnail_url = element.select("img").attr("data-src") - anime.title = element.select("a").attr("title") + anime.setUrlWithoutDomain(element.selectFirst("a").attr("href")) + anime.thumbnail_url = element.selectFirst("img").attr("data-src") + anime.title = element.selectFirst("a").attr("title") return anime } override fun popularAnimeNextPageSelector(): String = "ul.pagination li.page-item a[title=next]" - // episodes + // ============================== Episodes ============================== override fun episodeListSelector() = throw Exception("not used") @@ -108,22 +121,21 @@ class SFlix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { val seasonId = element.attr("data-id") val seasonName = element.text() val episodesUrl = "$baseUrl/ajax/v2/season/episodes/$seasonId" - val episodesHtml = client.newCall( - GET( - episodesUrl, - ) - ).execute().asJsoup() + val episodesHtml = client.newCall(GET(episodesUrl)) + .execute() + .asJsoup() val episodeElements = episodesHtml.select("div.eps-item") return episodeElements.map { episodeFromElement(it, seasonName) } } private fun episodeFromElement(element: Element, seasonName: String): SEpisode { val episodeId = element.attr("data-id") - val episode = SEpisode.create() - val epNum = element.select("div.episode-number").text() - val epName = element.select("h3.film-name a").text() - episode.name = "$seasonName $epNum $epName" - episode.setUrlWithoutDomain("$baseUrl/ajax/v2/episode/servers/$episodeId") + val epNum = element.selectFirst("div.episode-number").text() + val epName = element.selectFirst("h3.film-name a").text() + val episode = SEpisode.create().apply { + name = "$seasonName $epNum $epName" + setUrlWithoutDomain("$baseUrl/ajax/v2/episode/servers/$episodeId") + } return episode } @@ -131,92 +143,86 @@ class SFlix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { return epsStr.filter { it.isDigit() } } - // Video Extractor + // ============================ Video Links ============================= override fun videoListParse(response: Response): List