fix(tr/hdfilmcehennemi): Update baseUrl + add a new extractor (#2884)

This commit is contained in:
Claudemirovsky 2024-02-08 10:46:14 -03:00 committed by GitHub
parent 6486f5c9b8
commit 5d62c958cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 82 additions and 79 deletions

View File

@ -58,7 +58,7 @@ object Unpacker {
} }
} }
private val wordRegex by lazy { Regex("""\w+""") } private val wordRegex by lazy { Regex("""[0-9A-Za-z]+""") }
private fun parseRadix62(str: String): Int { private fun parseRadix62(str: String): Int {
var result = 0 var result = 0

View File

@ -13,7 +13,7 @@
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data <data
android:host="www.hdfilmcehennemi.de" android:host="www.hdfilmcehennemi.us"
android:pathPattern="/..*" android:pathPattern="/..*"
android:scheme="https" /> android:scheme="https" />
</intent-filter> </intent-filter>

View File

@ -1,7 +1,7 @@
ext { ext {
extName = 'HDFilmCehennemi' extName = 'HDFilmCehennemi'
extClass = '.HDFilmCehennemi' extClass = '.HDFilmCehennemi'
extVersionCode = 9 extVersionCode = 10
isNsfw = true isNsfw = true
} }

View File

@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi
import android.app.Application import android.app.Application
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors.RapidrameExtractor import eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors.CloseloadExtractor
import eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors.VidmolyExtractor import eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors.VidmolyExtractor
import eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors.XBetExtractor import eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors.XBetExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
@ -22,7 +22,6 @@ import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import eu.kanade.tachiyomi.util.parallelMapBlocking import eu.kanade.tachiyomi.util.parallelMapBlocking
import eu.kanade.tachiyomi.util.parseAs import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.Request import okhttp3.Request
@ -31,7 +30,6 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
@ -39,7 +37,7 @@ class HDFilmCehennemi : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val name = "HDFilmCehennemi" override val name = "HDFilmCehennemi"
override val baseUrl = "https://www.hdfilmcehennemi.fun" override val baseUrl = "https://www.hdfilmcehennemi.us"
override val lang = "tr" override val lang = "tr"
@ -49,8 +47,6 @@ class HDFilmCehennemi : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
.add("Referer", "$baseUrl/") .add("Referer", "$baseUrl/")
.add("Origin", baseUrl) .add("Origin", baseUrl)
private val json: Json by injectLazy()
private val preferences by lazy { private val preferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
} }
@ -225,8 +221,8 @@ class HDFilmCehennemi : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
// ============================ Video Links ============================= // ============================ Video Links =============================
private val vidmolyExtractor by lazy { VidmolyExtractor(client, headers) } private val vidmolyExtractor by lazy { VidmolyExtractor(client, headers) }
private val rapidrameExtractor by lazy { RapidrameExtractor(client, headers, json) } private val closeloadExtractor by lazy { CloseloadExtractor(client, headers) }
private val xbetExtractor by lazy { XBetExtractor(client, headers, json) } private val xbetExtractor by lazy { XBetExtractor(client, headers) }
override fun videoListParse(response: Response): List<Video> { override fun videoListParse(response: Response): List<Video> {
val doc = response.asJsoup() val doc = response.asJsoup()
@ -235,12 +231,13 @@ class HDFilmCehennemi : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
.drop(1) .drop(1)
.parallelMapBlocking { client.newCall(GET(it.absUrl("href") + "/")).await().asJsoup() } .parallelMapBlocking { client.newCall(GET(it.absUrl("href") + "/")).await().asJsoup() }
.let { listOf(doc) + it } .let { listOf(doc) + it }
.mapNotNull { it.selectFirst("div.card-video > iframe")?.attr("data-src") } .mapNotNull { it.selectFirst("div.card-video > iframe") }
.map { it.attr("data-src").ifBlank { it.attr("src") } }
.filter(String::isNotBlank) .filter(String::isNotBlank)
.parallelCatchingFlatMapBlocking { url -> .parallelCatchingFlatMapBlocking { url ->
when { when {
url.contains("https://closeload") -> closeloadExtractor.videosFromUrl(url)
url.contains("vidmoly") -> vidmolyExtractor.videosFromUrl(url) url.contains("vidmoly") -> vidmolyExtractor.videosFromUrl(url)
url.contains("$baseUrl/playerr") -> rapidrameExtractor.videosFromUrl(url)
url.contains("trstx.org") -> xbetExtractor.videosFromUrl(url) url.contains("trstx.org") -> xbetExtractor.videosFromUrl(url)
else -> emptyList() else -> emptyList()
} }
@ -279,7 +276,6 @@ class HDFilmCehennemi : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
} }
// ============================= Utilities ============================== // ============================= Utilities ==============================
override fun List<Video>.sort(): List<Video> { override fun List<Video>.sort(): List<Video> {
val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!! val quality = preferences.getString(PREF_QUALITY_KEY, PREF_QUALITY_DEFAULT)!!

View File

@ -8,7 +8,7 @@ import android.util.Log
import kotlin.system.exitProcess import kotlin.system.exitProcess
/** /**
* Springboard that accepts https://www.hdfilmcehennemi.de/<item> intents * Springboard that accepts https://www.hdfilmcehennemi.us/<item> intents
* and redirects them to the main Aniyomi process. * and redirects them to the main Aniyomi process.
*/ */
class HDFilmCehennemiUrlActivity : Activity() { class HDFilmCehennemiUrlActivity : Activity() {

View File

@ -0,0 +1,62 @@
package eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors
import android.util.Base64
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.unpacker.Unpacker
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
class CloseloadExtractor(private val client: OkHttpClient, private val headers: Headers) {
suspend fun videosFromUrl(url: String): List<Video> {
val doc = client.newCall(GET(url, headers)).await().asJsoup()
val script = doc.selectFirst("script:containsData(eval):containsData(PlayerInit)")?.data()
?: return emptyList()
val unpackedScript = Unpacker.unpack(script).takeIf(String::isNotEmpty)
?: return emptyList()
val varName = unpackedScript.substringAfter("atob(").substringBefore(")")
val playlistUrl = unpackedScript.getProperty("$varName=")
.let { String(Base64.decode(it, Base64.DEFAULT)) }
val hostUrl = "https://" + url.toHttpUrl().host
val videoHeaders = headers.newBuilder()
.set("Referer", url)
.set("origin", hostUrl)
.build()
runCatching { tryAjaxPost(unpackedScript, hostUrl) }
val subtitles = doc.select("track[src]").map {
Track(it.absUrl("src"), it.attr("label").ifEmpty { it.attr("srclang") })
}
return listOf(Video(playlistUrl, "Closeload", playlistUrl, videoHeaders, subtitleTracks = subtitles))
}
private suspend fun tryAjaxPost(script: String, hostUrl: String) {
val hash = script.getProperty("hash:")
val url = script.getProperty("url:").let {
when {
it.startsWith("//") -> "https:$it"
it.startsWith("/") -> "https://" + hostUrl + it
!it.startsWith("https://") -> "https://$it"
else -> it
}
}
val body = FormBody.Builder().add("hash", hash).build()
client.newCall(POST(url, headers, body)).await().close()
}
private fun String.getProperty(before: String) =
substringAfter("$before\"").substringBefore('"')
}

View File

@ -1,54 +0,0 @@
package eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors
import android.util.Base64
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.lib.unpacker.Unpacker
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.Headers
import okhttp3.OkHttpClient
@Serializable
data class TrackDto(val label: String = "", val file: String, val kind: String)
class RapidrameExtractor(
private val client: OkHttpClient,
private val headers: Headers,
private val json: Json,
) {
private val playlistUtils by lazy { PlaylistUtils(client, headers) }
fun videosFromUrl(url: String): List<Video> {
val doc = client.newCall(GET(url, headers)).execute().asJsoup()
val script = doc.selectFirst("script:containsData(eval):containsData(file_link)")?.data()
?: return emptyList()
val unpackedScript = Unpacker.unpack(script).takeIf(String::isNotEmpty)
?: return emptyList()
val subtitles = (script.substringAfter("tracks: ", "").substringBefore("],", "") + "]")
.let { list ->
runCatching {
val baseUrl = headers["Origin"]!!
json.decodeFromString<List<TrackDto>>(list)
.filter { it.kind.equals("captions") }
.map { Track(baseUrl + it.file, it.label.replace("Forced", "Türkçe")) }
}.getOrElse { emptyList() }
}
val playlistUrl = unpackedScript.substringAfter('"').substringBefore('"')
.let { String(Base64.decode(it, Base64.DEFAULT)) }
return playlistUtils.extractFromHls(
playlistUrl,
referer = url,
videoNameGen = { "Rapidrame - $it" },
subtitleList = subtitles,
)
}
}

View File

@ -3,14 +3,15 @@ package eu.kanade.tachiyomi.animeextension.tr.hdfilmcehennemi.extractors
import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.await
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
class VidmolyExtractor(private val client: OkHttpClient, private val headers: Headers) { class VidmolyExtractor(private val client: OkHttpClient, private val headers: Headers) {
private val playlistUtils by lazy { PlaylistUtils(client, headers) } private val playlistUtils by lazy { PlaylistUtils(client, headers) }
fun videosFromUrl(url: String): List<Video> { suspend fun videosFromUrl(url: String): List<Video> {
val body = client.newCall(GET(url, headers)).execute() val body = client.newCall(GET(url, headers)).await()
.body.string() .body.string()
val playlistUrl = body.substringAfter("file:\"", "").substringBefore('"', "") val playlistUrl = body.substringAfter("file:\"", "").substringBefore('"', "")

View File

@ -4,10 +4,10 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parseAs import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -15,13 +15,11 @@ import okhttp3.OkHttpClient
class XBetExtractor( class XBetExtractor(
private val client: OkHttpClient, private val client: OkHttpClient,
private val headers: Headers, private val headers: Headers,
private val json: Json,
) { ) {
private val playlistUtils by lazy { PlaylistUtils(client, headers) } private val playlistUtils by lazy { PlaylistUtils(client, headers) }
fun videosFromUrl(url: String): List<Video> { suspend fun videosFromUrl(url: String): List<Video> {
val doc = client.newCall(GET(url, headers)).execute() val doc = client.newCall(GET(url, headers)).await().asJsoup()
.asJsoup()
val script = doc.selectFirst("script:containsData(playerConfigs =)")?.data() val script = doc.selectFirst("script:containsData(playerConfigs =)")?.data()
?: return emptyList() ?: return emptyList()
@ -36,12 +34,12 @@ class XBetExtractor(
.set("Origin", host) .set("Origin", host)
.build() .build()
val postRes = client.newCall(POST(host + postPath, postHeaders)).execute() val postRes = client.newCall(POST(host + postPath, postHeaders)).await()
.parseAs<List<VideoItemDto>> { it.replace("[],", "") } .parseAs<List<VideoItemDto>> { it.replace("[],", "") }
return postRes.flatMap { video -> return postRes.flatMap { video ->
runCatching { runCatching {
val playlistUrl = client.newCall(POST(host + video.path, postHeaders)).execute() val playlistUrl = client.newCall(POST(host + video.path, postHeaders)).await()
.body.string() .body.string()
playlistUtils.extractFromHls( playlistUtils.extractFromHls(