diff --git a/lib/fastream-extractor/src/main/java/eu/kanade/tachiyomi/lib/fastreamextractor/FastreamExtractor.kt b/lib/fastream-extractor/src/main/java/eu/kanade/tachiyomi/lib/fastreamextractor/FastreamExtractor.kt index 0d07c910d..7aba71fd3 100644 --- a/lib/fastream-extractor/src/main/java/eu/kanade/tachiyomi/lib/fastreamextractor/FastreamExtractor.kt +++ b/lib/fastream-extractor/src/main/java/eu/kanade/tachiyomi/lib/fastreamextractor/FastreamExtractor.kt @@ -25,18 +25,20 @@ class FastreamExtractor(private val client: OkHttpClient, private val headers: H return runCatching { val firstDoc = client.newCall(GET(url, videoHeaders)).execute().use { it.asJsoup() } - val form = FormBody.Builder().apply { - firstDoc.select("input[name]").forEach { - add(it.attr("name"), it.attr("value")) - } - }.build() - if (needsSleep) Thread.sleep(5100L) // 5s is the minimum - val doc = client.newCall(POST(url, videoHeaders, body = form)).execute() - .use { it.asJsoup() } - val scriptElement = doc.selectFirst("script:containsData(jwplayer):containsData(vplayer)") - ?: return emptyList() + val scriptElement = if (firstDoc.select("input[name]").any()) { + val form = FormBody.Builder().apply { + firstDoc.select("input[name]").forEach { + add(it.attr("name"), it.attr("value")) + } + }.build() + val doc = client.newCall(POST(url, videoHeaders, body = form)).execute().use { it.asJsoup() } + doc.selectFirst("script:containsData(jwplayer):containsData(vplayer)") ?: return emptyList() + } + else { + firstDoc.selectFirst("script:containsData(jwplayer):containsData(vplayer)") ?: return emptyList() + } val scriptData = scriptElement.data().let { when { @@ -45,10 +47,7 @@ class FastreamExtractor(private val client: OkHttpClient, private val headers: H } } ?: return emptyList() - val videoUrl = scriptData.substringAfter("file:") - .substringBefore('}') - .substringBefore(',') - .trim('"', '\'', ' ') + val videoUrl = scriptData.substringAfter("file:\"").substringBefore("\"").trim() return when { videoUrl.contains(".m3u8") -> { diff --git a/src/es/metroseries/build.gradle b/src/es/metroseries/build.gradle index ad4f41700..921c2c770 100644 --- a/src/es/metroseries/build.gradle +++ b/src/es/metroseries/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'MetroSeries' pkgNameSuffix = 'es.metroseries' extClass = '.MetroSeries' - extVersionCode = 3 + extVersionCode = 4 libVersion = '13' } diff --git a/src/es/metroseries/src/eu/kanade/tachiyomi/animeextension/es/metroseries/MetroSeries.kt b/src/es/metroseries/src/eu/kanade/tachiyomi/animeextension/es/metroseries/MetroSeries.kt index bd97990eb..db292fb4a 100644 --- a/src/es/metroseries/src/eu/kanade/tachiyomi/animeextension/es/metroseries/MetroSeries.kt +++ b/src/es/metroseries/src/eu/kanade/tachiyomi/animeextension/es/metroseries/MetroSeries.kt @@ -30,6 +30,7 @@ import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response +import org.jsoup.nodes.Element import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.text.SimpleDateFormat @@ -80,7 +81,8 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() { SAnime.create().apply { setUrlWithoutDomain(element.selectFirst(".lnk-blk")?.attr("abs:href") ?: "") title = element.selectFirst(".entry-header .entry-title")?.text() ?: "" - thumbnail_url = element.selectFirst(".post-thumbnail figure img")?.attr("abs:src") ?: "" + description = element.select(".entry-content p").text() ?: "" + thumbnail_url = element.selectFirst(".post-thumbnail figure img")?.let { getImageUrl(it) } } } return AnimesPage(animeList, nextPage) @@ -99,12 +101,20 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() { return SAnime.create().apply { title = document.selectFirst("main .entry-header .entry-title")?.text() ?: "" description = document.select("main .entry-content p").joinToString { it.text() } - thumbnail_url = document.selectFirst("main .post-thumbnail img")?.attr("abs:src") + thumbnail_url = document.selectFirst("main .post-thumbnail img")?.let { getImageUrl(it) } genre = document.select("main .entry-content .tagcloud a").joinToString { it.text() } status = SAnime.UNKNOWN } } + private fun getImageUrl(element: Element): String? { + return when { + element.hasAttr("data-src") -> element.attr("abs:data-src") + element.hasAttr("src") -> element.attr("abs:src") + else -> null + } + } + override fun episodeListParse(response: Response): List { val document = response.asJsoup() val referer = response.request.url.toString() @@ -218,7 +228,7 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() { val key = src.split("/").last() src = "https://fastream.to/embed-$key.html" } - FastreamExtractor(client, headers).videosFromUrl(src).also(videoList::addAll) + FastreamExtractor(client, headers).videosFromUrl(src, needsSleep = false).also(videoList::addAll) } if (src.contains("upstream")) { diff --git a/src/es/tioanime/build.gradle b/src/es/tioanime/build.gradle index 82fd1e3fa..086733049 100644 --- a/src/es/tioanime/build.gradle +++ b/src/es/tioanime/build.gradle @@ -5,13 +5,14 @@ ext { extName = 'TioanimeH' pkgNameSuffix = 'es.tioanimeh' extClass = '.TioanimeHFactory' - extVersionCode = 13 + extVersionCode = 14 libVersion = '13' } dependencies { implementation(project(':lib-yourupload-extractor')) implementation(project(':lib-okru-extractor')) + implementation(project(':lib-voe-extractor')) } diff --git a/src/es/tioanime/src/eu/kanade/tachiyomi/animeextension/es/tioanimeh/TioanimeH.kt b/src/es/tioanime/src/eu/kanade/tachiyomi/animeextension/es/tioanimeh/TioanimeH.kt index eee6918ff..32cc04a67 100644 --- a/src/es/tioanime/src/eu/kanade/tachiyomi/animeextension/es/tioanimeh/TioanimeH.kt +++ b/src/es/tioanime/src/eu/kanade/tachiyomi/animeextension/es/tioanimeh/TioanimeH.kt @@ -4,6 +4,7 @@ import android.app.Application import android.content.SharedPreferences import androidx.preference.ListPreference import androidx.preference.PreferenceScreen +import eu.kanade.tachiyomi.animeextension.es.tioanimeh.extractors.VidGuardExtractor import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.model.AnimeFilter import eu.kanade.tachiyomi.animesource.model.AnimeFilterList @@ -12,6 +13,7 @@ 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.okruextractor.OkruExtractor +import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.util.asJsoup @@ -28,7 +30,7 @@ open class TioanimeH(override val name: String, override val baseUrl: String) : override val lang = "es" - override val supportsLatest = false + override val supportsLatest = true override val client: OkHttpClient = network.cloudflareClient @@ -36,6 +38,21 @@ open class TioanimeH(override val name: String, override val baseUrl: String) : Injekt.get().getSharedPreferences("source_$id", 0x0000) } + companion object { + private const val PREF_QUALITY_KEY = "preferred_quality" + private const val PREF_QUALITY_DEFAULT = "1080" + private val QUALITY_LIST = arrayOf("1080", "720", "480", "360") + + private const val PREF_SERVER_KEY = "preferred_server" + private const val PREF_SERVER_DEFAULT = "Voe" + private val SERVER_LIST = arrayOf( + "YourUpload", + "Voe", + "VidGuard", + "Okru", + ) + } + override fun popularAnimeSelector(): String = "ul.animes.list-unstyled.row li.col-6.col-sm-4.col-md-3.col-xl-2" override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/directorio?p=$page") @@ -84,14 +101,10 @@ open class TioanimeH(override val name: String, override val baseUrl: String) : val serverName = servers[0] val serverUrl = servers[1].replace("\\/", "/") when (serverName.lowercase()) { - "okru" -> { - OkruExtractor(client).videosFromUrl(serverUrl).map { vid -> videoList.add(vid) } - } - "yourupload" -> { - videoList.addAll( - YourUploadExtractor(client).videoFromUrl(serverUrl, headers = headers), - ) - } + "voe" -> VoeExtractor(client).videosFromUrl(serverUrl).let(videoList::addAll) + "vidguard" -> VidGuardExtractor(client).videosFromUrl(serverUrl).let(videoList::addAll) + "okru" -> OkruExtractor(client).videosFromUrl(serverUrl).let(videoList::addAll) + "yourupload" -> YourUploadExtractor(client).videoFromUrl(serverUrl, headers = headers).let(videoList::addAll) } } @@ -105,24 +118,15 @@ open class TioanimeH(override val name: String, override val baseUrl: String) : override fun videoFromElement(element: Element) = throw Exception("not used") override fun List