Skip to content

Commit

Permalink
fix(pt/vizer): Fixed pt/Vizer videos empty (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dark25 authored Oct 18, 2024
1 parent 25e922a commit 288a0c4
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 72 deletions.
10 changes: 10 additions & 0 deletions lib/fireplayer-extractor/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
id("lib-android")
}

dependencies {
implementation("dev.datlag.jsunpacker:jsunpacker:1.0.1") {
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
}
implementation(project(":lib:playlist-utils"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package eu.kanade.tachiyomi.lib.fireplayerextractor

import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient

class FireplayerExtractor(
private val client: OkHttpClient,
private val defaultHost: String? = null,
) {
fun videosFromUrl(
url: String,
videoNameGen: (String) -> String = { quality -> quality },
videoHost: String? = null,
): List<Video> {
val host = videoHost ?: defaultHost ?: "https://${url.toHttpUrl().host}"

val headers = Headers.Builder()
.set("X-Requested-With", "XMLHttpRequest")
.set("Referer", host)
.set("Origin", "https://${host.toHttpUrl().host}")
.set("X-Requested-With", "XMLHttpRequest")
.build()

var id = url.substringAfterLast("/")

if (id.length < 32) {
val doc = client.newCall(GET(url, headers)).execute().asJsoup()

val script =
doc.selectFirst("script:containsData(eval):containsData(p,a,c,k,e,d)")?.data()
?.let(JsUnpacker::unpackAndCombine)
?: doc.selectFirst("script:containsData(FirePlayer)")?.data()

if (script?.contains("FirePlayer(") == true) {
id = script.substringAfter("FirePlayer(\"").substringBefore('"')
}
}

val postUrl = "$host/player/index.php?data=$id&do=getVideo"
val body = FormBody.Builder()
.add("hash", id)
.add("r", "")
.build()

val masterUrl = client.newCall(POST(postUrl, headers, body = body)).execute()
.body.string()
.substringAfter("securedLink\":\"")
.substringBefore('"')
.replace("\\", "")

val playlistUtils = PlaylistUtils(client, headers)

return playlistUtils.extractFromHls(masterUrl, videoNameGen = videoNameGen)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ class MixDropExtractor(private val client: OkHttpClient) {
externalSubs: List<Track> = emptyList(),
referer: String = DEFAULT_REFERER,
): List<Video> {
val headers = Headers.headersOf("Referer", referer)
val headers = Headers.headersOf(
"Referer",
referer,
"User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
)
val doc = client.newCall(GET(url, headers)).execute().asJsoup()
val unpacked = doc.selectFirst("script:containsData(eval):containsData(MDCore)")
?.data()
Expand Down
5 changes: 4 additions & 1 deletion src/pt/vizer/build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
ext {
extName = 'Vizer.tv'
extClass = '.Vizer'
extVersionCode = 16
extVersionCode = 17
isNsfw = true
}

apply from: "$rootDir/common.gradle"

dependencies {
implementation(project(':lib:fireplayer-extractor'))
implementation(project(':lib:mixdrop-extractor'))
implementation(project(':lib:playlist-utils'))
implementation(project(':lib:streamtape-extractor'))
implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.SearchItemDto
import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.SearchResultDto
import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.VideoDto
import eu.kanade.tachiyomi.animeextension.pt.vizer.dto.VideoListDto
import eu.kanade.tachiyomi.animeextension.pt.vizer.extractors.WarezExtractor
import eu.kanade.tachiyomi.animeextension.pt.vizer.interceptor.WebViewResolver
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.AnimeHttpSource
import eu.kanade.tachiyomi.lib.fireplayerextractor.FireplayerExtractor
import eu.kanade.tachiyomi.lib.mixdropextractor.MixDropExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.network.GET
Expand All @@ -41,7 +42,7 @@ class Vizer : ConfigurableAnimeSource, AnimeHttpSource() {

override val name = "Vizer.tv"

override val baseUrl = "https://vizertv.in"
override val baseUrl = "https://novizer.com"
private val apiUrl = "$baseUrl/includes/ajax"

override val lang = "pt-BR"
Expand All @@ -58,6 +59,8 @@ class Vizer : ConfigurableAnimeSource, AnimeHttpSource() {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}

private val webViewResolver by lazy { WebViewResolver(headers) }

// ============================== Popular ===============================
override fun popularAnimeRequest(page: Int): Request {
val pageType = preferences.getString(PREF_POPULAR_PAGE_KEY, PREF_POPULAR_PAGE_DEFAULT)!!
Expand Down Expand Up @@ -176,7 +179,7 @@ class Vizer : ConfigurableAnimeSource, AnimeHttpSource() {
val response = episodesClient.newCall(apiRequest("getEpisodes=$id")).execute()
val episodes = response.parseAs<EpisodeListDto>().episodes
.values
.filter { it.released }
.filter { it.released === true }
.map {
SEpisode.create().apply {
name = "$sname: Ep ${it.name}".run {
Expand Down Expand Up @@ -243,20 +246,24 @@ class Vizer : ConfigurableAnimeSource, AnimeHttpSource() {

private val mixdropExtractor by lazy { MixDropExtractor(client) }
private val streamtapeExtractor by lazy { StreamTapeExtractor(client) }
private val warezExtractor by lazy { WarezExtractor(client, headers) }
private val fireplayerExtractor by lazy { FireplayerExtractor(client) }

private fun getVideosFromObject(videoObj: VideoDto): List<Video> {
val hosters = videoObj.hosters ?: return emptyList()

val langPrefix = if (videoObj.lang == "1") "LEG" else "DUB"

return hosters.iterator().flatMap { (name, status) ->
if (status != 3) return@flatMap emptyList()
// Always try the warezcdn
if (status != 3 && name != "warezcdn") return@flatMap emptyList()
val url = getPlayerUrl(videoObj.id, name)
if (url.isNullOrBlank()) {
return emptyList()
}
when (name) {
"mixdrop" -> mixdropExtractor.videosFromUrl(url, langPrefix)
"streamtape" -> streamtapeExtractor.videosFromUrl(url, "StreamTape($langPrefix)")
"warezcdn" -> warezExtractor.videosFromUrl(url, langPrefix)
"warezcdn" -> fireplayerExtractor.videosFromUrl(url, videoNameGen = { "WarezCDN($langPrefix) - $it" })
else -> emptyList()
}
}
Expand Down Expand Up @@ -295,17 +302,8 @@ class Vizer : ConfigurableAnimeSource, AnimeHttpSource() {
// ============================= Utilities ==============================
private val noRedirectClient = client.newBuilder().followRedirects(false).build()

private fun getPlayerUrl(id: String, name: String): String {
val req = GET("$baseUrl/embed/getPlay.php?id=$id&sv=$name", headers)
return if (name == "warezcdn") {
val res = noRedirectClient.newCall(req).execute()
res.close()
res.headers["location"]!!
} else {
val res = client.newCall(req).execute()
val body = res.body.string()
body.substringAfter("location.href=\"", "").substringBefore("\";", "")
}
private fun getPlayerUrl(id: String, name: String): String? {
return webViewResolver.getUrl("$baseUrl/embed/getEmbed.php?id=$id&sv=$name", "$baseUrl/termos")
}

private fun apiRequest(body: String): Request {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class HostersDto(
object BooleanSerializer : JsonTransformingSerializer<Boolean>(Boolean.serializer()) {
override fun transformDeserialize(element: JsonElement): JsonElement {
require(element is JsonPrimitive)
return if (element.jsonPrimitive.isString) {
return if (element.jsonPrimitive.isString && element.jsonPrimitive.content == "true") {
JsonPrimitive(true)
} else {
JsonPrimitive(element.jsonPrimitive.booleanOrNull ?: false)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package eu.kanade.tachiyomi.animeextension.pt.vizer.interceptor

import android.annotation.SuppressLint
import android.app.Application
import android.os.Handler
import android.os.Looper
import android.util.Log
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 globalHeaders: Headers) {
private val context: Application by injectLazy()
private val handler by lazy { Handler(Looper.getMainLooper()) }
private val tag by lazy { javaClass.simpleName }

@SuppressLint("SetJavaScriptEnabled")
fun getUrl(origRequestUrl: String, baseUrl: String): String? {
val latch = CountDownLatch(1)
var webView: WebView? = null
var result: String? = null

handler.post {
val webview = WebView(context)
webView = webview
with(webview.settings) {
javaScriptEnabled = true
domStorageEnabled = true
databaseEnabled = true
useWideViewPort = false
loadWithOverviewMode = false
userAgentString = globalHeaders["User-Agent"]
}
webview.webViewClient = object : WebViewClient() {
override fun shouldInterceptRequest(
view: WebView,
request: WebResourceRequest,
): WebResourceResponse? {
val url = request.url.toString()
Log.d(tag, "Checking url $url")
if (VIDEO_REGEX.containsMatchIn(url)) {
result = url
latch.countDown()
}
return super.shouldInterceptRequest(view, request)
}

override fun onPageFinished(view: WebView?, url: String?) {
Log.d(tag, "onPageFinished $url")
super.onPageFinished(view, url)

view?.evaluateJavascript("document.body.innerHTML += '<iframe src=\"" + origRequestUrl + "\" scrolling=\"no\" frameborder=\"0\" allowfullscreen=\"\" webkitallowfullscreen=\"\" mozallowfullscreen=\"\"></iframe>'") {}
}
}

webView?.loadUrl(baseUrl)
}

latch.await(TIMEOUT_SEC, TimeUnit.SECONDS)

handler.post {
webView?.stopLoading()
webView?.destroy()
webView = null
}
return result
}

companion object {
const val TIMEOUT_SEC: Long = 25
private val VIDEO_REGEX by lazy { Regex("//(mixdrop|streamtape|warezcdn)|/video/") }
}
}

0 comments on commit 288a0c4

Please sign in to comment.