mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
sora: added Pobmovies
This commit is contained in:
parent
04f6dac736
commit
e7777079e6
5 changed files with 115 additions and 28 deletions
|
@ -1,7 +1,7 @@
|
||||||
import org.jetbrains.kotlin.konan.properties.Properties
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
|
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 141
|
version = 142
|
||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
|
|
@ -1013,16 +1013,18 @@ object SoraExtractor : SoraStream() {
|
||||||
val animeId =
|
val animeId =
|
||||||
app.get("https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/anilist/anime/${aniId ?: return}.json")
|
app.get("https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/anilist/anime/${aniId ?: return}.json")
|
||||||
.parsedSafe<MALSyncResponses>()?.pages?.zoro?.keys?.map { it }
|
.parsedSafe<MALSyncResponses>()?.pages?.zoro?.keys?.map { it }
|
||||||
|
val headers = mapOf(
|
||||||
|
"X-Requested-With" to "XMLHttpRequest",
|
||||||
|
)
|
||||||
animeId?.apmap { id ->
|
animeId?.apmap { id ->
|
||||||
val episodeId = app.get("$zoroAPI/ajax/v2/episode/list/${id ?: return@apmap}")
|
val episodeId = app.get("$zoroAPI/ajax/v2/episode/list/${id ?: return@apmap}", headers = headers)
|
||||||
.parsedSafe<ZoroResponses>()?.html?.let {
|
.parsedSafe<ZoroResponses>()?.html?.let {
|
||||||
Jsoup.parse(it)
|
Jsoup.parse(it)
|
||||||
}?.select("div.ss-list a")?.find { it.attr("data-number") == "${episode ?: 1}" }
|
}?.select("div.ss-list a")?.find { it.attr("data-number") == "${episode ?: 1}" }
|
||||||
?.attr("data-id")
|
?.attr("data-id")
|
||||||
|
|
||||||
val servers =
|
val servers =
|
||||||
app.get("$zoroAPI/ajax/v2/episode/servers?episodeId=${episodeId ?: return@apmap}")
|
app.get("$zoroAPI/ajax/v2/episode/servers?episodeId=${episodeId ?: return@apmap}", headers = headers)
|
||||||
.parsedSafe<ZoroResponses>()?.html?.let { Jsoup.parse(it) }
|
.parsedSafe<ZoroResponses>()?.html?.let { Jsoup.parse(it) }
|
||||||
?.select("div.item.server-item")?.map {
|
?.select("div.item.server-item")?.map {
|
||||||
Triple(
|
Triple(
|
||||||
|
@ -1034,7 +1036,7 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
servers?.apmap servers@{ server ->
|
servers?.apmap servers@{ server ->
|
||||||
val iframe =
|
val iframe =
|
||||||
app.get("$zoroAPI/ajax/v2/episode/sources?id=${server.second ?: return@servers}")
|
app.get("$zoroAPI/ajax/v2/episode/sources?id=${server.second ?: return@servers}", headers = headers)
|
||||||
.parsedSafe<ZoroResponses>()?.link ?: return@servers
|
.parsedSafe<ZoroResponses>()?.link ?: return@servers
|
||||||
val audio = if (server.third == "sub") "Raw" else "English Dub"
|
val audio = if (server.third == "sub") "Raw" else "English Dub"
|
||||||
if (server.first == "Vidstreaming" || server.first == "Vidcloud") {
|
if (server.first == "Vidstreaming" || server.first == "Vidcloud") {
|
||||||
|
@ -1260,20 +1262,13 @@ object SoraExtractor : SoraStream() {
|
||||||
extractMirrorUHD(bitLink, base)
|
extractMirrorUHD(bitLink, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
val tags =
|
val tags = getUhdTags(quality)
|
||||||
Regex("\\d{3,4}[Pp]\\.?(.*?)\\[").find(quality)?.groupValues?.getOrNull(1)
|
val qualities = getIndexQuality(quality)
|
||||||
?.replace(".", " ")?.trim()
|
val size = getIndexSize(quality)
|
||||||
?: ""
|
|
||||||
val qualities =
|
|
||||||
Regex("(\\d{3,4})[Pp]").find(quality)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
|
||||||
?: Qualities.Unknown.value
|
|
||||||
val size =
|
|
||||||
Regex("(?i)\\[(\\S+\\s?(gb|mb))[]/]").find(quality)?.groupValues?.getOrNull(1)
|
|
||||||
?.let { "[$it]" } ?: quality
|
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
"UHDMovies",
|
"UHDMovies",
|
||||||
"UHDMovies $tags $size",
|
"UHDMovies $tags [$size]",
|
||||||
downloadLink ?: return@apmap,
|
downloadLink ?: return@apmap,
|
||||||
"",
|
"",
|
||||||
qualities
|
qualities
|
||||||
|
@ -1285,6 +1280,72 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun invokePobmovies(
|
||||||
|
title: String? = null,
|
||||||
|
year: Int? = null,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
|
val detailDoc = app.get("$pobmoviesAPI/${title.createSlug()}-$year").document
|
||||||
|
val iframeList = detailDoc.select("div.entry-content p").map { it }
|
||||||
|
.filter { it.text().filterIframe(year = year, title = title) }.mapNotNull {
|
||||||
|
it.text() to it.nextElementSibling()?.select("a")?.attr("href")
|
||||||
|
}.filter { it.second?.contains(Regex("(https:)|(http:)")) == true }
|
||||||
|
|
||||||
|
val sources = mutableListOf<Pair<String, String?>>()
|
||||||
|
if (iframeList.any {
|
||||||
|
it.first.contains(
|
||||||
|
"2160p",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
sources.addAll(iframeList.filter {
|
||||||
|
it.first.contains(
|
||||||
|
"2160p",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
sources.add(iframeList.first {
|
||||||
|
it.first.contains(
|
||||||
|
"1080p",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
sources.addAll(iframeList.filter { it.first.contains("1080p", true) })
|
||||||
|
}
|
||||||
|
|
||||||
|
sources.apmap { (name, link) ->
|
||||||
|
if (link.isNullOrEmpty()) return@apmap
|
||||||
|
val videoLink = when {
|
||||||
|
link.contains("gdtot") -> {
|
||||||
|
val gdBotLink = extractGdbot(link)
|
||||||
|
extractGdflix(gdBotLink ?: return@apmap)
|
||||||
|
}
|
||||||
|
link.contains("gdflix") -> {
|
||||||
|
extractGdflix(link)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
return@apmap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val tags = getUhdTags(name)
|
||||||
|
val qualities = getIndexQuality(name)
|
||||||
|
val size = getIndexSize(name)
|
||||||
|
callback.invoke(
|
||||||
|
ExtractorLink(
|
||||||
|
"Pobmovies",
|
||||||
|
"Pobmovies $tags [${size}]",
|
||||||
|
videoLink ?: return@apmap,
|
||||||
|
"",
|
||||||
|
qualities
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun invokeFwatayako(
|
suspend fun invokeFwatayako(
|
||||||
imdbId: String? = null,
|
imdbId: String? = null,
|
||||||
season: Int? = null,
|
season: Int? = null,
|
||||||
|
|
|
@ -50,6 +50,7 @@ import com.hexated.SoraExtractor.invokeShivamhw
|
||||||
import com.hexated.SoraExtractor.invokeSmashyStream
|
import com.hexated.SoraExtractor.invokeSmashyStream
|
||||||
import com.hexated.SoraExtractor.invokeDumpStream
|
import com.hexated.SoraExtractor.invokeDumpStream
|
||||||
import com.hexated.SoraExtractor.invokeEmovies
|
import com.hexated.SoraExtractor.invokeEmovies
|
||||||
|
import com.hexated.SoraExtractor.invokePobmovies
|
||||||
import com.hexated.SoraExtractor.invokeTvMovies
|
import com.hexated.SoraExtractor.invokeTvMovies
|
||||||
import com.hexated.SoraExtractor.invokeUhdmovies
|
import com.hexated.SoraExtractor.invokeUhdmovies
|
||||||
import com.hexated.SoraExtractor.invokeVitoenMovies
|
import com.hexated.SoraExtractor.invokeVitoenMovies
|
||||||
|
@ -129,6 +130,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val ridomoviesAPI = "https://ridomovies.pw"
|
const val ridomoviesAPI = "https://ridomovies.pw"
|
||||||
const val navyAPI = "https://navy-issue-i-239.site"
|
const val navyAPI = "https://navy-issue-i-239.site"
|
||||||
const val emoviesAPI = "https://emovies.si"
|
const val emoviesAPI = "https://emovies.si"
|
||||||
|
const val pobmoviesAPI = "https://pobmovies.cam"
|
||||||
|
|
||||||
// INDEX SITE
|
// INDEX SITE
|
||||||
const val blackMoviesAPI = "https://dl.blacklistedbois.workers.dev/0:"
|
const val blackMoviesAPI = "https://dl.blacklistedbois.workers.dev/0:"
|
||||||
|
@ -806,8 +808,11 @@ open class SoraStream : TmdbProvider() {
|
||||||
invokeNavy(res.imdbId, res.season, res.episode, callback)
|
invokeNavy(res.imdbId, res.season, res.episode, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeEmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
|
if (!res.isAnime) invokeEmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
if(!res.isAnime && res.season == null) invokePobmovies(res.title, res.year, callback)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -290,7 +290,7 @@ class SoraStreamLite : SoraStream() {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeEmovies(
|
if (!res.isAnime) invokeEmovies(
|
||||||
res.title,
|
res.title,
|
||||||
res.year,
|
res.year,
|
||||||
res.season,
|
res.season,
|
||||||
|
|
|
@ -111,7 +111,12 @@ data class FilmxyCookies(
|
||||||
val wSec: String? = null,
|
val wSec: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun String.filterIframe(seasonNum: Int?, lastSeason: Int?, year: Int?, title: String?): Boolean {
|
fun String.filterIframe(
|
||||||
|
seasonNum: Int? = null,
|
||||||
|
lastSeason: Int? = null,
|
||||||
|
year: Int?,
|
||||||
|
title: String?
|
||||||
|
): Boolean {
|
||||||
val slug = title.createSlug()
|
val slug = title.createSlug()
|
||||||
val dotSlug = slug?.replace("-", ".")
|
val dotSlug = slug?.replace("-", ".")
|
||||||
val spaceSlug = slug?.replace("-", " ")
|
val spaceSlug = slug?.replace("-", " ")
|
||||||
|
@ -271,8 +276,8 @@ suspend fun extractDrivebot(url: String): String? {
|
||||||
|
|
||||||
suspend fun extractGdflix(url: String): String? {
|
suspend fun extractGdflix(url: String): String? {
|
||||||
val iframeGdflix =
|
val iframeGdflix =
|
||||||
app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(GDFlix Direct)")
|
if (!url.contains("gdflix")) app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(GDFlix Direct)")
|
||||||
?.attr("href") ?: return null
|
?.attr("href") ?: return null else url
|
||||||
val base = getBaseUrl(iframeGdflix)
|
val base = getBaseUrl(iframeGdflix)
|
||||||
|
|
||||||
val req = app.get(iframeGdflix).document.selectFirst("script:containsData(replace)")?.data()
|
val req = app.get(iframeGdflix).document.selectFirst("script:containsData(replace)")?.data()
|
||||||
|
@ -586,7 +591,10 @@ suspend fun getDumpIdAndType(title: String?, year: Int?, season: Int?): Pair<Str
|
||||||
it.name?.contains(
|
it.name?.contains(
|
||||||
"$title",
|
"$title",
|
||||||
true
|
true
|
||||||
) == true && (it.releaseTime == "$year" || it.name.contains("Season $season", true)) && it.domainType == 1
|
) == true && (it.releaseTime == "$year" || it.name.contains(
|
||||||
|
"Season $season",
|
||||||
|
true
|
||||||
|
)) && it.domainType == 1
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
it.name?.contains(Regex("(?i)$title\\s?($season|${season.toRomanNumeral()}|Season\\s$season)")) == true && it.releaseTime == "$year" && it.domainType == 1
|
it.name?.contains(Regex("(?i)$title\\s?($season|${season.toRomanNumeral()}|Season\\s$season)")) == true && it.releaseTime == "$year" && it.domainType == 1
|
||||||
|
@ -744,7 +752,11 @@ suspend fun bypassTechmny(url: String): String? {
|
||||||
val thirdPage = secondPage.getNextTechPage().text
|
val thirdPage = secondPage.getNextTechPage().text
|
||||||
val goToken = thirdPage.substringAfter("?go=").substringBefore("\"")
|
val goToken = thirdPage.substringAfter("?go=").substringBefore("\"")
|
||||||
val tokenUrl = "$postUrl?go=$goToken"
|
val tokenUrl = "$postUrl?go=$goToken"
|
||||||
val headers = mapOf("Cookie" to "$goToken=${secondPage.select("form#landing input[name=_wp_http2]").attr("value")}")
|
val headers = mapOf(
|
||||||
|
"Cookie" to "$goToken=${
|
||||||
|
secondPage.select("form#landing input[name=_wp_http2]").attr("value")
|
||||||
|
}"
|
||||||
|
)
|
||||||
Pair(tokenUrl, headers)
|
Pair(tokenUrl, headers)
|
||||||
}
|
}
|
||||||
val driveUrl =
|
val driveUrl =
|
||||||
|
@ -1279,6 +1291,12 @@ fun String.getFileSize(): Float? {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getUhdTags(str: String?): String {
|
||||||
|
return Regex("\\d{3,4}[Pp]\\.?(.*?)\\[").find(str ?: "")?.groupValues?.getOrNull(1)
|
||||||
|
?.replace(".", " ")?.trim()
|
||||||
|
?: str ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
fun getIndexQualityTags(str: String?, fullTag: Boolean = false): String {
|
fun getIndexQualityTags(str: String?, fullTag: Boolean = false): String {
|
||||||
return if (fullTag) Regex("(?i)(.*)\\.(?:mkv|mp4|avi)").find(str ?: "")?.groupValues?.get(1)
|
return if (fullTag) Regex("(?i)(.*)\\.(?:mkv|mp4|avi)").find(str ?: "")?.groupValues?.get(1)
|
||||||
?.trim() ?: str ?: "" else Regex("(?i)\\d{3,4}[pP]\\.?(.*?)\\.(mkv|mp4|avi)").find(
|
?.trim() ?: str ?: "" else Regex("(?i)\\d{3,4}[pP]\\.?(.*?)\\.(mkv|mp4|avi)").find(
|
||||||
|
@ -1486,12 +1504,13 @@ fun getBaseUrl(url: String): String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isUpcoming(dateString: String?) : Boolean {
|
fun isUpcoming(dateString: String?): Boolean {
|
||||||
if(dateString == null) return false
|
if (dateString == null) return false
|
||||||
val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
||||||
val dateTime = format.parse(dateString)?.time ?: return false
|
val dateTime = format.parse(dateString)?.time ?: return false
|
||||||
return unixTimeMS < dateTime
|
return unixTimeMS < dateTime
|
||||||
}
|
}
|
||||||
|
|
||||||
fun decode(input: String): String = URLDecoder.decode(input, "utf-8")
|
fun decode(input: String): String = URLDecoder.decode(input, "utf-8")
|
||||||
|
|
||||||
fun encode(input: String): String = URLEncoder.encode(input, "utf-8").replace("+", "%20")
|
fun encode(input: String): String = URLEncoder.encode(input, "utf-8").replace("+", "%20")
|
||||||
|
@ -2021,8 +2040,9 @@ object DumpUtils {
|
||||||
return app.custom(
|
return app.custom(
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
requestBody = if(method == "POST") params.toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) else null,
|
requestBody = if (method == "POST") params.toJson()
|
||||||
params = if(method == "GET") params else emptyMap(),
|
.toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) else null,
|
||||||
|
params = if (method == "GET") params else emptyMap(),
|
||||||
headers = createHeaders(params)
|
headers = createHeaders(params)
|
||||||
).parsedSafe<HashMap<String, String>>()?.get("data").let {
|
).parsedSafe<HashMap<String, String>>()?.get("data").let {
|
||||||
cryptoHandler(
|
cryptoHandler(
|
||||||
|
@ -2062,7 +2082,8 @@ object DumpUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAesKey(): String? {
|
private fun getAesKey(): String? {
|
||||||
val publicKey = RSAEncryptionHelper.getPublicKeyFromString(BuildConfig.DUMP_KEY) ?: return null
|
val publicKey =
|
||||||
|
RSAEncryptionHelper.getPublicKeyFromString(BuildConfig.DUMP_KEY) ?: return null
|
||||||
return RSAEncryptionHelper.encryptText(deviceId, publicKey)
|
return RSAEncryptionHelper.encryptText(deviceId, publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue