fix(tr/hdfilmcehennemi): Update baseUrl + add a new extractor (#2884)
This commit is contained in:
parent
6486f5c9b8
commit
5d62c958cf
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ext {
|
ext {
|
||||||
extName = 'HDFilmCehennemi'
|
extName = 'HDFilmCehennemi'
|
||||||
extClass = '.HDFilmCehennemi'
|
extClass = '.HDFilmCehennemi'
|
||||||
extVersionCode = 9
|
extVersionCode = 10
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)!!
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
@ -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('"')
|
||||||
|
}
|
@ -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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -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('"', "")
|
||||||
|
@ -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(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user