From 694a8b4aba9e4173296e830a50a6a41f05fb759a Mon Sep 17 00:00:00 2001 From: WebDitto Date: Thu, 17 Oct 2024 16:37:13 -0300 Subject: [PATCH 1/7] fix(pt/megaflix): Fixed pt/MegaFlix source (#311) --- src/pt/megaflix/build.gradle | 2 +- .../animeextension/pt/megaflix/Megaflix.kt | 39 ++++++++--- .../pt/megaflix/MegaflixUrlActivity.kt | 2 +- .../pt/megaflix/WebViewResolver.kt | 69 +++++++++++++++++++ .../megaflix/extractors/MegaflixExtractor.kt | 2 +- 5 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/WebViewResolver.kt diff --git a/src/pt/megaflix/build.gradle b/src/pt/megaflix/build.gradle index ede65fca..ff685850 100644 --- a/src/pt/megaflix/build.gradle +++ b/src/pt/megaflix/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Megaflix' extClass = '.Megaflix' - extVersionCode = 19 + extVersionCode = 20 isNsfw = true } diff --git a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/Megaflix.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/Megaflix.kt index edb032cb..e64a0785 100644 --- a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/Megaflix.kt +++ b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/Megaflix.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.animeextension.pt.megaflix import android.app.Application -import android.util.Base64 import androidx.preference.ListPreference import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.animeextension.pt.megaflix.extractors.MegaflixExtractor @@ -14,6 +13,7 @@ import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor import eu.kanade.tachiyomi.lib.mixdropextractor.MixDropExtractor +import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor import eu.kanade.tachiyomi.lib.vidhideextractor.VidHideExtractor @@ -35,7 +35,7 @@ class Megaflix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { override val name = "Megaflix" - override val baseUrl = "https://megaflix.co" + override val baseUrl = "https://megaflix.ac" override val lang = "pt-BR" @@ -73,7 +73,11 @@ class Megaflix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { override fun latestUpdatesNextPageSelector() = "div.nav-links > a:containsOwn(PRÓXIMO)" // =============================== Search =============================== - override suspend fun getSearchAnime(page: Int, query: String, filters: AnimeFilterList): AnimesPage { + override suspend fun getSearchAnime( + page: Int, + query: String, + filters: AnimeFilterList, + ): AnimesPage { return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler val path = query.removePrefix(PREFIX_SEARCH) client.newCall(GET("$baseUrl/$path")) @@ -135,6 +139,7 @@ class Megaflix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { episode_number = 1F }, ) + else -> seasons.parallelFlatMapBlocking(::episodesFromSeason).reversed() } } @@ -163,12 +168,14 @@ class Megaflix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { .parallelCatchingFlatMapBlocking { element -> val language = element.text().substringAfter("-") val id = element.attr("href") - val url = element.parents().get(5)?.selectFirst("div$id a") - ?.run { - attr("href") - .substringAfter("token=") - .let { String(Base64.decode(it, Base64.DEFAULT)) } - .substringAfter("||") + val url = element.closest("body")?.selectFirst("div$id iframe") + ?.let { + val iframeUrl = it.attr("src") + client.newCall(GET(iframeUrl, headers)) + .execute() + .asJsoup() + .selectFirst("iframe") + ?.attr("src") } ?: return@parallelCatchingFlatMapBlocking emptyList() getVideoList(url, language) @@ -176,6 +183,9 @@ class Megaflix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { } /*--------------------------------Video extractors------------------------------------*/ + private val webViewResolver by lazy { WebViewResolver() } + private val playlistUtils by lazy { PlaylistUtils(client, headers) } + private val mixdropExtractor by lazy { MixDropExtractor(client) } private val streamtapeExtractor by lazy { StreamTapeExtractor(client) } private val megaflixExtractor by lazy { MegaflixExtractor(client, headers) } @@ -193,6 +203,17 @@ class Megaflix : ConfigurableAnimeSource, ParsedAnimeHttpSource() { arrayOf("filemoon", "moonplayer").any(url) -> filemoonExtractor.videosFromUrl(url, prefix = "$language Filemoon:") arrayOf("vidhide", "vid.").any(url) -> vidHideExtractor.videosFromUrl(url, videoNameGen = { "$language VidHide:$it" }) arrayOf("wishembed", "streamwish", "strwish", "wish", "jwplayerhls").any(url) -> streamWishExtractor.videosFromUrl(url, videoNameGen = { "$language StreamWish:$it" }) + arrayOf("fembedder").any(url) -> { + val webViewResult = webViewResolver.getUrl(url, headers) + if (webViewResult.isBlank()) { + return emptyList() + } + return if (webViewResult.contains("m3u8")) { + playlistUtils.extractFromHls(webViewResult) + } else { + listOf(Video(url, "Default", url)) + } + } else -> emptyList() } } diff --git a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixUrlActivity.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixUrlActivity.kt index f3f5edff..cec9a93d 100644 --- a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixUrlActivity.kt +++ b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/MegaflixUrlActivity.kt @@ -8,7 +8,7 @@ import android.util.Log import kotlin.system.exitProcess /** - * Springboard that accepts https://megaflix.co// intents + * Springboard that accepts https://megaflix.ac// intents * and redirects them to the main Aniyomi process. */ class MegaflixUrlActivity : Activity() { diff --git a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/WebViewResolver.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/WebViewResolver.kt new file mode 100644 index 00000000..a1c377b0 --- /dev/null +++ b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/WebViewResolver.kt @@ -0,0 +1,69 @@ +package eu.kanade.tachiyomi.animeextension.pt.megaflix + +import android.annotation.SuppressLint +import android.app.Application +import android.os.Handler +import android.os.Looper +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import android.webkit.WebViewClient +import okhttp3.Headers +import uy.kohesive.injekt.injectLazy +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +class WebViewResolver() { + private val context: Application by injectLazy() + private val handler by lazy { Handler(Looper.getMainLooper()) } + + @SuppressLint("SetJavaScriptEnabled") + fun getUrl(origRequestUrl: String, origRequestheader: Headers): String { + val latch = CountDownLatch(1) + var webView: WebView? = null + var resultUrl = "" + val headers = origRequestheader.toMultimap().mapValues { it.value.getOrNull(0) ?: "" }.toMutableMap() + + handler.post { + val webview = WebView(context) + webView = webview + with(webview.settings) { + javaScriptEnabled = true + domStorageEnabled = true + databaseEnabled = true + useWideViewPort = false + loadWithOverviewMode = false + userAgentString = origRequestheader["User-Agent"] + } + webview.webViewClient = object : WebViewClient() { + override fun shouldInterceptRequest( + view: WebView, + request: WebResourceRequest, + ): WebResourceResponse? { + val url = request.url.toString() + if (VIDEO_REGEX.containsMatchIn(url)) { + resultUrl = url + latch.countDown() + } + return super.shouldInterceptRequest(view, request) + } + } + + webView?.loadUrl(origRequestUrl, headers) + } + + latch.await(TIMEOUT_SEC, TimeUnit.SECONDS) + + handler.post { + webView?.stopLoading() + webView?.destroy() + webView = null + } + return resultUrl + } + + companion object { + const val TIMEOUT_SEC: Long = 20 + private val VIDEO_REGEX by lazy { Regex("\\.(mp4|m3u8)") } + } +} diff --git a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/extractors/MegaflixExtractor.kt b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/extractors/MegaflixExtractor.kt index a7a4e96e..849511d8 100644 --- a/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/extractors/MegaflixExtractor.kt +++ b/src/pt/megaflix/src/eu/kanade/tachiyomi/animeextension/pt/megaflix/extractors/MegaflixExtractor.kt @@ -21,7 +21,7 @@ class MegaflixExtractor(private val client: OkHttpClient, private val headers: H return playlistUtils.extractFromHls( playlistUrl, - "https://megaflix.co", + "https://megaflix.ac", videoNameGen = { "Megaflix($lang) - $it" }, ) } -- 2.47.2 From 2eac3267938e1c2bb35567d5544375da1b179b71 Mon Sep 17 00:00:00 2001 From: WebDitto Date: Thu, 17 Oct 2024 16:37:33 -0300 Subject: [PATCH 2/7] fix(pt/Anitube): Added option to disable File4Go mirror (#309) --- src/pt/anitube/build.gradle | 2 +- .../animeextension/pt/anitube/Anitube.kt | 20 +++++++++- .../extractors/AnitubeDownloadExtractor.kt | 37 +++++++++++++------ 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/pt/anitube/build.gradle b/src/pt/anitube/build.gradle index a468f926..519039b0 100644 --- a/src/pt/anitube/build.gradle +++ b/src/pt/anitube/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Anitube' extClass = '.Anitube' - extVersionCode = 19 + extVersionCode = 20 } apply from: "$rootDir/common.gradle" diff --git a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt index 9d5e4d02..4f5f8ae6 100644 --- a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt +++ b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/Anitube.kt @@ -4,6 +4,7 @@ import android.app.Application import androidx.preference.EditTextPreference import androidx.preference.ListPreference import androidx.preference.PreferenceScreen +import androidx.preference.SwitchPreferenceCompat import eu.kanade.tachiyomi.animeextension.pt.anitube.extractors.AnitubeDownloadExtractor import eu.kanade.tachiyomi.animeextension.pt.anitube.extractors.AnitubeExtractor import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource @@ -199,8 +200,10 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { val links = mutableListOf(document.location()) - document.selectFirst("div.abaItemDown > a")?.attr("href")?.let { - links.add(it) + if (preferences.getBoolean(PREF_FILE4GO_KEY, PREF_FILE4GO_DEFAULT)!!) { + document.selectFirst("div.abaItemDown > a")?.attr("href")?.let { + links.add(it) + } } val epName = document.selectFirst("meta[itemprop=name]")!!.attr("content") @@ -235,6 +238,16 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { } }.also(screen::addPreference) + SwitchPreferenceCompat(screen.context).apply { + key = PREF_FILE4GO_KEY + title = "Usar File4Go como mirror" + setDefaultValue(PREF_FILE4GO_DEFAULT) + summary = PREF_FILE4GO_SUMMARY + setOnPreferenceChangeListener { _, newValue -> + preferences.edit().putBoolean(key, newValue as Boolean).commit() + } + }.also(screen::addPreference) + // Auth Code EditTextPreference(screen.context).apply { key = PREF_AUTHCODE_KEY @@ -308,6 +321,9 @@ class Anitube : ConfigurableAnimeSource, ParsedAnimeHttpSource() { private const val PREF_AUTHCODE_KEY = "authcode" private const val PREF_AUTHCODE_SUMMARY = "Código de Autenticação" private const val PREF_AUTHCODE_DEFAULT = "" + private const val PREF_FILE4GO_KEY = "file4go" + private const val PREF_FILE4GO_SUMMARY = "Usar File4Go como mirror" + private const val PREF_FILE4GO_DEFAULT = false private const val PREF_QUALITY_KEY = "preferred_quality" private const val PREF_QUALITY_TITLE = "Qualidade preferida" private const val PREF_QUALITY_DEFAULT = "HD" diff --git a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeDownloadExtractor.kt b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeDownloadExtractor.kt index 2d0bb1d6..a5e864ce 100644 --- a/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeDownloadExtractor.kt +++ b/src/pt/anitube/src/eu/kanade/tachiyomi/animeextension/pt/anitube/extractors/AnitubeDownloadExtractor.kt @@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.parallelMapNotNullBlocking import okhttp3.FormBody import okhttp3.Headers +import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient class AnitubeDownloadExtractor( @@ -20,23 +21,33 @@ class AnitubeDownloadExtractor( private fun videosFromFile4Go(url: String, quality: String): Video? { Log.d(tag, "Checking download for $url") - val docDownload = client.newCall(GET(url)).execute().asJsoup() - val form = - docDownload.selectFirst("button.download")?.closest("form") + val newHeaders = headers.newBuilder() + .set("Referer", "https://${url.toHttpUrl().host}/") + .add("Accept", "*/*") + .add("Cache-Control", "no-cache") + .add("Pragma", "no-cache") + .add("Connection", "keep-alive") + .add("Sec-Fetch-Dest", "empty") + .add("Sec-Fetch-Mode", "cors") + .add("Sec-Fetch-Site", "same-site") + .build() - if (form == null) { - Log.d(tag, "Download form not found for $url") - return null - } + val id = url.split('/').last() + val idusuario = + client.newCall(GET("$ADS_URL/file4go.php", headers = newHeaders)) + .execute() + .body.string() + .substringAfter("\"publicidade\"") + .substringAfter('"') + .substringBefore('"') val body = FormBody.Builder().apply { - form.select("input[name]").forEach { - add(it.attr("name"), it.attr("value")) - } + add("id", id) + add("idusuario", idusuario) }.build() - val postUrl = form.attr("action") + val postUrl = "https://www.file4go.net/getdownload_new_anitube.php" val postHeaders = headers.newBuilder() .set("Referer", url) @@ -95,4 +106,8 @@ class AnitubeDownloadExtractor( return videosFromDownloadPage(url, epName) } + + companion object { + private const val ADS_URL = "https://ads.anitube.vip" + } } -- 2.47.2 From 88361e0e354c9d0d944d332fa1de08a7658c9208 Mon Sep 17 00:00:00 2001 From: WebDitto Date: Thu, 17 Oct 2024 16:37:52 -0300 Subject: [PATCH 3/7] fix(pt/pobreflix): Fixed pt/PobreFlix source (fix #258) (#310) --- .../FireplayerExtractor.kt | 1 + src/pt/pobreflix/build.gradle | 5 +- .../animeextension/pt/pobreflix/Pobreflix.kt | 45 +++++++-------- .../extractors/FireplayerExtractor.kt | 56 ------------------- .../extractors/PlayerFlixExtractor.kt | 35 ++++++++++++ .../extractors/SuperFlixExtractor.kt | 2 +- 6 files changed, 63 insertions(+), 81 deletions(-) delete mode 100644 src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/FireplayerExtractor.kt create mode 100644 src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/extractors/PlayerFlixExtractor.kt diff --git a/lib/fireplayer-extractor/src/main/java/eu/kanade/tachiyomi/lib/fireplayerextractor/FireplayerExtractor.kt b/lib/fireplayer-extractor/src/main/java/eu/kanade/tachiyomi/lib/fireplayerextractor/FireplayerExtractor.kt index f9735def..4afa8d95 100644 --- a/lib/fireplayer-extractor/src/main/java/eu/kanade/tachiyomi/lib/fireplayerextractor/FireplayerExtractor.kt +++ b/lib/fireplayer-extractor/src/main/java/eu/kanade/tachiyomi/lib/fireplayerextractor/FireplayerExtractor.kt @@ -36,6 +36,7 @@ class FireplayerExtractor( val script = doc.selectFirst("script:containsData(eval):containsData(p,a,c,k,e,d)")?.data() + ?.replace(Regex("[\\u00E0-\\u00FC]"), "-") // Fix a bug in JsUnpacker with accents ?.let(JsUnpacker::unpackAndCombine) ?: doc.selectFirst("script:containsData(FirePlayer)")?.data() diff --git a/src/pt/pobreflix/build.gradle b/src/pt/pobreflix/build.gradle index ec1d8eb7..5b4d764a 100644 --- a/src/pt/pobreflix/build.gradle +++ b/src/pt/pobreflix/build.gradle @@ -2,8 +2,8 @@ ext { extName = 'Pobreflix' extClass = '.Pobreflix' themePkg = 'dooplay' - baseUrl = 'https://pobreflix1.art' - overrideVersionCode = 10 + baseUrl = 'https://pobreflix.global' + overrideVersionCode = 11 isNsfw = true } @@ -11,6 +11,7 @@ apply from: "$rootDir/common.gradle" dependencies { implementation(project(":lib:filemoon-extractor")) + implementation(project(":lib:fireplayer-extractor")) implementation(project(":lib:streamwish-extractor")) implementation(project(":lib:streamtape-extractor")) implementation(project(":lib:playlist-utils")) diff --git a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/Pobreflix.kt b/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/Pobreflix.kt index 30783608..c1159018 100644 --- a/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/Pobreflix.kt +++ b/src/pt/pobreflix/src/eu/kanade/tachiyomi/animeextension/pt/pobreflix/Pobreflix.kt @@ -1,23 +1,25 @@ package eu.kanade.tachiyomi.animeextension.pt.pobreflix import android.util.Base64 -import eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors.FireplayerExtractor import eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors.MyStreamExtractor +import eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors.PlayerFlixExtractor import eu.kanade.tachiyomi.animeextension.pt.pobreflix.extractors.SuperFlixExtractor import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor +import eu.kanade.tachiyomi.lib.fireplayerextractor.FireplayerExtractor import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor import eu.kanade.tachiyomi.multisrc.dooplay.DooPlay import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.util.asJsoup +import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Response class Pobreflix : DooPlay( "pt-BR", "Pobreflix", - "https://pobreflix1.art", + "https://pobreflix.global", ) { // ============================== Popular =============================== override fun popularAnimeSelector() = "div.featured div.poster" @@ -26,53 +28,52 @@ class Pobreflix : DooPlay( override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/series/page/$page/", headers) // ============================ Video Links ============================= - private val embedplayerExtractor by lazy { FireplayerExtractor(client) } - private val brbeastExtractor by lazy { FireplayerExtractor(client, "https://brbeast.com") } - private val superembedsExtractor by lazy { FireplayerExtractor(client, "https://superembeds.com/") } + private val fireplayerExtractor by lazy { FireplayerExtractor(client) } private val filemoonExtractor by lazy { FilemoonExtractor(client) } private val mystreamExtractor by lazy { MyStreamExtractor(client, headers) } private val streamtapeExtractor by lazy { StreamTapeExtractor(client) } private val streamwishExtractor by lazy { StreamWishExtractor(client, headers) } + private val playerflixExtractor by lazy { PlayerFlixExtractor(client, headers, ::genericExtractor) } private val superflixExtractor by lazy { SuperFlixExtractor(client, headers, ::genericExtractor) } private val supercdnExtractor by lazy { SuperFlixExtractor(client, headers, ::genericExtractor, "https://supercdn.org") } override fun videoListParse(response: Response): List